--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ButtonController.st Mon Feb 06 01:52:01 1995 +0100
@@ -0,0 +1,427 @@
+"
+ COPYRIGHT (c) 1995 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+
+Controller subclass:#ButtonController
+ instanceVariableNames:'enabled pressed active entered triggerOnDown autoRepeat
+ repeatBlock initialDelay repeatDelay
+ pressActionBlock releaseActionBlock'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Support'
+!
+
+!ButtonController class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1995 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+version
+"
+$Header: /cvs/stx/stx/libwidg/ButtonController.st,v 1.1 1995-02-06 00:51:58 claus Exp $
+"
+!
+
+documentation
+"
+ ButtonControllers are used with buttons and handle all user interaction.
+ These are automatically created when a Button is created, therefore no manual
+ action is required for creation.
+
+ Instance variables:
+
+ enabled <Boolean> pressing is allowed (default: true)
+ pressed <Boolean> true if currently pressed (read-only)
+ entered <Boolean> true if the cursor is currently in this view
+ triggerOnDown <Boolean> controls if the action should be executed on
+ press or on release (default: on release).
+ pressActionBlock <Block> block to evaluate when pressed (default: noop)
+ releaseActionBlock <Block> block to evaluate when released (default: noop)
+ autoRepeat <Boolean> auto-repeats when pressed long enough (default: false)
+ initialDelay <Number> seconds till first auto-repeat (default: 0.2)
+ repeatDelay <Number> seconds of repeat intervall (default: 0.025)
+ repeatBlock <Block> block evaluated for auto-repeat (internal)
+ active <Boolean> true during action evaluation (internal)
+"
+!
+
+examples
+"
+ |top b|
+
+ top := StandardSystemView new.
+ top extent:100@100.
+
+ b := Button label:'hello' in:top.
+ b action:[Transcript flash].
+ top open.
+
+
+ |top b|
+
+ top := StandardSystemView new.
+ top extent:100@100.
+
+ b := Button label:'hello' in:top.
+ b controller beTriggerOnUp.
+ top open.
+"
+! !
+
+!ButtonController class methodsFor:'defaults'!
+
+defaultRepeatDelay
+ "when autorepeat is enabled, and button is not released,
+ repeat every repeatDelay seconds"
+
+ ^ 0.025
+
+!
+
+defaultInitialDelay
+ "when autorepeat is enabled, and button is not released,
+ start repeating after initialDelay seconds"
+
+ ^ 0.2
+
+
+! !
+
+!ButtonController methodsFor:'initialization'!
+
+initialize
+ super initialize.
+
+ enabled := true.
+ active := false.
+ pressed := false.
+ entered := false.
+ autoRepeat := false.
+ initialDelay := self class defaultInitialDelay.
+ repeatDelay := self class defaultRepeatDelay.
+ triggerOnDown := false.
+! !
+
+!ButtonController methodsFor:'accessing'!
+
+beTriggerOnUp
+ "make the receiver act on button release"
+
+ triggerOnDown := false
+!
+
+beTriggerOnDown
+ "make the receiver act on button press"
+
+ triggerOnDown := true
+!
+
+triggerOnDown:aBoolean
+ "set/clear the flag which controls if the action block is to be evaluated
+ on press or on release.
+ (see also ST-80 compatibility methods beTriggerOn*)"
+
+ triggerOnDown := aBoolean
+!
+
+isTriggerOnDown
+ ^ triggerOnDown
+!
+
+pressAction
+ "return the pressAction; thats the block which gets evaluated
+ when the button is pressed (if non-nil)"
+
+ ^ pressActionBlock
+!
+
+pressAction:aBlock
+ "define the action to be performed on press"
+
+ pressActionBlock := aBlock
+!
+
+releaseAction
+ "return the releaseAction; thats the block which gets evaluated
+ when the button is relreased (if non-nil)"
+
+ ^ releaseActionBlock
+!
+
+releaseAction:aBlock
+ "define the action to be performed on release"
+
+ releaseActionBlock := aBlock
+!
+
+action:aBlock
+ "convenient method: depending on the setting the triggerOnDown flag,
+ either set the press-action clear any release-action or
+ vice versa, set the release-action and clear the press-action."
+
+ triggerOnDown ifTrue:[
+ releaseActionBlock := nil.
+ pressActionBlock := aBlock
+ ] ifFalse:[
+ releaseActionBlock := aBlock.
+ pressActionBlock := nil
+ ]
+!
+
+autoRepeat
+ "turn on autorepeat"
+
+ autoRepeat := true.
+ repeatBlock := [self repeat]
+!
+
+disable
+ "disable the button"
+
+ enabled ifTrue:[
+ enabled := false.
+ view redraw
+ ]
+!
+
+enable
+ "enable the button"
+
+ enabled ifFalse:[
+ enabled := true.
+ view redraw
+ ]
+!
+
+enabled
+ ^ enabled
+!
+
+active
+ ^ active
+!
+
+pressed
+ ^ pressed
+!
+
+entered
+ ^ entered
+!
+
+entered:aBoolean
+ entered := aBoolean
+!
+
+pressed:aBoolean
+ pressed := aBoolean
+!
+
+active:aBoolean
+ active := aBoolean
+! !
+
+!ButtonController methodsFor:'event handling'!
+
+buttonPress:button x:x y:y
+ |sym|
+
+ (button == 1 or:[button == #select]) ifFalse:[
+ ^ super buttonPress:button x:x y:y
+ ].
+
+ pressed ifFalse:[
+ enabled ifTrue:[
+ pressed := true.
+ view showActive.
+
+ (pressActionBlock notNil or:[model notNil]) ifTrue:[
+ "
+ force output - so that button is drawn correctly in case
+ of any long-computation (at high priority)
+ "
+ view device synchronizeOutput.
+ ].
+
+ active := true.
+
+ pressActionBlock notNil ifTrue:[
+ pressActionBlock value
+ ].
+
+ triggerOnDown ifTrue:[
+ "the ST-80 way of doing things"
+ (model notNil and:[(sym := view changeSymbol) notNil]) ifTrue:[
+ model perform:sym
+ ].
+ ].
+
+ active := false.
+
+ autoRepeat ifTrue:[
+ Processor addTimedBlock:repeatBlock afterSeconds:initialDelay
+ ]
+ ]
+ ]
+!
+
+buttonRelease:button x:x y:y
+ "button was released - if enabled, perform releaseaction"
+
+ |sym|
+
+ (button == 1 or:[button == #select]) ifFalse:[
+ ^ super buttonRelease:button x:x y:y
+ ].
+ pressed ifTrue:[
+ autoRepeat ifTrue:[
+ Processor removeTimedBlock:repeatBlock
+ ].
+ pressed := false.
+ view showPassive.
+
+ enabled ifTrue:[
+ "
+ only perform action if released within myself
+ "
+ ((x >= 0)
+ and:[x <= view width
+ and:[y >= 0
+ and:[y <= view height]]]) ifTrue:[
+ (releaseActionBlock notNil or:[model notNil]) ifTrue:[
+ "
+ force output - so that button is drawn correctly in case
+ of any long-computation (at high priority)
+ "
+ view device synchronizeOutput.
+ ].
+
+ active := true.
+
+ releaseActionBlock notNil ifTrue:[
+ releaseActionBlock value
+ ].
+ triggerOnDown ifFalse:[
+ "the ST-80 way of doing things"
+ (model notNil and:[(sym := view changeSymbol) notNil]) ifTrue:[
+ model perform:sym
+ ].
+ ].
+
+ active := false.
+
+ view redraw.
+ ]
+ ]
+ ]
+!
+
+pointerEnter:state x:x y:y
+ "redraw with enteredColors if they differ from the normal colors"
+
+ entered := true.
+ pressed ifTrue:[
+ "
+ reentered after a leave with mouse-button down;
+ restart autorepeating and/or if I am a button with
+ triggerOnDown, show active again.
+ "
+ enabled ifTrue:[
+ autoRepeat ifTrue:[
+ Processor addTimedBlock:repeatBlock afterSeconds:initialDelay
+ ].
+ triggerOnDown ifFalse:[
+ view showActive.
+ ]
+ ]
+ ] ifFalse:[
+ enabled ifTrue:[
+ view redraw
+ ]
+ ]
+!
+
+repeat
+ "this is sent from the autorepeat-block, when the button has been pressed long
+ enough; it simulates a release-press, by evaluating both release
+ and press actions."
+
+ pressed ifTrue:[
+ enabled ifTrue:[
+ active ifFalse:[
+ active := true.
+ releaseActionBlock notNil ifTrue:[releaseActionBlock value].
+ pressActionBlock notNil ifTrue:[pressActionBlock value].
+ active := false.
+
+ autoRepeat ifTrue:[
+ Processor addTimedBlock:repeatBlock afterSeconds:repeatDelay
+ ]
+ ]
+ ]
+ ]
+!
+
+buttonMultiPress:button x:x y:y
+ ^ self buttonPress:button x:x y:y
+!
+
+keyPress:key x:x y:y
+ "only trigger, if I am the focusView of my group"
+
+ |group|
+
+ ((group := view windowGroup) notNil
+ and:[group focusView == view]) ifTrue:[
+ (key == #Return or:[key == Character space]) ifTrue:[
+ "just simulate a buttonPress/release here."
+ self buttonPress:1 x:0 y:0.
+ self buttonRelease:1 x:0 y:0.
+ ^ self.
+ ]
+ ].
+ view keyPress:key x:x y:y
+!
+
+pointerLeave:state
+ "redraw with normal colors if they differ from enteredColors"
+
+ entered := false.
+ pressed ifTrue:[
+ "
+ leave with mouse-button down;
+ stop autorepeating and/or if I am a button with
+ action on release, show passive
+ "
+ autoRepeat ifTrue:[
+ Processor removeTimedBlock:repeatBlock
+ ].
+ triggerOnDown ifFalse:[
+ view showPassive.
+ ]
+ ] ifFalse:[
+ enabled ifTrue:[
+ view redraw
+ ]
+ ]
+! !
+