"
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/Attic/ButtonC.st,v 1.5 1995-03-06 19:27:54 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)
"
! !
!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
"return true, if I trigger on press
(in contrast to triggering on up, which is the default)"
^ 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
"return true, if I am enabled"
^ enabled
!
active
"return true, if I am active; that is currently performing my
action."
^ active
!
pressed
"return true, if I am pressed"
^ pressed
!
entered
"return true, if the mouse pointer is currently in my view"
^ 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"
view notNil ifTrue:[
view sendChangeMessageWith:true
]
].
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"
view notNil ifTrue:[
view sendChangeMessageWith:false.
].
].
active := false.
]
]
]
!
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
]
]
! !