m := BorderedMorph new.
m on: #startDrag send: #grabMorph: to: m.
m on: #click send: #value to:[self inform:'you clicked'].
m openInWorld
When you drag the morph you drag it. When you click you click.
---
Any plain Morph (one that doesn't override handlesMouseDown: and
mouseDown: et. al.) can be sensitized to mouse clicks. Just say:
myMorph on: #mouseDown send: #doSomething to: someObject.
Same for the events mouseMove, mouseStillDown, mouseUp, mouseEnter,
mouseLeave, mouseEnterDragging, mouseLeaveDragging, click,
doubleClick, doubleClickTimeout, startDrag, keyStroke, and gesture.
---
> If an area is covered by a morph and a sumborph which one will
> receive the mouse events ?
Safer than playing with mouseDownPriority (which I found to be very
tricky) is to just lock the submorphs and then you'll get the events
in the parent. You can then explicitly call the submorphs mouseDown:
etc. methods.
for extra credit: study this message trace to understand what happens
when you click on a Morph:
m _ Morph new.
sm _ Morph new extent: 20@20; color: Color red.
sm center: m center.
m addMorph: sm.
m openInWorld.
evt _ MouseButtonEvent new
setType: #mouseDown
position: sm center
which: 0
buttons: 0
hand: ActiveHand
stamp: Time millisecondClockValue.
evt toggleRedButton.
MessageTally tallySends: [ ActiveHand handleEvent: evt ].
No. You can separately receive click and startDrag events. You get a
click before you get a doubleClick event. Try this in a Workspace:
m _ Morph new.
m on: #click send: #value to: [ m color: Color red ].
m on: #startDrag send: #value to: [ m color: Color orange. ActiveHand
grabMorph: m ].
m on: #doubleClick send: #value to: [ m color: Color green ].
m openInHand.
> I don't want to use the halo for dragging.
That's understandable.
> Some things I don't understand yet:
>
> do submorphs always appear *above* its owning morph ?
Depends on how you implement fullDrawOn: . You could re-implement it
and go the other way; the default version in Morph draws the parent
first.
> If an area is covered by a morph and a sumborph which one will
> receive the mouse events ?
Depends. There is mouseDownPriority that can be used to tweak this.
> Any plain Morph (one that doesn't override handlesMouseDown: and
> mouseDown: et. al.) can be sensitized to mouse clicks. Just say:
>
> myMorph on: #mouseDown send: #doSomething to: someObject.
Just to clarify:
The #doSomething selector can actually have an arity (number of
arguments) of 0, 1, 2, or 3. So you can pass the event itself, the
morph that received the event, and a single parameter. But there is
only one parameter shared between all the event types. To pass a
parameter you use the form #on:send:to:withValue: .
These are passed as:
arity = 0 ifTrue:
[^ recipient perform: selector].
arity = 1 ifTrue:
[^ recipient perform: selector with: event].
arity = 2 ifTrue:
[^ recipient perform: selector with: event with: sourceMorph].
arity = 3 ifTrue:
[^ recipient perform: selector with: valueParameter with: event
with: sourceMorph].
Unfortunately, the error message in
EventHandler>>on:send:to:withValue: that says 'Warning: value
parameters are passed as last of 3 arguments' is incorrect, as is the
class comment in EventHandler which says it's:
mouseDownRecipient perform: mouseDownSelector3 with: event with:
targetMorph with: valueParameter