Squeak SmalltalkJoker Squeak Smalltalk : Morphic : prevnext Drag Vs Click

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