'From Squeakland 3.8.5976 of 18 August 2004 [latest update: #242] on 21 August 2004 at 6:17:24 pm'! "Change Set: SimpleButtonWhilePressedFix-nk Date: 13 June 2004 Author: Ned Konz Fixes the problem seen with the #whilePressed event type and repeating too fast. For an example, try the 'Next' button in the GraphicalDictionaryMenu before and after this fix: GraphicalDictionaryMenu example Move mouseDownTime up to SimpleButtonMorph: " (SimpleButtonDelayedMenuMorph instVarNames includes: 'mouseDownTime') ifTrue: [ SimpleButtonDelayedMenuMorph removeInstVarName: 'mouseDownTime' ]. (SimpleButtonMorph instVarNames includes: 'mouseDownTime') ifFalse: [ SimpleButtonMorph addInstVarName: 'mouseDownTime' ].! !Morph methodsFor: 'events-processing' stamp: 'nk 3/10/2004 14:30'! handleMouseDown: anEvent "System level event handling." anEvent wasHandled ifTrue:[^self]. "not interested" anEvent hand removePendingBalloonFor: self. anEvent hand removePendingHaloFor: self. anEvent wasHandled: true. (anEvent controlKeyPressed and: [Preferences cmdGesturesEnabled]) ifTrue: [^ self invokeMetaMenu: anEvent]. "Make me modal during mouse transitions" anEvent hand newMouseFocus: self event: anEvent. anEvent blueButtonChanged ifTrue:[^self blueButtonDown: anEvent]. "this mouse down could be the start of a gesture, or the end of a gesture focus" (self isGestureStart: anEvent) ifTrue: [^ self gestureStart: anEvent]. self mouseDown: anEvent. anEvent hand removeHaloFromClick: anEvent on: self. (self handlesMouseStillDown: anEvent) ifTrue:[ self startStepping: #handleMouseStillDown: at: Time millisecondClockValue + self mouseStillDownThreshold arguments: {anEvent copy resetHandlerFields} stepTime: self mouseStillDownStepRate ]. ! ! !Morph methodsFor: 'events-processing' stamp: 'nk 6/13/2004 09:16'! handleMouseMove: anEvent "System level event handling." anEvent wasHandled ifTrue:[^self]. "not interested" "Rules say that by default a morph gets #mouseMove iff * the hand is not dragging anything, + and some button is down, + and the receiver is the current mouse focus." (anEvent hand hasSubmorphs) ifTrue:[^self]. (anEvent anyButtonPressed and:[anEvent hand mouseFocus == self]) ifFalse:[^self]. anEvent wasHandled: true. self mouseMove: anEvent. (self handlesMouseStillDown: anEvent) ifTrue:[ "Step at the new location" self startStepping: #handleMouseStillDown: at: Time millisecondClockValue arguments: {anEvent copy resetHandlerFields} stepTime: self mouseStillDownStepRate ]. ! ! !GraphicalMenu methodsFor: 'initialization' stamp: 'nk 1/11/2004 15:09'! initializeFor: aTarget withForms: formList coexist: aBoolean "World primaryHand attachMorph: (GraphicalMenu new initializeFor: nil withForms: Form allInstances coexist: true)" | buttons bb anIndex buttonCage | target := aTarget. coexistWithOriginal := aBoolean. formChoices := formList. currentIndex := 1. self borderWidth: 1; cellPositioning: #center; color: Color white; hResizing: #shrinkWrap; vResizing: #shrinkWrap. buttons := AlignmentMorph newRow. buttons borderWidth: 0; layoutInset: 0. buttons hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5 @ 5. buttons wrapCentering: #topLeft. buttonCage := AlignmentMorph newColumn. buttonCage hResizing: #shrinkWrap; vResizing: #spaceFill. buttonCage addTransparentSpacerOfSize: 0 @ 10. bb := SimpleButtonMorph new target: self; borderColor: Color black. buttons addMorphBack: (bb label: 'Prev'; actionSelector: #downArrowHit; actWhen: #whilePressed). buttons addTransparentSpacerOfSize: 9 @ 0. bb := SimpleButtonMorph new target: self; borderColor: Color black. buttons addMorphBack: (bb label: 'Next'; actionSelector: #upArrowHit; actWhen: #whilePressed). buttons addTransparentSpacerOfSize: 5 @ 0. buttons submorphs last color: Color white. buttonCage addMorphBack: buttons. buttonCage addTransparentSpacerOfSize: 0 @ 12. buttons := AlignmentMorph newRow. bb := SimpleButtonMorph new target: self; borderColor: Color black. buttons addMorphBack: (bb label: 'OK'; actionSelector: #okay). buttons addTransparentSpacerOfSize: 5 @ 0. bb := SimpleButtonMorph new target: self; borderColor: Color black. buttons addMorphBack: (bb label: 'Cancel'; actionSelector: #cancel). buttonCage addMorphBack: buttons. buttonCage addTransparentSpacerOfSize: 0 @ 10. self addMorphFront: buttonCage. formDisplayMorph := Thumbnail new extent: 100 @ 100; maxWidth: 100 minHeight: 30; yourself. self addMorphBack: (Morph new color: Color white; layoutPolicy: TableLayout new; layoutInset: 4 @ 4; hResizing: #spaceFill; vResizing: #spaceFill; listCentering: #center; addMorphBack: formDisplayMorph; yourself). target ifNotNil: [(anIndex := formList indexOf: target form ifAbsent: []) ifNotNil: [currentIndex := anIndex]]. self updateThumbnail! ! !GraphicalMenu methodsFor: 'event handling' stamp: 'nk 1/11/2004 14:44'! updateThumbnail | f | f _ formChoices at: currentIndex. formDisplayMorph makeThumbnailFromForm: f. ! ! !GraphicalDictionaryMenu methodsFor: 'initialization' stamp: 'nk 1/11/2004 16:22'! initializeFor: aTarget fromDictionary: aDictionary "Initialize me for a target and a dictionary." | anIndex aButton | self baseDictionary: aDictionary. target := aTarget. coexistWithOriginal := true. self extent: 210 @ 210. self clipSubmorphs: true. self layoutPolicy: ProportionalLayout new. aButton := (IconicButton new) borderWidth: 0; labelGraphic: (ScriptingSystem formAtKey: 'TinyMenu'); color: Color transparent; actWhen: #buttonDown; actionSelector: #showMenu; target: self; setBalloonText: 'menu'. self addMorph: aButton fullFrame: (LayoutFrame fractions: (0.5 @ 0 extent: 0 @ 0) offsets: (-50 @ 6 extent: aButton extent)). aButton := (SimpleButtonMorph new) target: self; borderColor: Color black; label: 'Prev'; actionSelector: #downArrowHit; actWhen: #whilePressed; setBalloonText: 'show previous picture'; yourself. self addMorph: aButton fullFrame: (LayoutFrame fractions: (0.5 @ 0 extent: 0 @ 0) offsets: (-24 @ 4 extent: aButton extent)). aButton := (SimpleButtonMorph new) target: self; borderColor: Color black; label: 'Next'; actionSelector: #upArrowHit; actWhen: #whilePressed; setBalloonText: 'show next pictutre'. self addMorph: aButton fullFrame: (LayoutFrame fractions: (0.5 @ 0 extent: 0 @ 0) offsets: (24 @ 4 extent: aButton extent)). self addMorph: ((UpdatingStringMorph new) contents: ' '; target: self; putSelector: #renameGraphicTo:; getSelector: #truncatedNameOfGraphic; useStringFormat; setBalloonText: 'The name of the current graphic'; yourself) fullFrame: (LayoutFrame fractions: (0 @ 0 extent: 1 @ 0) offsets: (10 @ 40 corner: -10 @ 60)). self addMorph: ((Morph new) extent: 100 @ 4; color: Color black) fullFrame: (LayoutFrame fractions: (0 @ 0 extent: 1 @ 0) offsets: (0 @ 60 corner: 0 @ 64)). formDisplayMorph := (Thumbnail new) extent: 100 @ 100; useInterpolation: true; maxWidth: 3000 minHeight: 100; yourself. self addMorph: formDisplayMorph fullFrame: (LayoutFrame fractions: (0 @ 0 extent: 0@0) offsets: (8 @ 72 corner: 108 @ 172)). self minimumExtent: 116@180. target ifNotNil: [(anIndex := formChoices indexOf: target form ifAbsent: []) ifNotNil: [currentIndex := anIndex]]. self updateThumbnail! ! !GraphicalDictionaryMenu methodsFor: 'private' stamp: 'nk 1/11/2004 15:14'! updateThumbnail super updateThumbnail. (self findA: UpdatingStringMorph) doneWithEdits; contents: (entryNames at: currentIndex) ! ! !GraphicalDictionaryMenu class methodsFor: 'instance creation' stamp: 'nk 1/11/2004 15:50'! openOn: aFormDictionary withLabel: aLabel "open a graphical dictionary in a window having the label aLabel. aFormDictionary should be a dictionary containing as value a form." | inst aWindow | aFormDictionary size isZero ifTrue: [^ self inform: 'Empty!!']. inst := self new initializeFor: nil fromDictionary: aFormDictionary. aWindow _ (SystemWindow labelled: aLabel) model: inst. aWindow addMorph: inst frame: (0@0 extent: 1@1). aWindow extent: inst fullBounds extent + (3 @ aWindow labelHeight + 3); minimumExtent: inst minimumExtent + (3 @ aWindow labelHeight + 3). HandMorph attach: aWindow. ^ inst! ! !SimpleButtonMorph methodsFor: 'copying' stamp: 'nk 1/23/2004 17:14'! veryDeepInner: deepCopier "Copy all of my instance variables. Some need to be not copied at all, but shared. Warning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment." super veryDeepInner: deepCopier. "target _ target. Weakly copied" "actionSelector _ actionSelector. a Symbol" "arguments _ arguments. All weakly copied" actWhen _ actWhen veryDeepCopyWith: deepCopier. oldColor _ oldColor veryDeepCopyWith: deepCopier. mouseDownTime _ nil.! ! !SimpleButtonMorph methodsFor: 'event handling' stamp: 'nk 1/11/2004 12:37'! mouseDown: evt super mouseDown: evt. mouseDownTime _ Time millisecondClockValue. oldColor _ self fillStyle. actWhen == #buttonDown ifTrue: [ self doButtonAction] ifFalse: [ self updateVisualState: evt ]. self mouseStillDown: evt.! ! !SimpleButtonMorph methodsFor: 'menu' stamp: 'nk 1/11/2004 12:40'! setActWhen actWhen := (SelectionMenu selections: #(#buttonDown #buttonUp #whilePressed #startDrag)) startUpWithCaption: 'Choose one of the following conditions'! ! !SimpleButtonMorph methodsFor: 'submorphs-add/remove' stamp: 'nk 6/13/2004 13:46'! actWhen: condition "Accepts symbols: #buttonDown, #buttonUp, and #whilePressed, #startDrag" actWhen _ condition. actWhen == #startDrag ifFalse: [self on: #startDrag send: nil to: nil ] ifTrue:[self on: #startDrag send: #doButtonAction to: self].! ! !SimpleButtonMorph methodsFor: 'events-processing' stamp: 'nk 1/11/2004 13:25'! mouseStillDownStepRate "Answer how often I want the #handleMouseStillDown: stepped" ^200! ! !SimpleButtonDelayedMenuMorph methodsFor: 'event handling' stamp: 'nk 1/11/2004 12:35'! mouseDown: evt didMenu _ nil. super mouseDown: evt. ! ! !UpdatingStringMorph methodsFor: 'editing' stamp: 'nk 1/11/2004 15:29'! doneWithEdits "If in a SyntaxMorph, shrink min width after editing" | editor | super doneWithEdits. (owner respondsTo: #parseNode) ifTrue: [minimumWidth _ 8]. editor _ (submorphs detect: [ :sm | sm isKindOf: StringMorphEditor ] ifNone: [ ^self ]). editor delete.! !