ModalBox.st
changeset 12 9f0995fac1fa
parent 6 7ee0cfde237d
child 17 be9898c59977
--- a/ModalBox.st	Sat Dec 11 02:34:56 1993 +0100
+++ b/ModalBox.st	Sat Dec 11 02:36:44 1993 +0100
@@ -11,7 +11,7 @@
 "
 
 StandardSystemView subclass:#ModalBox
-       instanceVariableNames:'haveControl shadowView'
+       instanceVariableNames:'haveControl shadowView exclusiveKeyboard'
        classVariableNames:'PopShadow'
        poolDictionaries:''
        category:'Views-Basic'
@@ -22,7 +22,7 @@
 COPYRIGHT (c) 1990 by Claus Gittinger
               All Rights Reserved
 
-$Header: /cvs/stx/stx/libview/ModalBox.st,v 1.4 1993-10-13 02:43:51 claus Exp $
+$Header: /cvs/stx/stx/libview/ModalBox.st,v 1.5 1993-12-11 01:31:00 claus Exp $
 
 written Jan 90 by claus
 '!
@@ -47,7 +47,9 @@
 
 initialize
     super initialize.
-    PopShadow := self classResources name:'POPUP_SHADOW' default:false
+    Display notNil ifTrue:[
+        PopShadow := self classResources name:'POPUP_SHADOW' default:false
+    ]
 ! !
 
 !ModalBox class methodsFor:'instance creation'!
@@ -62,13 +64,18 @@
     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
-    ].
-
-    PopShadow ifTrue:[
-        shadowView := (ShadowView on:device) for:self
     ]
 !
 
@@ -84,8 +91,12 @@
 !
 
 destroy
+    shadowView notNil ifTrue:[
+        shadowView destroy.
+        shadowView := nil
+    ].
+    self leaveControl. "just to make sure"
     super destroy.
-    shadowView notNil ifTrue:[shadowView destroy]
 !
 
 create
@@ -105,21 +116,34 @@
     "wait till visible for grabbing"
 
     super mapped.
-    device grabKeyboardIn:drawableId.
+
+    "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.
 !
 
-show
-    "make myself visible and take control"
+fixPosition:aPoint
+    "make sure, that the box is visible by shifting it
+     into the visible screen area"
 
-    self fixSize.
-    shadowView notNil ifTrue:[shadowView realize].
-    self raise.
-    self realize.
-    self takeControl
-!
-
-showAt:aPoint
     self origin:aPoint.
     ((top + height) > (device height)) ifTrue:[
         self top:(device height - height)
@@ -133,44 +157,98 @@
     (left < 0) ifTrue:[
         self left:0
     ].
-    self show
+!
+
+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
-    self showAt:(device pointerPosition - ((width // 2) @ (height // 2)))
+    "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
-    |x y|
+    "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|
 
-    x := device pointerPosition x - (width // 2).
-    y := device pointerPosition y - (height // 2).
-    (((x @ y) corner:((x + width) @ (y + height))) intersects:
+    pos := device pointerPosition - self positionOffset.
+    ((Rectangle origin:pos extent:self extent) intersects:
      (aView origin corner: aView corner)) ifTrue:[
-        x := aView origin x + aView width
+        pos x:(aView origin x + aView width)
     ].
-    self showAt:(x @ y)
+    self showAt:pos
 !
 
 hide
     "make myself invisible and leave control"
 
+    shadowView notNil ifTrue:[shadowView unrealize].
     self unrealize.
-    device synchronizeOutput.
-    shadowView notNil ifTrue:[shadowView 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.
 
 "
-    device grabKeyboardIn:drawableId.
+    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"
 
@@ -179,5 +257,7 @@
 
 leaveControl
     haveControl := false.
-    device ungrabKeyboard
+    exclusiveKeyboard ifTrue:[
+        device ungrabKeyboard
+    ]
 ! !