The Trunk: Morphic-mt.1732.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Morphic-mt.1732.mcz

commits-2
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1732.mcz

==================== Summary ====================

Name: Morphic-mt.1732
Author: mt
Time: 2 March 2021, 5:06:00.167687 pm
UUID: cb835785-768b-fd48-8eef-af27742a70dc
Ancestors: Morphic-mt.1731

Encapsulates most of the logic for halo invocation (and transfer) from Morph and PasteUpMorph into a new MorphicHaloDispatcher.

Hopefully no new bugs introduced. Yet, there is still this issue with protruding submorphs due to the logic in #dispatchHalo:createFor: ... :-)

PasteUpMorph #tryInvokeHalo: --> #dispatchHalo:createFor:
Morph #transferHalo:from: --> #dispatchHalo:transferFrom:

It always starts in #dispatchHalo:with: --- either called from the world's event filter or the current halo's mouse-down handling code.

=============== Diff against Morphic-mt.1731 ===============

Item was removed:
- ----- Method: Morph>>addHalo:from: (in category 'halos and balloon help') -----
- addHalo: evt from: formerHaloOwner
- "Transfer a halo from the former halo owner to the receiver"
- ^self addHalo: evt!

Item was added:
+ ----- Method: Morph>>defaultHaloDispatcher (in category 'halos and balloon help') -----
+ defaultHaloDispatcher
+
+ ^ MorphicHaloDispatcher new!

