开发者

scala swing: draggable / resizable component trait

I'm looking for a scala trait that I can mix in to a scala.swing.Component that will allow that component to be positioned and resized using mouse i开发者_如何学编程nput.

Ideally it would add little boxes as "handles" to indicate to the user that the component can be resized:

scala swing: draggable / resizable component trait

I feel like this is a fairly common task, and there should be some traits out there that support it.


I'm using these in my current project. You probably need to replace the Vector library with your own and add implicit defs. Or use Point/Dimension from swing. The Components need to be in a panel which allows custom positions and sizes, like NullPanel from http://dgronau.wordpress.com/2010/08/28/eine-frage-des-layouts/

trait Movable extends Component{
    var dragstart:Vec2i = null
    listenTo(mouse.clicks, mouse.moves)
    reactions += {
        case e:MouseDragged =>
            if( dragstart != null )
                peer.setLocation(location - dragstart + e.point)
        case e:MousePressed =>
            this match {
                case component:Resizable =>
                    if( component.resizestart == null )
                        dragstart = e.point
                case _ =>
                    dragstart = e.point
                     
            }
        case e:MouseReleased =>
            dragstart = null    
    }
}

trait Resizable extends Component{
    var resizestart:Vec2i = null
    var oldsize = Vec2i(0)
    def resized(delta:Vec2i) {}
    listenTo(mouse.clicks, mouse.moves)
    reactions += {
        case e:MouseDragged =>
            if( resizestart != null ){
                val delta = e.point - resizestart
                peer.setSize(max(oldsize + delta, minimumSize))

                oldsize += delta
                resizestart += delta

                resized(delta)
                revalidate
            }
        case e:MousePressed =>
            if( size.width - e.point.x < 15
             && size.height - e.point.y < 15 ){
                resizestart = e.point
                oldsize = size
            
                this match {
                    case component:Movable =>
                        component.dragstart = null
                    case _ =>
                }
            }
        case e:MouseReleased =>
            resizestart = null
    }
}


The only Component I know of that is Dragable and resizeable is the InternalFrame on the JDesktop. here is an example:

import swing._
import event._

import javax.swing.{UIManager,JComponent}
import javax.swing.KeyStroke.getKeyStroke
import java.awt.{Graphics2D,Graphics}

object InternalFrameDemo extends SimpleSwingApplication{
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName)

    val top = new MainFrame{
        title = "InternalFrameDemo"
        preferredSize = new Dimension(640,480)
        val desktop = new javax.swing.JDesktopPane

        val jc = new JComponent{
            override def paint(g:Graphics){
                import g._
                drawLine(0,0,20,20)
                drawLine(0,20,20,0)
                println("yay draw")
            }

            setVisible(true)
        }

        desktop add jc

        contents = Component.wrap(desktop)

        menuBar = new MenuBar{
            contents += new Menu("Document"){
                mnemonic = Key.D

                contents += new MenuItem("New"){
                    mnemonic = Key.N
                    action = new Action("new"){
                        def apply = createFrame
                        accelerator = Some(getKeyStroke("alt N"))
                    }
                }

                contents += new MenuItem("Quit"){
                    mnemonic = Key.Q
                    action = new Action("quit"){
                        def apply(){
                            quit()
                        }
                        accelerator = Some(getKeyStroke("alt Q"))
                    }
                }
            }
        }

        def createFrame{
            val newFrame = MyInternalFrame()
            newFrame setVisible true
            desktop add newFrame
            newFrame setSelected true

        }
    }
}

import javax.swing.{JDesktopPane,JInternalFrame}
import collection.mutable.ArrayBuffer

object MyInternalFrame{
    var openFrameCount = 0;
    val xOffset, yOffset = 30;

    def apply() = {
        openFrameCount += 1
        val jframe = new javax.swing.JInternalFrame("Document #" + openFrameCount,true,true,true,true)

        jframe.setSize(300,300)
        jframe.setLocation(xOffset*openFrameCount,yOffset*openFrameCount)

        jframe //Component.wrap(jframe)
    }
}

but both JInternalFrame and JDesktop are not integrated in the scala swing package and need to be wrapped manually.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