Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1445.mcz ==================== Summary ==================== Name: Morphic-mt.1445 Author: mt Time: 31 May 2018, 10:32:00.706975 am UUID: 5bb479eb-ac7f-4d42-a614-96468d8dd517 Ancestors: Morphic-mt.1444 Refactor the halo-navigation improvement from Morphic-cmm.1443. The actual change is not in the initial halo invocation but in the transferring of halos between morphs. Thus, still exit the event filter in PasteUpMorph as early as possible to just deal with regular event dispatch. See the line "anEvent hand halo ifNotNil: [^ self]" in #tryInvokeHalo. =============== Diff against Morphic-mt.1444 =============== Item was changed: ----- Method: PasteUpMorph>>tryInvokeHalo: (in category 'events-processing') ----- + tryInvokeHalo: anEvent + + | innerMost target | + anEvent hand halo ifNotNil: [^ self "No invocation needed. Halo will handle transfer itself."]. + Preferences noviceMode ifTrue: [^ self "No halo in novice mode."]. + Morph haloForAll ifFalse: [^ self]. + + innerMost := (self morphsAt: anEvent position unlocked: true) first. + + "1) Try to use innermost morph but skip all the ones that do not want to show a halo along the owner chain." + target := innerMost. + [target isNil or: [target wantsHaloFromClick]] + whileFalse: [target := target owner]. + target ifNil: [^ self]. + + "2) Without a modifier, which is normal, find the outermost container for that inner morph." + (innerMost == self or: [anEvent shiftPressed]) ifFalse: [ + | previousTargets | + previousTargets := OrderedCollection new. + [target notNil and: [target owner ~~ self]] whileTrue: [ + previousTargets add: target. + target := target owner]. + target ifNil: [^ self]. + [previousTargets isEmpty or: [target wantsHaloFromClick]] whileFalse: [ + target := previousTargets removeLast]. + target wantsHaloFromClick ifFalse: [^ self]]. + + "3) Now that we have the target, show the halo. Abort event dispatching, too, to avoid confusion." + anEvent hand newMouseFocus: target event: anEvent. + target invokeHaloOrMove: anEvent. + anEvent ignore.! - 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 target owners | - Preferences noviceMode ifTrue: [^self ]. - Morph haloForAll ifFalse: [^self]. - "the stack is the top-most morph to bottom-most." - stack := (self morphsAt: aUserInputEvent position unlocked: true) select: [ : each | each wantsHaloFromClick ]. - stack ifEmpty: [^self]. - target := - aUserInputEvent hand halo - ifNil: [ stack first ] - ifNotNil: - [ : existingHalo | - stack allButFirst "halo's are always topmost on the stack" - detect: [ : each | each owner == self ] - ifFound: - [ : topMostWhereClicked | - (existingHalo target withAllOwners includes: topMostWhereClicked) - ifTrue: [ "No invocation needed. Halo will handle transfer itself." ^self ] - ifFalse: - [ "Transfer halo to new world container." - aUserInputEvent hand removeHalo. - aUserInputEvent shiftPressed - ifTrue: [ stack second ] - ifFalse: [ topMostWhereClicked ] ] ] - ifNone: ["Okay, invoke halos on the world." self ] ]. - "With a modifier, we want the innermost, otherwise the outermost." - owners := target withAllOwners select: [ : each | each wantsHaloFromClick ]. - "the last owner is expected to be self." - target := aUserInputEvent shiftPressed ifTrue: [ owners first ] ifFalse: [ owners at: owners size-1 ifAbsent: [self] ]. - "Now that we have the target, show the halo. Abort event dispatching, too, to avoid confusion." - aUserInputEvent hand newMouseFocus: target event: aUserInputEvent. - target 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. Switch between siblings if overlapping." - "Transfer the halo to the next likely recipient" + (self target world morphsAt: event position) allButFirst "... the halo itself" + detect: [:morph | + "Sibling found?" + (morph owner == self target owner + and: [morph ~~ self target]) + ifTrue: [ + ^ morph invokeHaloOrMove: event]. + "No sibling possible anymore?" + morph == self target]. + self target transferHalo: (event transformedBy: (self target transformedFrom: self)) from: self target.! |
Hey Marcel,
I was wondering whether "transfer halo" is a useful first-class abstraction to keep factored out above "remove"+"invoke" halo? I was just thinking about some potential alternative uses of halos, but the whole idea of "transfer" seems to get in the way... For example, it's hard to understand how "transfer" would fit in a world where multiple objects could simply have their halos toggled on/off independently? Or, how would "transfer" fit if we wanted each Morph to be able to provide its own custom set of halos? They wouldn't want a "transfer" of the other guys halos, but to "invoke" their own. I know this may sound crazy, but would you be open to the idea of seeing if we can get rid of the concept of "transfer" and just use the elemental "remove" and "invoke" in its place? Right now, the #tryInvokeHalo: (called from the event filter mech) is tied in with distant code (regular event handler)... totally different places, and we both know that's bad. So if we could jettison the "transfer" idea, maybe we could the code too, leaving it neatly all in one place..? What do you think? Best, Chris On Thu, May 31, 2018 at 3:32 AM, <[hidden email]> wrote: > Marcel Taeumel uploaded a new version of Morphic to project The Trunk: > http://source.squeak.org/trunk/Morphic-mt.1445.mcz > > ==================== Summary ==================== > > Name: Morphic-mt.1445 > Author: mt > Time: 31 May 2018, 10:32:00.706975 am > UUID: 5bb479eb-ac7f-4d42-a614-96468d8dd517 > Ancestors: Morphic-mt.1444 > > Refactor the halo-navigation improvement from Morphic-cmm.1443. The actual change is not in the initial halo invocation but in the transferring of halos between morphs. Thus, still exit the event filter in PasteUpMorph as early as possible to just deal with regular event dispatch. See the line "anEvent hand halo ifNotNil: [^ self]" in #tryInvokeHalo. > > =============== Diff against Morphic-mt.1444 =============== > > Item was changed: > ----- Method: PasteUpMorph>>tryInvokeHalo: (in category 'events-processing') ----- > + tryInvokeHalo: anEvent > + > + | innerMost target | > + anEvent hand halo ifNotNil: [^ self "No invocation needed. Halo will handle transfer itself."]. > + Preferences noviceMode ifTrue: [^ self "No halo in novice mode."]. > + Morph haloForAll ifFalse: [^ self]. > + > + innerMost := (self morphsAt: anEvent position unlocked: true) first. > + > + "1) Try to use innermost morph but skip all the ones that do not want to show a halo along the owner chain." > + target := innerMost. > + [target isNil or: [target wantsHaloFromClick]] > + whileFalse: [target := target owner]. > + target ifNil: [^ self]. > + > + "2) Without a modifier, which is normal, find the outermost container for that inner morph." > + (innerMost == self or: [anEvent shiftPressed]) ifFalse: [ > + | previousTargets | > + previousTargets := OrderedCollection new. > + [target notNil and: [target owner ~~ self]] whileTrue: [ > + previousTargets add: target. > + target := target owner]. > + target ifNil: [^ self]. > + [previousTargets isEmpty or: [target wantsHaloFromClick]] whileFalse: [ > + target := previousTargets removeLast]. > + target wantsHaloFromClick ifFalse: [^ self]]. > + > + "3) Now that we have the target, show the halo. Abort event dispatching, too, to avoid confusion." > + anEvent hand newMouseFocus: target event: anEvent. > + target invokeHaloOrMove: anEvent. > + anEvent ignore.! > - 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 target owners | > - Preferences noviceMode ifTrue: [^self ]. > - Morph haloForAll ifFalse: [^self]. > - "the stack is the top-most morph to bottom-most." > - stack := (self morphsAt: aUserInputEvent position unlocked: true) select: [ : each | each wantsHaloFromClick ]. > - stack ifEmpty: [^self]. > - target := > - aUserInputEvent hand halo > - ifNil: [ stack first ] > - ifNotNil: > - [ : existingHalo | > - stack allButFirst "halo's are always topmost on the stack" > - detect: [ : each | each owner == self ] > - ifFound: > - [ : topMostWhereClicked | > - (existingHalo target withAllOwners includes: topMostWhereClicked) > - ifTrue: [ "No invocation needed. Halo will handle transfer itself." ^self ] > - ifFalse: > - [ "Transfer halo to new world container." > - aUserInputEvent hand removeHalo. > - aUserInputEvent shiftPressed > - ifTrue: [ stack second ] > - ifFalse: [ topMostWhereClicked ] ] ] > - ifNone: ["Okay, invoke halos on the world." self ] ]. > - "With a modifier, we want the innermost, otherwise the outermost." > - owners := target withAllOwners select: [ : each | each wantsHaloFromClick ]. > - "the last owner is expected to be self." > - target := aUserInputEvent shiftPressed ifTrue: [ owners first ] ifFalse: [ owners at: owners size-1 ifAbsent: [self] ]. > - "Now that we have the target, show the halo. Abort event dispatching, too, to avoid confusion." > - aUserInputEvent hand newMouseFocus: target event: aUserInputEvent. > - target 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. Switch between siblings if overlapping." > - "Transfer the halo to the next likely recipient" > > + (self target world morphsAt: event position) allButFirst "... the halo itself" > + detect: [:morph | > + "Sibling found?" > + (morph owner == self target owner > + and: [morph ~~ self target]) > + ifTrue: [ > + ^ morph invokeHaloOrMove: event]. > + "No sibling possible anymore?" > + morph == self target]. > + > self target > transferHalo: (event transformedBy: (self target transformedFrom: self)) > from: self target.! > > |
Free forum by Nabble | Edit this page |