Item was removed:
- ----- Method: Morph>>invokeHaloOrMove: (in category 'meta-actions') -----
- invokeHaloOrMove: anEvent
- "Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph."
- | h tfm doNotDrag |
- h := anEvent hand halo.
- "Prevent wrap around halo transfers originating from throwing the event back in"
- doNotDrag := false.
- h ifNotNil:[
- (h innerTarget == self) ifTrue:[doNotDrag := true].
- (h innerTarget hasOwner: self) ifTrue:[doNotDrag := true].
- (self hasOwner: h target) ifTrue:[doNotDrag := true]].
-
- tfm := (self transformedFrom: nil) inverseTransformation.
-
- "cmd-drag on flexed morphs works better this way"
- h := self addHalo: (anEvent transformedBy: tfm).
- h ifNil: [^ self].
- doNotDrag ifTrue:[^self].
- "Initiate drag transition if requested"
- anEvent hand
- waitForClicksOrDrag: h
- event: (anEvent transformedBy: tfm)
- selectors: { nil. nil. nil. #startDragTarget:. }
- threshold: HandMorph dragThreshold.
- "Pass focus explicitly here"
- anEvent hand newMouseFocus: h.
- "Reset temporary cursors to make available halo interaction visible."
- anEvent hand showTemporaryCursor: nil.!

Item was added:
+ ----- Method: Morph>>transferHalo: (in category 'halos and balloon help') -----
+ transferHalo: event
+
+ ^ self transferHalo: event using: self defaultHaloDispatcher!

Item was removed:
- ----- Method: Morph>>transferHalo:from: (in category 'halos and balloon help') -----
- transferHalo: event from: formerHaloOwner
- "Progressively transfer the halo to the next likely recipient"
- | localEvt w target |
-
- self flag: #workAround. "For halo's distinction between 'target' and 'innerTarget' we need to bypass any renderers."
- (formerHaloOwner == self and:[self isRenderer and:[self wantsHaloFromClick not]]) ifTrue:[
- event shiftPressed ifTrue:[
- target := owner.
- localEvt := event transformedBy: (self transformedFrom: owner).
- ] ifFalse:[
- target := self renderedMorph.
- localEvt := event transformedBy: (target transformedFrom: self).
- ].
- ^target transferHalo: localEvt from: target].
-
- " formerHaloOwner == self ifTrue:[^ self removeHalo]."
-
- "Never transfer halo to top-most world"
- (self isWorldMorph and:[owner isNil]) ifFalse:[
- (self wantsHaloFromClick and:[formerHaloOwner ~~ self])
- ifTrue:[^self addHalo: event from: formerHaloOwner]].
-
- event shiftPressed ifTrue:[
- "Pass it outwards"
- owner ifNotNil:[^owner transferHalo: event from: formerHaloOwner].
- "We're at the top level; throw the event back in to find recipient"
- formerHaloOwner removeHalo.
- ^self processEvent: event copy resetHandlerFields.
- ].
- self submorphsDo:[:m|
- localEvt := event transformedBy: (m transformedFrom: self).
- (m fullContainsPoint: localEvt position)
- ifTrue:[^m transferHalo: event from: formerHaloOwner].
- ].
- "We're at the bottom most level; throw the event back up to the root to find recipient"
- formerHaloOwner removeHalo.
-
- Preferences maintainHalos ifFalse:[
- (w := self world) ifNil: [ ^self ].
- localEvt := event transformedBy: (self transformedFrom: w) inverseTransformation.
- ^w processEvent: localEvt resetHandlerFields.
- ].
- !

Item was added:
+ ----- Method: Morph>>transferHalo:using: (in category 'halos and balloon help') -----
+ transferHalo: event using: dispatcher
+
+ ^ dispatcher dispatchHalo: event with: self!

Item was added:
+ Object subclass: #MorphicHaloDispatcher
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Morphic-Events'!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>dispatchHalo:createFor: (in category 'dispatching') -----
+ dispatchHalo: anEvent createFor: aMorph
+ "Invoke halos around the top-most world container at aUserInputEvent's #position.  If it was already halo'd, zero-in on its next inward component morph at that position.  Holding Shift during the click reverses this traversal order."
+
+ | stack innermost haloTarget |
+ "the stack is the top-most morph to bottom-most."
+ stack := (aMorph morphsAt: anEvent position unlocked: true) select:
+ [ : each | each wantsHaloFromClick or: [ each handlesMouseDown: anEvent ] ].
+ innermost := anEvent hand halo
+ ifNil: [ stack first ]
+ ifNotNil:
+ [ : existingHalo |
+ (stack := stack copyWithout: existingHalo) "No halos on halos"
+ detect: [ : each | each owner == aMorph ]
+ ifFound:
+ [ : worldContainer | "Is existingHalo's target part of the same worldContainer as the morph clicked?"
+ (existingHalo target withAllOwners includes: worldContainer)
+ ifTrue: [ "same hierarchy, let #transferHalo: continue to handle it for now."  ^ false ]
+ ifFalse:
+ [ "different hierarchy, remove + add."
+ anEvent hand removeHalo.
+ anEvent shiftPressed
+ ifTrue: [ stack first ]
+ ifFalse: [ worldContainer ] ] ]
+ ifNone: [ "existingHalo is on the World, defer to #transferHalo: for now." ^ false ] ].
+
+ "If modifier key is pressed, start at innermost (the target), otherwise the outermost (direct child of the world (self))."
+ haloTarget := (innermost == aMorph or: [anEvent shiftPressed])
+ ifTrue: [ innermost ]
+ ifFalse:
+ [ "Find the outermost owner that wants it."
+ innermost withAllOwners reversed allButFirst
+ detect: [ : each | each wantsHaloFromClick ]
+ ifNone: [ "haloTarget has its own mouseDown handler, don't halo."  ^ false ] ].
+ "Now that we have the haloTarget, show the halo."
+ self invokeHaloOrMove: anEvent on: haloTarget.
+ ^ true!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>dispatchHalo:transferFrom: (in category 'dispatching') -----
+ dispatchHalo: event transferFrom: morph
+ "Progressively transfer the halo to the next likely recipient"
+
+ ^ event shiftPressed
+ ifTrue: [self dispatchHalo: event transferOutwardsFrom: morph]
+ ifFalse: [self dispatchHalo: event transferInwardsFrom: morph]!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>dispatchHalo:transferInwardsFrom: (in category 'dispatching') -----
+ dispatchHalo: event transferInwardsFrom: currentTarget
+
+ | localEvent world |
+ currentTarget submorphsDo: [:nextTarget |
+ localEvent := event transformedBy: (nextTarget transformedFrom: currentTarget).
+ (nextTarget fullContainsPoint: localEvent position) ifTrue: [
+ ^ nextTarget wantsHaloFromClick
+ ifTrue: [self invokeHalo: localEvent on: nextTarget]
+ ifFalse: [self dispatchHalo: localEvent transferInwardsFrom: nextTarget]]].
+
+ "We're at the bottom most level; throw the event back up to the root to find recipient"
+ event hand removeHalo.
+ Preferences maintainHalos ifFalse: [
+ (world := currentTarget world) ifNil: [ ^ false ].
+ localEvent := event transformedBy: (currentTarget transformedFrom: world) inverseTransformation.
+ world processEvent: localEvent resetHandlerFields].
+
+ ^ false!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>dispatchHalo:transferOutwardsFrom: (in category 'dispatching') -----
+ dispatchHalo: event transferOutwardsFrom: currentTarget
+
+ | localEvent |
+ currentTarget owner ifNotNil: [:nextTarget |
+ localEvent := event transformedBy: (currentTarget transformedFrom: nextTarget).
+ "Never transfer halo to top-most world"
+ ^ (nextTarget isWorldMorph not and: [nextTarget wantsHaloFromClick])
+ ifTrue: [self invokeHalo: localEvent on: nextTarget]
+ ifFalse: [self dispatchHalo: localEvent transferOutwardsFrom: nextTarget]].
+
+ "We're at the top level; throw the event back in to find recipient"
+ event hand removeHalo.
+ currentTarget isWorldMorph
+ ifTrue: [currentTarget processEvent: event copy resetHandlerFields].
+
+ ^ false!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>dispatchHalo:with: (in category 'dispatching') -----
+ dispatchHalo: anEvent with: aMorph
+
+ | halo successful |
+ halo := anEvent hand halo.
+ successful := (halo isNil or: [halo target ~~ aMorph])
+ ifTrue: [self dispatchHalo: anEvent createFor: aMorph]
+ ifFalse: [self dispatchHalo: anEvent transferFrom: aMorph].
+ successful ifTrue: [
+ self assert: [halo ~~ anEvent hand halo].
+ anEvent hand halo setProperty: #lastHaloDispatcher toValue: self].
+ ^ successful!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>invokeHalo:on: (in category 'invoking') -----
+ invokeHalo: anEvent on: aMorph
+
+ aMorph addHalo: anEvent.
+ ^ true!

Item was added:
+ ----- Method: MorphicHaloDispatcher>>invokeHaloOrMove:on: (in category 'invoking') -----
+ invokeHaloOrMove: anEvent on: aMorph
+ "Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph."
+ | h tfm doNotDrag |
+ anEvent hand newMouseFocus: aMorph event: anEvent.
+ h := anEvent hand halo.
+ "Prevent wrap around halo transfers originating from throwing the event back in"
+ doNotDrag := false.
+ h ifNotNil:[
+ (h innerTarget == aMorph) ifTrue:[doNotDrag := true].
+ (h innerTarget hasOwner: aMorph) ifTrue:[doNotDrag := true].
+ (aMorph hasOwner: h target) ifTrue:[doNotDrag := true]].
+
+ tfm := (aMorph transformedFrom: nil) inverseTransformation.
+
+ "cmd-drag on flexed morphs works better this way"
+ h := aMorph addHalo: (anEvent transformedBy: tfm).
+ h setProperty: #lastHaloDispatcher toValue: self.
+ doNotDrag ifTrue:[^ true].
+ "Initiate drag transition if requested"
+ anEvent hand
+ waitForClicksOrDrag: h
+ event: (anEvent transformedBy: tfm)
+ selectors: { nil. nil. nil. #startDragTarget:. }
+ threshold: HandMorph dragThreshold.
+ "Pass focus explicitly here"
+ anEvent hand newMouseFocus: h.
+ "Reset temporary cursors to make available halo interaction visible."
+ anEvent hand showTemporaryCursor: nil.
+ ^ true!

Item was changed:
  ----- Method: PasteUpMorph>>tryInvokeHalo: (in category 'events-processing') -----
  tryInvokeHalo: aUserInputEvent
+
- "Invoke halos around the top-most world container at aUserInputEvent's #position.  If it was already halo'd, zero-in on its next inward component morph at that position.  Holding Shift during the click reverses this traversal order."
- | stack innermost haloTarget |
  Preferences noviceMode ifTrue: [ ^ self ].
  Morph haloForAll ifFalse: [ ^ self ].
+
+ (self transferHalo: aUserInputEvent)
+ ifTrue: "The event was handled, don't let it cause any further side-effects."
+ [ aUserInputEvent ignore ].!
- "the stack is the top-most morph to bottom-most."
- stack := (self morphsAt: aUserInputEvent position unlocked: true) select:
- [ : each | each wantsHaloFromClick or: [ each handlesMouseDown: aUserInputEvent ] ].
- innermost := aUserInputEvent hand halo
- ifNil: [ stack first ]
- ifNotNil:
- [ : existingHalo | (stack copyWithout: existingHalo) "No halos on halos"
- detect: [ : each | each owner == self ]
- ifFound:
- [ : worldContainer | "Is existingHalo's target part of the same worldContainer as the morph clicked?"
- (existingHalo target withAllOwners includes: worldContainer)
- ifTrue: [ "same hierarchy, let #transferHalo: continue to handle it for now."  ^self ]
- ifFalse:
- [ "different hierarchy, remove + add."
- aUserInputEvent hand removeHalo.
- aUserInputEvent shiftPressed
- ifTrue: [ stack second "first is still the just removed halo" ]
- ifFalse: [ worldContainer ] ] ]
- ifNone: [ "existingHalo is on the World, defer to #transferHalo: for now."  ^self ] ].
- "If modifier key is pressed, start at innermost (the target), otherwise the outermost (direct child of the world (self))."
- haloTarget := (innermost == self or: [aUserInputEvent shiftPressed])
- ifTrue: [ innermost ]
- ifFalse:
- [ "Find the outermost owner that wants it."
- innermost withAllOwners reversed allButFirst
- detect: [ : each | each wantsHaloFromClick ]
- ifNone: [ "haloTarget has its own mouseDown handler, don't halo."  ^ self ] ].
- "Now that we have the haloTarget, show the halo."
- aUserInputEvent hand
- newMouseFocus: haloTarget
- event: aUserInputEvent.
- haloTarget invokeHaloOrMove: aUserInputEvent.
- "aUserInputEvent has been consumed, don't let it cause any further side-effects."
- aUserInputEvent ignore!

Item was changed:
  ----- Method: SimpleHaloMorph>>transferHalo: (in category 'pop up') -----
  transferHalo: event
  "Transfer the halo to the next likely recipient"
 
+ ^ self
+ transferHalo: event
+ using: (self
+ valueOfProperty: #lastHaloDispatcher
+ ifAbsent: [self target defaultHaloDispatcher])!
- self target
- transferHalo: (event transformedBy: (self target transformedFrom: self))
- from: self target.!

Item was removed:
- ----- Method: SimpleHaloMorph>>transferHalo:from: (in category 'halos and balloon help') -----
- transferHalo: event from: formerHaloOwner
- "If my world tries to open on me, pass it on to the next sibling after me."
-
- formerHaloOwner == self world ifTrue: [
- self world submorphsDo: [:m |
- (m ~~ self and: [m fullContainsPoint: event position]) ifTrue: [
- m comeToFront.
- ^ m transferHalo: event from: formerHaloOwner]]].!

Item was added:
+ ----- Method: SimpleHaloMorph>>transferHalo:using: (in category 'pop up') -----
+ transferHalo: event using: dispatcher
+ "Transfer the halo to the next likely recipient. Call the target again so that it may change the dispatcher."
+
+ ^ self target
+ transferHalo: (event transformedBy: (self target transformedFrom: self))
+ using: dispatcher!

Item was added:
+ ----- Method: SimpleHaloMorph>>wantsHaloFromClick (in category 'halos and balloon help') -----
+ wantsHaloFromClick
+
+ ^ false!