Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

## Selecting & Dragging a Node (or other object) with the mouse

by Nathan Randall

Using the mouseMovedEvent, redButtonPressedEvent & redButtonReleasedEvent methods, selecting a node (or any object) and moving it across the screen is very easy.

First, you're going to want to use the point class for the position of the node. This allows us to find out whether or not we're clicking on the node very easily, since adding/subtracting to a point adds & subtracts both x & y values:
```| pt |
pt := 50@50.
pt := pt + 25.
```

Now if you were to print pt, it would display 75@75. The same is true for subtraction as you would expect.

The other variable that we'll need for a node is a boolean for whether or not the node is selected. A simple getter & setter are all you'll need for this.

In order to drag the node, we will need a Boolean to determine if we are dragging the node or just moving the mouse around. This is an instance variable in the controller. Again, a simple getter & setter are needed.

Now, if you have your node displayed on the canvas, you're going to use the redButtonPressedEvent to select the node.

In this code example, the nodes were in a Dictionary which were part of a matrix that was in a graph that was part of our model.....

We're going to loop through the dictionary of nodes and determine if the mouse click occured within the given range to a nodes current position. (Here the range is +/- 26 since our nodes were circles with radius of 25.) In the inner most IF statement we returned true to exit out of the loop to prevent selecting more than one node at a time. We set the selected node as being selected and also set dragging to true so that we can drag the node to its new location.
```redButtonPressedEvent: anEvent
|pt|
pt := self sensor cursorPointFor: anEvent.
model graph matrix nodes  keysAndValuesDo: [:keys :value |
(pt >= (value position - 26 ) )
ifTrue: [
(pt <= (value position +26 ) )
ifTrue:[value selected: true.
dragging := true.
^true.
].
]
].
```

Once the node is selected and dragging true we can move it to its new location. We'll do this with the mouseMovedEvent.

So, while dragging is true, get the current point from the mouse, set that point to the position of the node that is currently selected and update the view while doing so:
```mouseMovedEvent: anEvent
|pt|
dragging ifTrue:[
pt := self sensor mousePointFor: anEvent.
model graph matrix nodes keysAndValuesDo: [:keys :value |
(value selected = true)
ifTrue: [ value position: pt. view model changed. ].
].
].
```

Once we release the mouse button we want the node to be de-selected and we want it to stop being dragged. We'll do this with the redButtonReleasedEvent.
```redButtonReleasedEvent: anEvent
|pt|
pt := self sensor cursorPointFor: anEvent.
model graph matrix nodes keysAndValuesDo: [:keys :value |
(value selected == true)
ifTrue: [ value position: pt. value selected: false. dragging := false. ].
].
view model changed.
```

We've set the node selected value and dragging to false and updated the view to reflect where we released the node.