ButtonC.st
author claus
Mon, 06 Mar 1995 20:29:54 +0100
changeset 97 cbf495fe3b64
parent 95 7535cfca9509
child 118 3ee5ea99d0e2
permissions -rw-r--r--
*** empty log message ***

"
 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
	]
    ]
! !