MenuPanel.st
changeset 2199 61ef4fe363e7
parent 2187 020c575c4d64
child 2214 8eefad87cf62
--- a/MenuPanel.st	Wed Sep 18 21:40:19 2002 +0200
+++ b/MenuPanel.st	Thu Sep 19 09:44:08 2002 +0200
@@ -15,19 +15,19 @@
 
 View subclass:#MenuPanel
 	instanceVariableNames:'adornment shadowView mapTime mustRearrange superMenu
-		shortKeyInset selection items groupSizes receiver 
-		enabled onLevel offLevel fgColor activeFgColor
-		lastActiveMenu activeBgColor disabledFgColor
-		disabledEtchedFgColor groupDividerSize itemSpace fitFirstPanel
-		rightArrow rightArrowShadow selectionFrameBrightColor
-		selectionFrameDarkColor buttonLightColor buttonShadowColor
-		buttonHalfLightColor buttonHalfShadowColor enteredItem
-		buttonEnteredBgColor prevFocusView previousPointerGrab
-		previousKeyboardGrab relativeGrabOrigin hasImplicitGrap
-		iconIndicationOff iconIndicationOn iconRadioGroupOff
-		iconRadioGroupOn iconIndicationDisabledOff
-		iconIndicationDisabledOn iconRadioGroupDisabledOff
-		iconRadioGroupDisabledOn scrollActivity stillPressedAction'
+		shortKeyInset selection items groupSizes receiver enabled onLevel
+		offLevel fgColor activeFgColor lastActiveMenu activeBgColor
+		disabledFgColor disabledEtchedFgColor groupDividerSize itemSpace
+		fitFirstPanel rightArrow rightArrowShadow
+		selectionFrameBrightColor selectionFrameDarkColor
+		buttonLightColor buttonShadowColor buttonHalfLightColor
+		buttonHalfShadowColor enteredItem buttonEnteredBgColor
+		prevFocusView previousPointerGrab previousKeyboardGrab
+		relativeGrabOrigin hasImplicitGrap iconIndicationOff
+		iconIndicationOn iconRadioGroupOff iconRadioGroupOn
+		iconIndicationDisabledOff iconIndicationDisabledOn
+		iconRadioGroupDisabledOff iconRadioGroupDisabledOn scrollActivity
+		stillPressedAction'
 	classVariableNames:'InitialSelectionQuerySignal DefaultAdornment ShortcutKeyOffset
 		DefaultGroupDividerSize DefaultHilightLevel DefaultLevel
 		DefaultButtonItemSpace DefaultForegroundColor
@@ -795,6 +795,7 @@
     self superMenu notNil ifTrue:[
         ^ self topMenu accept:anItem
     ].
+    self openDelayed:nil.
     self scrollActivity stop.
     self selection:nil.
 
@@ -947,10 +948,13 @@
 !
 
 acceptItem:anItem inMenu:aMenu
