WindowEvent.st
author ca
Wed, 08 Dec 1999 21:39:31 +0100
changeset 3089 ea806f804f5c
parent 3011 e5880bb2738d
child 3138 578c121bd7ff
permissions -rw-r--r--
accessors for x/y

"
 COPYRIGHT (c) 1993 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.
"

Object subclass:#WindowEvent
	instanceVariableNames:'view type arguments delegatedFrom consumed'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Support'
!

WindowEvent subclass:#ClientEvent
	instanceVariableNames:'eventData'
	classVariableNames:''
	poolDictionaries:''
	privateIn:WindowEvent
!

WindowEvent subclass:#InputEvent
	instanceVariableNames:'modifierFlags'
	classVariableNames:'F_CTRL F_ALT F_META F_SHIFT F_BUTTON1 F_BUTTON2 F_BUTTON3'
	poolDictionaries:''
	privateIn:WindowEvent
!

WindowEvent::InputEvent subclass:#KeyboardEvent
	instanceVariableNames:'rawKey'
	classVariableNames:''
	poolDictionaries:''
	privateIn:WindowEvent
!

WindowEvent::InputEvent subclass:#FocusEvent
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:WindowEvent
!

WindowEvent::InputEvent subclass:#ButtonEvent
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:WindowEvent
!

!WindowEvent class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1993 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.
"
!

