ModalBox.st
author claus
Mon, 13 Dec 1993 18:10:47 +0100
changeset 17 be9898c59977
parent 12 9f0995fac1fa
child 21 7b3da079729d
permissions -rw-r--r--
*** empty log message ***

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

StandardSystemView subclass:#ModalBox
       instanceVariableNames:'haveControl shadowView exclusiveKeyboard'
       classVariableNames:'PopShadow'
       poolDictionaries:''
       category:'Views-Basic'
!

ModalBox comment:'

COPYRIGHT (c) 1990 by Claus Gittinger
              All Rights Reserved

$Header: /cvs/stx/stx/libview/ModalBox.st,v 1.6 1993-12-13 17:10:15 claus Exp $

written Jan 90 by claus
'!

!ModalBox class methodsFor:'documentation'!

documentation
"
this class implements modal boxes; ModalBoxes are different from
others, in that they take complete control over the display, until 
all processing is done (i.e. other views will not get any events
while the box is active).

class variables:

PopShadow       <Boolean>       if true, modalBoxes will show a shadow

"
! !

!ModalBox class methodsFor:'initialization'!

initialize
    super initialize.
    Display notNil ifTrue:[
        PopShadow := self classResources name:'POPUP_SHADOW' default:false
    ]
! !

!ModalBox class methodsFor:'instance creation'!

new
    ^ super on:ModalDisplay
! !

!ModalBox methodsFor:'initialize / release'!

initialize
    super initialize.

    haveControl := false.
    exclusiveKeyboard := false.

    PopShadow ifTrue:[
        shadowView := (ShadowView on:device) for:self
    ]
!

initStyle
    super initStyle.
    self is3D ifTrue:[
        borderWidth := 0.
        self level:2
    ]
!

initEvents
    super initEvents.
    self enableKeyEvents
!

addToCurrentProject
    "ignored here"

    ^ self
!

destroy
    shadowView notNil ifTrue:[
        shadowView destroy.
        shadowView := nil
    ].
    self leaveControl. "just to make sure"
    super destroy.
!

create
    super create.
    PopShadow ifFalse:[
        self saveUnder:true
    ]
!

createOnTop
    ^ true
! !

!ModalBox methodsFor:'show / hide'!

mapped
    "wait till visible for grabbing"

    super mapped.

    "take it away from any popup menu possibly still active"

    device ungrabKeyboard.
    ActiveGrab := nil.
    device grabPointerIn:drawableId.
    device ungrabPointer.

    exclusiveKeyboard ifTrue:[
        device grabKeyboardIn:drawableId.
    ].

    "this will be changed as soon as I find out, where the
     timing problem is .... close your eyes please"

    ActiveGrab := nil.
    ModalDisplay ungrabPointer.
    ModalDisplay synchronizeOutput.
    Display ungrabPointer.
    Display synchronizeOutput.

    device setInputFocusTo:drawableId.
!

fixPosition:aPoint
    "make sure, that the box is visible by shifting it
     into the visible screen area if nescessary"

    self origin:aPoint.
    ((top + height) > (device height)) ifTrue:[
        self top:(device height - height)
    ].
    ((left + width) > (device width)) ifTrue:[
        self left:(device width - width)
    ].
    (top < 0) ifTrue:[
        self top:0
    ].
    (left < 0) ifTrue:[
        self left:0
    ].
!

positionOffset
    "return the delta, by which the box should be
     displaced from the mouse pointer. Usually redefined in
     subclasses to have some ok-button appear under
     the pointer."

    ^ (width // 2) @ (height // 2)
!

show
    "make myself visible (at the last position) and take control"

    self fixSize.
    self makeVisible
!

showAt:aPoint
    "make myself visible at aPoint.
     Fix position to make box fully visible"

    self fixSize.
    self fixPosition:aPoint.
    self makeVisible
!

showAtPointer
    "make myself visible at mouse pointer shifted to have
     convenient button under cursor.
     Fix position to make box fully visible"

    self fixSize.
    self showAt:(device pointerPosition - self positionOffset).
!

showAtPointerNotCovering:aView
    "make myself visible at mouse pointer shifted to have
     convenient button under cursor.
     Fix position to make box fully visible or to make sure that
     aView is not covered."

    |pos|

    pos := device pointerPosition - self positionOffset.
    ((Rectangle origin:pos extent:self extent) intersects:
     (aView origin corner: aView corner)) ifTrue:[
        pos x:(aView origin x + aView width)
    ].
    self showAt:pos
!

hide
    "make myself invisible and leave control"

    shadowView notNil ifTrue:[shadowView unrealize].
    self unrealize.
    device synchronizeOutput. 
    self leaveControl.
! !

!ModalBox methodsFor:'private'!

makeVisible
    "make myself visible (at the last position) and take control"

    Display synchronizeOutput.      "show all buffered drawing"
    shadowView notNil ifTrue:[shadowView realize].
    self raise.
    self realize.
    self takeControl
!

takeControl
    haveControl := true.

"
    exclusiveKeyboard ifTrue:[
        device grabKeyboardIn:drawableId.
    ].
    device setInputFocusTo:drawableId.
"

    "this will be changed as soon as I find out, where the
     timing problem is .... close your eyes please"

    ActiveGrab := nil.
    device ungrabKeyboard.
    device grabPointerIn:drawableId.
    device ungrabPointer.


    "this is a kludge - we do not have multiple processes, therefore
     we start another dispatch loop, which exits when control is lost"

    device dispatchWhile:[haveControl]
!

leaveControl
    haveControl := false.
    exclusiveKeyboard ifTrue:[
        device ungrabKeyboard
    ]
! !