-    |tgState|
+    |tgState topMenu|
+
+    topMenu := self topMenu.
+    topMenu openDelayed:nil.
 
     (anItem isNil or:[anItem hideMenuOnActivated]) ifTrue:[
-        self topMenu accept:anItem
+        topMenu accept:anItem
     ] ifFalse:[
         anItem canAccept ifTrue:[
             tgState := anItem toggleIndication.
@@ -2793,13 +2797,15 @@
 buttonRelease:button x:x y:y
     "button release action; accept selection and close all views
     "
-    |topMenu dstMenu item srcPoint dstPoint|
+    |topMenu dstMenu item srcPoint dstPoint subm|
+
+    topMenu := self topMenu.
+    topMenu openDelayed:nil.
 
     self scrollActivity stop ifTrue:[
         ^ self
     ].
 
-    topMenu := self topMenu.
     dstMenu := topMenu activeMenu.
 
     (    dstMenu selection notNil
@@ -2817,18 +2823,26 @@
 
                 (selection isNil and:[self isPopUpView not]) ifTrue:[
                     self accept:nil
-                ]
-            ] ifFalse:[
-                item currentSubmenu isNil ifTrue:[
-                    dstPoint := dstMenu translateGrabPoint:srcPoint.
-
-                    (dstMenu itemAtX:(dstPoint x) y:(dstPoint y)) == dstMenu selection ifFalse:[
-                        item := nil
-                    ].
-                    topMenu acceptItem:item inMenu:dstMenu.
-                ]
+                ].
+                ^ self
+
             ].
-            ^ self
+            subm := item currentSubmenu.
+
+            subm ifNotNil:[
+                subm shown ifTrue:[^ self].
+                "/ test whether any action is assigned to the menu
+                "/ if not ignorre accept
+                item hasDelayedMenu ifFalse:[^ self].
+                "/ handle action defined for the delayed menu
+            ].
+            dstPoint := dstMenu translateGrabPoint:srcPoint.
+
+            (dstMenu itemAtX:(dstPoint x) y:(dstPoint y)) == dstMenu selection ifFalse:[
+                item := nil
+            ].
+            topMenu acceptItem:item inMenu:dstMenu.
+          ^ self
         ].
 
         (selection notNil and:[dstMenu == self]) ifTrue:[
@@ -3074,7 +3088,7 @@
 handleButtonPressAtPoint:aPoint
     "a button pressed; open or close the corresponding submenus
     "
-    |triggerOnDown item sensor yS direction|
+    |triggerOnDown item sensor direction|
 
     item := self itemAtPoint:aPoint.
 
@@ -3093,16 +3107,10 @@
     self openMenuOnSelect:nil.
 
     item isNil ifTrue:[^ self].
+    item hasDelayedMenu ifTrue:[^ self].
 
     triggerOnDown := item triggerOnDown.
 
-    (triggerOnDown not
-     and:[item delayMenu]
-    ) ifTrue:[
-self halt.
-    ].
-
-
     ((item isToggle or:[triggerOnDown])
      and:[item canAccept
      and:[item == self selection]]
@@ -3267,7 +3275,7 @@
 handleReturnPressed
     "any key is pressed
     "
-    |sensor|
+    |sensor subm|
 
     selection isNil ifTrue:[
         superMenu notNil ifTrue:[
@@ -3278,7 +3286,15 @@
         ^ self
     ].
     selection hasSubmenu ifTrue:[
-        ^ selection toggleSubmenuVisibility
+        selection hasDelayedMenu ifFalse:[
+            ^ selection toggleSubmenuVisibility
+        ].
+        subm := selection currentSubmenu.
+
+        (subm notNil and:[subm shown]) ifTrue:[
+            ^ selection toggleSubmenuVisibility
+        ].
+        self openDelayed:nil
     ].
     self accept.
 
@@ -3295,7 +3311,6 @@
         sensor hasKeyPressEventFor:nil.
 
     ] whileTrue.
-
 !
 
 pointerEntersItem:anItemOrNil
@@ -3973,11 +3988,16 @@
     start := aStart max:1.
     stop  := aStop  min:(items size).
 
-    start to:stop do:[:i| |item menu seq isItem|
-        item   := items at:i.
-        isItem := aOneArgBlock value:item.
-
-        (isItem or:[item hasSubmenu]) ifTrue:[
+    start to:stop do:[:i| |item menu seq isItem test|
+        item := items at:i.
+        test := isItem := aOneArgBlock value:item.
+
+        test ifFalse:[
+            item hasSubmenu ifTrue:[
+                test := item hasDelayedMenu not
+            ]
+        ].
+        test ifTrue:[
             (item enabled and:[item isVisible]) ifTrue:[
                 isItem ifTrue:[ ^ OrderedCollection with:i ].
 
@@ -4713,6 +4733,30 @@
     ^ self selection notNil
 !
 
+openDelayed:anItem
+    |block|
+
+    superMenu ifNotNil:[
+        ^ superMenu openDelayed:anItem
+    ].
+    block := self menuAdornmentAt:#delayedBlock.
+    block ifNotNil:[ Processor removeTimedBlock:block ].
+
+    anItem ifNil:[
+        block ifNotNil:[ self menuAdornmentAt:#delayedBlock put:nil ].
+      ^ block notNil
+    ].
+    self menuAdornmentAt:#delayedBlock put:block.
+
+    block := [  self menuAdornmentAt:#delayedBlock put:nil.
+                anItem openDelayedSubmenu
+             ].
+
+    Processor removeTimedBlock:block.
+    Processor addTimedBlock:block afterSeconds:0.5.
+  ^ true
+!
+
 selection
     "returns current selected item or nil
     "
@@ -4738,6 +4782,7 @@
     selection == newSel ifTrue:[
         ^ self
     ].
+    self openDelayed:nil.
 
     (item := selection) notNil ifTrue:[
         selection := nil.
@@ -4903,7 +4948,11 @@
 canAccept
     "returns true if item is acceptable
     "
-  ^ (self enabled and:[self hasSubmenu not])
+    self enabled    ifFalse:[ ^ false].
+    self hasSubmenu ifFalse:[ ^ true ].
+
+    self hasDelayedMenu ifFalse:[^ false ].
+  ^ subMenu isNil or:[subMenu shown not]
 !
 
 toggleIndication
@@ -5596,25 +5645,56 @@
 hideSubmenu
     "hide submenu
     "
+    self hideSubmenu:subMenu.
+!
+
+hideSubmenu:aSubmenu
+    "hide submenu
+    "
     |id|
 
-    subMenu notNil ifTrue:[
-        subMenu realized ifFalse:[
-            (id := subMenu id) notNil ifTrue:[
-                menuPanel device unmapWindow:id
-            ]
-        ] ifTrue:[
-           subMenu hide
-        ].
-
-        subMenu windowGroup:nil.
-        menuPanel windowGroup removeView:subMenu.
-
-        "/ release menu if derived from channel
-        submenuChannel notNil ifTrue:[
+    aSubmenu ifNil:[^ self].
+
+    aSubmenu realized ifFalse:[
+        id := aSubmenu id.
+        id ifNotNil:[ menuPanel device unmapWindow:id ]
+    ] ifTrue:[
+        aSubmenu hide
+    ].
+
+    aSubmenu  windowGroup:nil.
+    menuPanel windowGroup removeView:aSubmenu.
+
+    "/ release menu if derived from channel
+    submenuChannel notNil ifTrue:[
+        subMenu == aSubmenu ifTrue:[
             subMenu := nil
         ]
-     ].
+    ].
+!
+
+openDelayedSubmenu
+    "called to open now my delayed submenu
+    "
+    |subm|
+
+    (self isSelected and:[menuPanel shown]) ifFalse:[^ self].
+
+    subMenu ifNotNil:[
+        subMenu realized ifTrue:[
+            "/ already open
+            ^ self
+        ].
+    ].
+    subm := self setupSubmenu.
+    subm ifNil:[^ self].
+
+    self openSubmenu.
+
+    (subm == subMenu and:[self isSelected]) ifFalse:[
+        "/ closed during building or opening the submenu
+        self hideSubmenu:subm.
+    ].
 !
 
 openSubmenu
@@ -6833,6 +6913,18 @@
     ^ false
 !
 
+hasDelayedMenu
+    "returns true if a delayed menu exists
+    "
+    (subMenu isNil and:[submenuChannel isNil]) ifTrue:[
+        ^ false
+    ].
+    (value isNil and:[indication isNil and:[choice isNil]]) ifTrue:[
+        ^ false
+    ].
+    ^ true
+!
+
 hasIndication
     "returns true if on/off indication exists
     "
@@ -6997,19 +7089,23 @@
 
     isSelected ifFalse:[
         self invalidate.
-        self hideSubmenu.
-    ] ifTrue:[
-        menuPanel realized ifTrue:[
-            (indication isNil or:[isButton not]) ifTrue:[
-                self invalidate
-            ].
-
-            (menuPanel isPopUpView not or:[menuPanel openMenuOnSelect]) ifTrue:[
-                (subMenu := self setupSubmenu) notNil ifTrue:[
-                    self openSubmenu
-                ]
-            ]
-        ]
+      ^ self hideSubmenu.
+    ].
+    menuPanel realized ifFalse:[ ^ self ].
+
+    (indication isNil or:[isButton not]) ifTrue:[
+        self invalidate
+    ].
+    self hasSubmenu ifFalse:[ ^ self].
+
+    (menuPanel isPopUpView not or:[menuPanel openMenuOnSelect]) ifFalse:[
+        ^ self
+    ].
+    self hasDelayedMenu ifTrue:[
+        menuPanel openDelayed:self
+    ] ifFalse:[
+        subMenu := self setupSubmenu.
+        subMenu ifNotNil:[ self openSubmenu ].
     ].
 ! !
 
@@ -7184,6 +7280,7 @@
 !MenuPanel class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/MenuPanel.st,v 1.323 2002-09-12 23:11:39 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/MenuPanel.st,v 1.324 2002-09-19 07:44:08 ca Exp $'
 ! !
+
 MenuPanel initialize!