documentation
"
    Instances of WindowEvent are created for every event coming from
    the graphics device. 
    Usually, they are enqueued by the event dispatcher process into
    a sensors input queue, and dequeued & processed by a windowGroup process
    in its event loop.

    WindowEvents hold the event type and additional information (such as key,
    x/y coordinates etc). Also, windowEvents know how to send themself to some
    destination. To provide a common (single) place where event dispatching is
    implemented, this forwarding is done by a class method here (i.e. not by the
    window group itself).

    The algorithm for event dispatching is:

	- if the destination view has a keyboard focus set,
	  AND the event is a keyboard event,
	  THEN recursively invoke the event dispatching method,
	       sending the event to the focus view (or its delegate, as below)

	- if the destination view has a delegate,
	  AND its a keyboard, button or pointer event,
	  AND the delegate is interested in that event 
	      (i.e. implements & responds to #handlesXXX with true)
	  THEN send the event to the delegate, passing the original view
	       as additional argument

	- if the view has a nonNil controller,
	  AND its a key, button or pointer event,
	  THEN send the event to the controller

	- otherwise send the event to the view


    If the view has a non-nil transformation, the event is sent as a
    #deviceXXX message, passing device coordinates. Typically, subclasses
    of view do not redefine this method and the inherited default method
    translates these device coordinates into logical coordinates and resends
    an XXX message.
    If the view has no transformation, the XXX message is directly sent here.

    For example, a 'buttonPress:button x:x y:y' event leads to sending of
    'aView deviceButtonPress:button x:x y:y' which resends
    'aView buttonPress:button x:(x-logical) y:(y-logical)'

    This allows views which are interested in deviceCoordinates to get them
    (by redefining #deviceXXX) and other views to transparently get & use
    logical coordinates.

    Therefore, for a delegated keyPress messages, the flow is:

	sendEvent
	    view has delegate
		------> ask delegate via 'handlesKeyPress:key inView:view'
		<------ returns true
		------> 'delegate keyPress:key x:x y:y view:view'
			-----> delegate does whatever it wants to do
			       (typically sends the event to some other view)

    for an undelegated message:

	sendEvent
	    view has delegate
		------> ask delegate via 'handlesKeyPress:key inView:view'
		<------ returns false
	    view has controller
		------> 'controller keyPress:key x:x y:y'
	    view has no controller
		view has transformation
		    ----> 'view deviceKeyPress:key x:x y:y'
			  inverse transform x/y
			  ----> 'self keyPress:key x:xLogical y:yLogical'
		view has no transformation
		    ----> 'view keyPress:key x:x y:y'

    [author:]
	Claus Gittinger

    [see also:]
	WindowGroup WindowSensor
	DeviceWorkstation View
	KeyboardMap KeyboardForwarder EventListener

"
! !

!WindowEvent class methodsFor:'instance creation'!

damageFor:aView rectangle:aRectangle
    "create and return a new damage Event for aRectangle
     in aView"

    ^ (self new) for:aView type:#damage arguments:aRectangle

!

for:aView type:aSymbol
    "create and return a new windowEvent for sending
     aSymbol-message with no arguments to aView"

    ^ (self new) for:aView type:aSymbol arguments:#()
!

for:aView type:aSymbol arguments:argArray
    "create and return a new windowEvent for sending
     aSymbol-message with arguments to aView"

    ^ (self new) for:aView type:aSymbol arguments:argArray
! !

!WindowEvent class methodsFor:'event class access'!

buttonEvent
    "return the class used to represent buttonEvents"

    ^ ButtonEvent

    "Created: / 4.4.1997 / 13:45:04 / cg"
    "Modified: / 6.6.1998 / 21:00:29 / cg"
!

clientEvent
    "return the class used to represent clientEvents"

    ^ ClientEvent

    "Created: / 4.4.1997 / 13:58:25 / cg"
    "Modified: / 6.6.1998 / 21:00:36 / cg"
!

focusEvent
    "return the class used to represent focusEvents"

    ^ FocusEvent

    "Modified: / 6.6.1998 / 21:00:50 / cg"
    "Created: / 21.5.1999 / 19:45:25 / cg"
!

inputEvent
    "return the class used to represent inputEvents"

    ^ InputEvent

    "Created: / 13.8.1997 / 23:03:02 / cg"
    "Modified: / 6.6.1998 / 21:00:43 / cg"
!

keyboardEvent
    "return the class used to represent keyboardEvents"

    ^ KeyboardEvent

    "Created: / 4.4.1997 / 13:41:44 / cg"
    "Modified: / 6.6.1998 / 21:00:50 / cg"
! !

!WindowEvent methodsFor:'accessing'!

arguments
    "return the arguments of the event"

    ^ arguments
!

arguments:anArray
    "set the arguments"

    arguments := anArray
!

delegatedFrom
    "return the value of the instance variable 'delegatedFrom' (automatically generated)"

    ^ delegatedFrom!

delegatedFrom:something
    "set the value of the instance variable 'delegatedFrom' (automatically generated)"

    delegatedFrom := something.!

key
    "return the key - nil is returned here.
     This is redefined in KeyboardEvent."

    ^ nil

    "Created: 1.8.1997 / 13:56:21 / cg"
!

rectangle
    "return the damage rectangle"

    ^ arguments "consider this a kludge"
!

type
    "return the type of the event"

    ^ type
!

view
    "return the view, for which the event is for"

    ^ view
!

view:aView
    "set the view, for which the event is for"

    view := aView
!

x
    "the x coordinate - if any.
     nil returned for all but button- and keyEvents"

    ^ nil
!

x:ignoredInteger
    ^ nil
!

y
    "the y coordinate - if any.
     nil returned for all but button- and keyEvents"

    ^ nil
!

y:ignoredInteger
    ^ nil
! !

!WindowEvent methodsFor:'dispatching'!

dispatchTo:anObject
    "send this event to anObject"

    ^ anObject perform:type withArguments:arguments
!

dispatchWithViewArgumentTo:anObject
    "send this event to anObject, and pass an additional view argument"

    arguments size = 0 ifTrue:[
        ^ anObject 
            perform:(type , ':') asSymbol
            with:view
    ].

    ^ anObject 
        perform:(type , 'view:') asSymbol
        withArguments:(arguments copyWith:view)

! !

!WindowEvent methodsFor:'printing & storing'!

displayString
    "return a string for display in inspectors etc."

    ^ self className 
      , '(' , type storeString 
      , ' view: ' , view className 
      , ' args: ' , arguments displayString
      , ')'

    "Created: 7.3.1996 / 14:55:50 / cg"
    "Modified: 20.9.1997 / 11:42:11 / cg"
! !

!WindowEvent methodsFor:'private accessing'!

for:aView type:aSymbol arguments:argArray
    "set the instance variables of the event"

    view := aView.
    type := aSymbol.
    arguments := argArray
! !

!WindowEvent methodsFor:'queries'!

hasAlt
    "return true, if this is a keyboard event, with ALT pressed"

    ^ false

    "Created: 12.4.1997 / 11:04:10 / cg"
!

hasCtrl
    "return true, if this is a keyboard event, with CTRL pressed"

    ^ false

    "Created: 12.4.1997 / 11:04:03 / cg"
!

hasMeta
    "return true, if this is a keyboard event, with META pressed"

    ^ false

    "Created: 12.4.1997 / 11:04:16 / cg"
!

hasShift
    "return true, if this is a keyboard event, with SHIFT pressed"

    ^ false

    "Created: 12.4.1997 / 11:30:59 / cg"
!

isButtonEvent
    "return true, if this event is a button event"

    ^ (type == #buttonPress:x:y:) 
      or:[type == #buttonRelease:x:y:
      or:[type == #'buttonShiftPress:x:y:'
      or:[type == #'buttonMultiPress:x:y:'
      or:[type == #'buttonMotion:x:y:']]]]
!

isButtonMotionEvent
    "return true, if this event is a buttonMotion event"

    ^ (type == #buttonMotion:x:y:)

    "Created: 5.3.1997 / 12:25:43 / cg"
!

isButtonPressEvent
    "return true, if this event is a buttonPress event"

    ^ (type == #buttonPress:x:y:)

    "Created: 5.3.1997 / 12:25:43 / cg"
!

isButtonReleaseEvent
    "return true, if this event is a buttonPress event"

    ^ (type == #buttonRelease:x:y:)

    "Created: 5.3.1997 / 12:25:43 / cg"
!

isConfigureEvent
    "return true, if this is a damage event"

    ^ type == #'configureX:y:width:height:'
!

isDamage
    "return true, if this is a damage event"

    ^ type == #damage
!

isDamageForView:aView
    "return true, if this is a damage event"

    type == #damage ifTrue:[
        view == aView ifTrue:[
            ^ true
        ]
    ].
    ^ false
!

isFocusEvent
    "return true, if this event is a focusIn/focusOut event"

    ^ (type == #focusIn) or:[type == #focusOut]

    "Created: 5.3.1997 / 12:12:37 / cg"
!

isFocusInEvent
    "return true, if this event is a focusIn event"

    ^ (type == #focusIn)

    "Created: 5.3.1997 / 12:18:10 / cg"
!

isInputEvent
    "return true, if this event is an input (pointer, key or button) event"

    ^ false

    "Created: / 21.5.1999 / 19:49:42 / cg"
    "Modified: / 21.5.1999 / 19:50:11 / cg"
!

isKeyEvent
    "return true, if this event is a keyboard event"

    ^ false

    "Modified: / 28.1.1998 / 00:03:17 / cg"
!

isKeyPressEvent
    "return true, if this event is a keyboard press event"

    ^ false

    "Modified: / 28.1.1998 / 00:03:24 / cg"
!

isKeyReleaseEvent
    "return true, if this event is a keyboard release event"

    ^ false

    "Modified: / 28.1.1998 / 00:03:31 / cg"
!

isMapEvent
    "return true, if this is a map event event"

    ^ type == #mapped

    "Created: / 29.1.1998 / 21:52:54 / cg"
!

isMouseWheelEvent
    ^ type == #mouseWheelMotion:x:y:amount:deltaTime:
!

isPointerEnterEvent
    "return true, if this event is a pointer-enter event"

    ^ (type == #'pointerEnter:x:y:')

    "Created: 9.1.1996 / 15:51:24 / cg"
    "Modified: 9.1.1996 / 15:51:40 / cg"
!

isPointerEnterLeaveEvent
    "return true, if this event is a pointer-enter/leave event"

    ^ (type == #'pointerEnter:x:y:') 
      or:[type == #'pointerLeave:']

    "Created: 9.1.1996 / 15:51:18 / cg"
!

isPointerLeaveEvent
    "return true, if this event is a pointer-leave event"

    ^ type == #'pointerLeave:'

    "Created: 9.1.1996 / 15:51:36 / cg"
!

isUnmapEvent
    "return true, if this is an unmap event event"

    ^ type == #unmapped

    "Modified: / 29.1.1998 / 21:53:02 / cg"
!

isUserEvent
    "return true, if this event is a user event (i.e. mouse, keyboard or button)"

    (type == #buttonPress:x:y:) ifTrue:[^ true].
    (type == #buttonRelease:x:y:) ifTrue:[^ true].
    (type == #buttonShiftPress:x:y:) ifTrue:[^ true].
    (type == #buttonMultiPress:x:y:) ifTrue:[^ true].
    (type == #buttonMotion:x:y:) ifTrue:[^ true].

    (type == #keyPress:x:y:) ifTrue:[^ true].
    (type == #keyRelease:x:y:) ifTrue:[^ true].

    (type == #pointerEnter:x:y:) ifTrue:[^ true].
"/    (type == #pointerLeave:) ifTrue:[^ true].

    ^ false

    "Modified: 5.3.1997 / 11:27:40 / cg"
! !

!WindowEvent::ClientEvent methodsFor:'accessing'!

eventData
    "return the value of the instance variable 'eventData' (automatically generated)"

    ^ eventData

    "Created: 4.4.1997 / 17:41:50 / cg"
!

eventData:something
    "set the value of the instance variable 'eventData' (automatically generated)"

    eventData := something.

    "Created: 4.4.1997 / 17:41:57 / cg"
! !

!WindowEvent::InputEvent class methodsFor:'class initialization'!

initialize
    F_SHIFT := 16r001.
    F_CTRL  := 16r002.
    F_ALT   := 16r004.
    F_META  := 16r008.

    F_BUTTON1 := 16r100.
    F_BUTTON2 := 16r200.
    F_BUTTON3 := 16r400.

    "
     self initialize
    "

    "Modified: 13.8.1997 / 22:16:17 / cg"
! !

!WindowEvent::InputEvent methodsFor:'accessing'!

hasShift:shift ctrl:ctrl alt:alt meta:meta button1:b1 button2:b2 button3:b3
    |f "{ Class: SmallInteger }"|

    f := 0.
    shift ifTrue:[f := f bitOr:F_SHIFT].
    ctrl ifTrue:[f := f bitOr:F_CTRL].
    alt ifTrue:[f := f bitOr:F_ALT].
    meta ifTrue:[f := f bitOr:F_META].
    b1 ifTrue:[f := f bitOr:F_BUTTON1].
    b2 ifTrue:[f := f bitOr:F_BUTTON2].
    b3 ifTrue:[f := f bitOr:F_BUTTON3].
    modifierFlags := f.

    "Created: 13.8.1997 / 22:17:56 / cg"
!

hasShift:shift hasCtrl:ctrl hasAlt:alt hasMeta:meta
    |f "{ Class: SmallInteger }"|

    f := 0.
    shift ifTrue:[f := f bitOr:F_SHIFT].
    ctrl ifTrue:[f := f bitOr:F_CTRL].
    alt ifTrue:[f := f bitOr:F_ALT].
    meta ifTrue:[f := f bitOr:F_META].
    modifierFlags := f.

    "Created: 13.8.1997 / 22:02:09 / cg"
!

hasShift:shift hasCtrl:ctrl hasAlt:alt hasMeta:meta hasButton1:b1 hasButton2:b2 hasButton3:b3
    |f "{ Class: SmallInteger }"|

    f := 0.
    shift ifTrue:[f := f bitOr:F_SHIFT].
    ctrl ifTrue:[f := f bitOr:F_CTRL].
    alt ifTrue:[f := f bitOr:F_ALT].
    meta ifTrue:[f := f bitOr:F_META].
    b1 ifTrue:[f := f bitOr:F_BUTTON1].
    b2 ifTrue:[f := f bitOr:F_BUTTON2].
    b3 ifTrue:[f := f bitOr:F_BUTTON3].
    modifierFlags := f.

    "Created: 13.8.1997 / 22:17:25 / cg"
!

modifierFlags
    ^ modifierFlags
!

modifierFlags:flagBits
    modifierFlags := flagBits
! !

!WindowEvent::InputEvent methodsFor:'queries'!

hasAlt
    "return true, if this is an event, with ALT pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_ALT) ~~ 0

    "Created: 13.8.1997 / 22:02:23 / cg"
    "Modified: 21.8.1997 / 19:41:11 / cg"
!

hasButton1
    "return true, if this is an event, with the left mouse button pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_BUTTON1) ~~ 0

    "Created: 13.8.1997 / 22:16:35 / cg"
    "Modified: 21.8.1997 / 19:41:40 / cg"
!

hasButton2
    "return true, if this is an event, with the middle mouse button pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_BUTTON2) ~~ 0

    "Created: 13.8.1997 / 22:16:43 / cg"
    "Modified: 21.8.1997 / 19:41:47 / cg"
!

hasButton3
    "return true, if this is an event, with the right mouse button pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_BUTTON3) ~~ 0

    "Created: 13.8.1997 / 22:16:49 / cg"
    "Modified: 21.8.1997 / 19:41:52 / cg"
!

hasCtrl
    "return true, if this is an event, with CTRL pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_CTRL) ~~ 0

    "Created: 13.8.1997 / 22:02:29 / cg"
    "Modified: 21.8.1997 / 19:41:21 / cg"
!

hasMeta
    "return true, if this is an event, with META pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_META) ~~ 0

    "Created: 13.8.1997 / 22:02:59 / cg"
    "Modified: 21.8.1997 / 19:41:27 / cg"
!

hasShift
    "return true, if this is an event, with SHIFT pressed"

    modifierFlags isNil ifTrue:[^ false].
    ^ (modifierFlags bitAnd:F_SHIFT) ~~ 0

    "Created: 13.8.1997 / 22:03:09 / cg"
    "Modified: 21.8.1997 / 19:41:34 / cg"
!

isInputEvent
    ^ true

    "Created: / 21.5.1999 / 19:49:30 / cg"
! !

!WindowEvent::KeyboardEvent methodsFor:'accessing'!

key
    "return the key of the key-event."

    ^ arguments at:1

    "Created: 1.8.1997 / 13:55:19 / cg"
!

key:aCharacterOrSymbol
    "change the key of the key-event."

    arguments at:1 put:aCharacterOrSymbol

    "Created: 1.8.1997 / 13:55:19 / cg"
!

rawKey
    ^ rawKey

    "Created: 4.4.1997 / 13:47:15 / cg"
!

rawKey:aKey
    rawKey := aKey

    "Created: 4.4.1997 / 13:47:10 / cg"
!

x
    "return the x coordinate of the key-event
     (mouse position at the time of the key-event)."

    ^ arguments at:2

    "Created: 1.8.1997 / 13:57:27 / cg"
!

xy:anInteger
    "change the x coordinate of the key-event"

    ^ arguments at:2 put:anInteger

!

y
    "return the y coordinate of the key-event
     (mouse position at the time of the key-event)."

    ^ arguments at:3

    "Created: 1.8.1997 / 13:55:19 / cg"
    "Modified: 1.8.1997 / 13:57:42 / cg"
!

y:anInteger
    "change the y coordinate of the key-event"

    ^ arguments at:3 put:anInteger

! !

!WindowEvent::KeyboardEvent methodsFor:'queries'!

isKeyEvent
    "return true, if this event is a keyboard event"

    ^ true

    "Created: 4.4.1997 / 13:39:59 / cg"
!

isKeyPressEvent
    "return true, if this event is a keyboard press event"

    ^ (type == #keyPress:x:y:)

    "Created: / 28.1.1998 / 00:02:40 / cg"
    "Modified: / 28.1.1998 / 00:02:52 / cg"
!

isKeyReleaseEvent
    "return true, if this event is a keyboard release event"

    ^ (type == #keyRelease:x:y:)

    "Created: / 28.1.1998 / 00:02:48 / cg"
! !

!WindowEvent::FocusEvent methodsFor:'queries'!

isFocusEvent
    "return true, if this event is a focus event"

    ^ true

    "Created: / 21.5.1999 / 19:44:47 / cg"
!

isFocusInEvent
    "return true, if this event is a focusIn event"

    ^ (type == #focusIn)

    "Created: / 21.5.1999 / 19:45:04 / cg"
! !

!WindowEvent::ButtonEvent methodsFor:'accessing'!

state
    "return the button state of the button-event
     (mouse button bits at the time of the event)."

    ^ arguments at:1

    "Created: / 12.11.1998 / 16:21:18 / cg"
!

x
    "return the x coordinate of the button-event
     (mouse position at the time of the event)."

    ^ arguments at:2

    "Created: 1.8.1997 / 13:58:15 / cg"
!

x:anInteger
    "change the x coordinate of the button-event"

    ^ arguments at:2 put:anInteger

    "Created: 1.8.1997 / 13:58:15 / cg"
!

y
    "return the y coordinate of the button-event
     (mouse position at the time of the event)."

    ^ arguments at:3

    "Created: 1.8.1997 / 13:58:07 / cg"
!

y:anInteger
    "change the y coordinate of the button-event"

    ^ arguments at:3 put:anInteger

    "Created: 1.8.1997 / 13:58:15 / cg"
! !

!WindowEvent::ButtonEvent methodsFor:'queries'!

isButtonEvent
    "return true, if this event is a button event"

    ^ true

    "Created: 4.4.1997 / 13:44:11 / cg"
!

isButtonMotionEvent
    "return true, if this event is a buttonMotion event"

    ^ (type == #buttonMotion:x:y:)

    "Created: 4.4.1997 / 13:44:22 / cg"
!

isButtonPressEvent
    "return true, if this event is a buttonPress event"

    ^ (type == #buttonPress:x:y:)

    "Created: 4.4.1997 / 13:44:22 / cg"
!

isButtonReleaseEvent
    "return true, if this event is a buttonRelease event"

    ^ (type == #buttonRelease:x:y:)

    "Created: 4.4.1997 / 13:44:22 / cg"
! !

!WindowEvent class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libview/WindowEvent.st,v 1.64 1999-12-08 20:39:31 ca Exp $'
! !