PullDownMenu.st
changeset 202 01f3cbb8e20e
parent 174 d80a6cc3f9b2
child 205 6814c0bf8df8
equal deleted inserted replaced
201:d2888811c664 202:01f3cbb8e20e
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 SimpleView subclass:#PullDownMenu
    13 SimpleView subclass:#PullDownMenu
    14        instanceVariableNames:'receiver menus titles selectors activeMenuNumber
    14 	 instanceVariableNames:'receiver menus titles selectors activeMenuNumber
    15 			      showSeparatingLines topMargin
    15                 showSeparatingLines topMargin fgColor bgColor activeFgColor
    16 			      fgColor bgColor activeFgColor activeBgColor
    16                 activeBgColor onLevel offLevel edgeStyle keepMenu toggleKeep
    17 			      onLevel offLevel edgeStyle
    17                 raiseTopWhenActivated'
    18 			      keepMenu toggleKeep raiseTopWhenActivated'
    18 	 classVariableNames:'DefaultFont DefaultViewBackground DefaultForegroundColor
    19        classVariableNames:'DefaultFont
    19                 DefaultBackgroundColor DefaultHilightForegroundColor
    20 			   DefaultViewBackground 
    20                 DefaultHilightBackgroundColor DefaultLevel DefaultHilightLevel
    21 			   DefaultForegroundColor 
    21                 DefaultShadowColor DefaultLightColor DefaultEdgeStyle
    22 			   DefaultBackgroundColor
    22                 DefaultKeepMenu DefaultToggleKeep DefaultSeparatingLines'
    23 			   DefaultHilightForegroundColor 
    23 	 poolDictionaries:''
    24 			   DefaultHilightBackgroundColor
    24 	 category:'Views-Menus'
    25 			   DefaultLevel DefaultHilightLevel
       
    26 			   DefaultShadowColor DefaultLightColor 
       
    27 			   DefaultEdgeStyle DefaultKeepMenu DefaultToggleKeep
       
    28 			   DefaultSeparatingLines'
       
    29        poolDictionaries:''
       
    30        category:'Views-Menus'
       
    31 !
    25 !
    32 
    26 
    33 !PullDownMenu class methodsFor:'documentation'!
    27 !PullDownMenu class methodsFor:'documentation'!
    34 
    28 
    35 copyright
    29 copyright
    42  inclusion of the above copyright notice.   This software may not
    36  inclusion of the above copyright notice.   This software may not
    43  be provided or otherwise made available to, or used by, any
    37  be provided or otherwise made available to, or used by, any
    44  other person.  No title to or ownership of the software is
    38  other person.  No title to or ownership of the software is
    45  hereby transferred.
    39  hereby transferred.
    46 "
    40 "
    47 !
       
    48 
       
    49 version
       
    50     ^ '$Header: /cvs/stx/stx/libwidg/PullDownMenu.st,v 1.26 1995-11-11 16:22:17 cg Exp $'
       
    51 !
    41 !
    52 
    42 
    53 documentation
    43 documentation
    54 "
    44 "
    55     PullDown menu provides the top (always visible) part of these menus. 
    45     PullDown menu provides the top (always visible) part of these menus. 
   328 	     putLabels:#('copy' 'cut' 'paste')
   318 	     putLabels:#('copy' 'cut' 'paste')
   329 	     selectors:#(copySelection cut paste)
   319 	     selectors:#(copySelection cut paste)
   330 	     receiver:textView.
   320 	     receiver:textView.
   331 	top open
   321 	top open
   332 "
   322 "
       
   323 !
       
   324 
       
   325 version
       
   326     ^ '$Header: /cvs/stx/stx/libwidg/PullDownMenu.st,v 1.27 1995-11-23 14:35:27 cg Exp $'
       
   327 ! !
       
   328 
       
   329 !PullDownMenu class methodsFor:'instance creation'!
       
   330 
       
   331 labels:titleArray
       
   332     "create and return a new PullDownMenu"
       
   333 
       
   334     ^ self new labels:titleArray
   333 ! !
   335 ! !
   334 
   336 
   335 !PullDownMenu class methodsFor:'defaults'!
   337 !PullDownMenu class methodsFor:'defaults'!
   336 
   338 
   337 updateStyleCache
   339 updateStyleCache
   382     "
   384     "
   383      PullDownMenu updateStyleCache
   385      PullDownMenu updateStyleCache
   384     "
   386     "
   385 ! !
   387 ! !
   386 
   388 
   387 !PullDownMenu class methodsFor:'instance creation'!
   389 !PullDownMenu methodsFor:'accessing'!
       
   390 
       
   391 at:aString putLabels:labels selector:selector args:args receiver:anObject
       
   392     "create and set the menu under the title, aString"
       
   393 
       
   394     |menuView|
       
   395 
       
   396     menuView := MenuView labels:labels
       
   397 		       selector:selector
       
   398 			   args:args
       
   399 		       receiver:anObject
       
   400 			    for:self.
       
   401     self at:aString putMenu:menuView
       
   402 !
       
   403 
       
   404 at:aString putLabels:labels selectors:selectors args:args receiver:anObject
       
   405     "create and set the menu under the title, aString"
       
   406 
       
   407     |menuView|
       
   408 
       
   409     menuView := MenuView labels:labels
       
   410 		      selectors:selectors
       
   411 			   args:args
       
   412 		       receiver:anObject
       
   413 			    for:self.
       
   414     self at:aString putMenu:menuView
       
   415 !
       
   416 
       
   417 at:aString putLabels:labels selectors:selectors receiver:anObject
       
   418     "create and set the menu under the title, aString"
       
   419 
       
   420     |menuView|
       
   421 
       
   422     menuView := MenuView labels:labels
       
   423 		      selectors:selectors
       
   424 		       receiver:anObject
       
   425 			    for:self.
       
   426     self at:aString putMenu:menuView
       
   427 !
       
   428 
       
   429 at:aString putMenu:aMenu
       
   430     "set the menu under the title, aString"
       
   431 
       
   432     |index|
       
   433 
       
   434     index := self indexOf:aString.
       
   435     (index == 0) ifTrue:[
       
   436 	self error:'no such menu entry'.
       
   437 	^ nil
       
   438     ].
       
   439 
       
   440 "/ not needed:
       
   441 "/    aMenu origin:((left + (self titleLenUpTo:index)) 
       
   442 "/                  @
       
   443 "/                  (height + aMenu borderWidth)).
       
   444     aMenu hiddenOnRealize:true.
       
   445     menus at:index put:aMenu.
       
   446     aMenu masterView:self.
       
   447 !
       
   448 
       
   449 labels
       
   450     "return the menu-titles (group-headers)"
       
   451 
       
   452     ^ titles
       
   453 !
   388 
   454 
   389 labels:titleArray
   455 labels:titleArray
   390     "create and return a new PullDownMenu"
   456     "define the menu-titles (group-headers)"
   391 
   457 
   392     ^ self new labels:titleArray
   458     |numberOfLabels|
   393 ! !
   459 
   394 
   460     numberOfLabels := titleArray size.
   395 !PullDownMenu methodsFor:'initialize / release'!
   461     menus := Array new:numberOfLabels.
   396 
   462     titles := Array new:numberOfLabels.
   397 initialize
   463 
   398     super initialize.
   464     titleArray keysAndValuesDo:[:index :entry |
   399 
   465 	|e|
   400     font := font on:device.
   466 
   401     self origin:(0.0 @ 0.0)
   467 	entry isImage ifTrue:[
   402 	 extent:(1.0 @ self preferredExtent y)
   468 	    e := entry on:device
   403 "/         extent:(1.0 @ (font height + (font descent * 2)  + topMargin)).
       
   404 !
       
   405 
       
   406 initStyle
       
   407     |style|
       
   408 
       
   409     super initStyle.
       
   410 
       
   411     showSeparatingLines := DefaultSeparatingLines. "/ false.
       
   412     DefaultViewBackground notNil ifTrue:[
       
   413 	viewBackground := DefaultViewBackground on:device
       
   414     ].
       
   415 
       
   416     DefaultFont notNil ifTrue:[
       
   417 	font := DefaultFont on:device
       
   418     ].
       
   419     DefaultForegroundColor notNil ifTrue:[
       
   420 	fgColor := DefaultForegroundColor
       
   421     ] ifFalse:[
       
   422 	fgColor := Black.
       
   423     ].
       
   424     DefaultBackgroundColor notNil ifTrue:[
       
   425 	bgColor := DefaultBackgroundColor
       
   426     ] ifFalse:[
       
   427 	bgColor := viewBackground.
       
   428     ].
       
   429     onLevel := DefaultHilightLevel.
       
   430     offLevel := DefaultLevel.
       
   431 
       
   432     self is3D ifTrue:[
       
   433 	device hasColors ifTrue:[
       
   434 	    activeFgColor := Color name:'yellow'
       
   435 	] ifFalse:[
   469 	] ifFalse:[
   436 	    activeFgColor := White
   470 	    e := entry printString
   437 	].
   471 	].
   438 	device hasGreyscales ifTrue:[
   472 	titles at:index put:e
   439 	    activeBgColor := bgColor.
   473     ].
   440 	] ifFalse:[
       
   441 	    activeBgColor := fgColor.
       
   442 	].
       
   443 	topMargin := 2.
       
   444 
       
   445 	style := styleSheet name.
       
   446 	((style == #iris) or:[style == #motif]) ifTrue:[
       
   447 	    self level:2.
       
   448 	    onLevel := 2.
       
   449 	    offLevel := 0.
       
   450 	    activeFgColor := fgColor
       
   451 	]
       
   452     ] ifFalse:[
       
   453 	activeFgColor := bgColor.
       
   454 	activeBgColor := fgColor.
       
   455 	topMargin := 0
       
   456     ].
       
   457 
       
   458     edgeStyle := DefaultEdgeStyle.
       
   459     keepMenu := DefaultKeepMenu.
       
   460     toggleKeep := DefaultToggleKeep.
       
   461 
       
   462     DefaultHilightForegroundColor notNil ifTrue:[
       
   463 	activeFgColor := DefaultHilightForegroundColor
       
   464     ].
       
   465     DefaultHilightBackgroundColor notNil ifTrue:[
       
   466 	activeBgColor := DefaultHilightBackgroundColor
       
   467     ].
       
   468     DefaultShadowColor notNil ifTrue:[
       
   469 	shadowColor := DefaultShadowColor on:device
       
   470     ].
       
   471     DefaultLightColor notNil ifTrue:[
       
   472 	lightColor := DefaultLightColor on:device
       
   473     ].
       
   474 
       
   475     bgColor := bgColor on:device.
       
   476     fgColor := fgColor on:device.
       
   477     activeBgColor := activeBgColor on:device.
       
   478     activeFgColor := activeFgColor on:device.
       
   479 
       
   480     raiseTopWhenActivated := styleSheet at:'pullDownMenuRaiseTop' default:true.
       
   481 !
       
   482 
       
   483 initCursor
       
   484     "set up a hand cursor"
       
   485 
       
   486     cursor := Cursor hand
       
   487 !
       
   488 
       
   489 recreate
       
   490     "if the image was saved with an active menu, hide it"
       
   491 
       
   492     |m|
       
   493 
       
   494     activeMenuNumber notNil ifTrue:[
       
   495 	(m := menus at:activeMenuNumber) notNil ifTrue:[
       
   496 	    m unrealize.
       
   497 	].
       
   498 	activeMenuNumber := nil.
       
   499     ].
       
   500     super recreate.
       
   501     self setMenuOrigins
       
   502 !
       
   503 
       
   504 create
       
   505     super create.
       
   506     self setMenuOrigins
       
   507 !
       
   508 
       
   509 destroy
       
   510     "have to destroy the menus manually here,
       
   511      since they are no real subviews of myself"
       
   512 
       
   513     menus notNil ifTrue:[
       
   514 	menus do:[:m |
       
   515 	    m notNil ifTrue:[m destroy]
       
   516 	].
       
   517 	menus := nil
       
   518     ].
       
   519     activeMenuNumber := nil.
       
   520     super destroy.
       
   521 !
       
   522 
       
   523 superView:aView
       
   524     "when my superView changes, all of my menus must change as well"
       
   525 
       
   526     super superView:aView.
       
   527     menus notNil ifTrue:[
       
   528 	menus do:[:aMenu |
       
   529 	    aMenu notNil ifTrue:[
       
   530 		aMenu superView:aView
       
   531 	    ]
       
   532 	]
       
   533     ]
       
   534 ! !
       
   535 
       
   536 !PullDownMenu methodsFor:'accessing-look'!
       
   537 
       
   538 showSeparatingLines:aBoolean
       
   539     "turn on/off drawing of separating lines.
       
   540      You should not use this method; instead leave the value as
       
   541      defined in the styleSheet."
       
   542 
       
   543     showSeparatingLines := aBoolean.
       
   544     shown ifTrue:[
   474     shown ifTrue:[
   545 	self setMenuOrigins.
   475 	self clear.
   546 	self redraw
   476 	self redraw
   547     ]
   477     ]
   548 !
   478 !
   549 
   479 
   550 font:aFont
   480 labels:titleArray selectors:selectorArray
   551     "set the menus font.
   481     "define the menu-titles (group-headers) and selectors.
   552      adjusts menu-origins when font changes.
   482      Selectors are mostly used as access keys to get to submenus later."
   553      You should not use this method; instead leave the value as
   483 
   554      defined in the styleSheet."
   484     self labels:titleArray.
   555 
   485     self selectors:selectorArray
   556     aFont ~~ font ifTrue:[
   486 
   557 	super font:(aFont on:device).
   487     "Created: 20.10.1995 / 20:15:54 / cg"
   558 	self height:(font height + (font descent * 2)).
   488 !
   559 	shown ifTrue:[
   489 
   560 	    self setMenuOrigins
   490 menuAt:stringOrNumber
   561 	]
   491     "return the menu with the title; return nil if not found"
   562     ]
   492 
   563 !
   493     |index|
   564 
   494 
   565 foregroundColor:aColor
   495     index := self indexOf:stringOrNumber.
   566     "set the foreground drawing color.
   496     (index == 0) ifTrue:[^ nil].
   567      You should not use this method; instead leave the value as
   497     ^ menus at:index
   568      defined in the styleSheet."
   498 !
   569 
   499 
   570     fgColor := aColor on:device
   500 numberOfTitles:n
   571 !
   501     "setup blank title-space to be filled in later"
   572 
   502 
   573 backgroundColor:aColor
   503     menus := Array new:n.
   574     "set the background drawing color.
   504     titles := Array new:n
   575      You should not use this method; instead leave the value as
   505 !
   576      defined in the styleSheet."
       
   577 
       
   578     bgColor := aColor on:device
       
   579 ! !
       
   580 
       
   581 
       
   582 !PullDownMenu methodsFor:'accessing'!
       
   583 
   506 
   584 receiver:anObject 
   507 receiver:anObject 
   585     "set the menu-receiver. Thats the one who gets the
   508     "set the menu-receiver. Thats the one who gets the
   586      messages (both from myself and from my submenus).
   509      messages (both from myself and from my submenus).
   587      This only sets the receiver for menus which are already
   510      This only sets the receiver for menus which are already
   596 	    ]
   519 	    ]
   597 	]
   520 	]
   598     ]
   521     ]
   599 !
   522 !
   600 
   523 
   601 numberOfTitles:n
       
   602     "setup blank title-space to be filled in later"
       
   603 
       
   604     menus := Array new:n.
       
   605     titles := Array new:n
       
   606 !
       
   607 
       
   608 labels:titleArray
       
   609     "define the menu-titles (group-headers)"
       
   610 
       
   611     |numberOfLabels|
       
   612 
       
   613     numberOfLabels := titleArray size.
       
   614     menus := Array new:numberOfLabels.
       
   615     titles := Array new:numberOfLabels.
       
   616 
       
   617     titleArray keysAndValuesDo:[:index :entry |
       
   618 	|e|
       
   619 
       
   620 	entry isImage ifTrue:[
       
   621 	    e := entry on:device
       
   622 	] ifFalse:[
       
   623 	    e := entry printString
       
   624 	].
       
   625 	titles at:index put:e
       
   626     ].
       
   627     shown ifTrue:[
       
   628 	self clear.
       
   629 	self redraw
       
   630     ]
       
   631 !
       
   632 
       
   633 labels
       
   634     "return the menu-titles (group-headers)"
       
   635 
       
   636     ^ titles
       
   637 !
       
   638 
       
   639 selectors:selectorArray
   524 selectors:selectorArray
   640     "define the menu-selectors. These are used as accesskey only
   525     "define the menu-selectors. These are used as accesskey only
   641      in menuAt: accesses. This makes PullDownMenu accesss
   526      in menuAt: accesses. This makes PullDownMenu accesss
   642      somewhat more compatible to PopUpMenus."
   527      somewhat more compatible to PopUpMenus."
   643 
   528 
   644     selectors := selectorArray.
   529     selectors := selectorArray.
   645 !
       
   646 
       
   647 labels:titleArray selectors:selectorArray
       
   648     "define the menu-titles (group-headers) and selectors.
       
   649      Selectors are mostly used as access keys to get to submenus later."
       
   650 
       
   651     self labels:titleArray.
       
   652     self selectors:selectorArray
       
   653 
       
   654     "Created: 20.10.1995 / 20:15:54 / cg"
       
   655 !
       
   656 
       
   657 menuAt:stringOrNumber
       
   658     "return the menu with the title; return nil if not found"
       
   659 
       
   660     |index|
       
   661 
       
   662     index := self indexOf:stringOrNumber.
       
   663     (index == 0) ifTrue:[^ nil].
       
   664     ^ menus at:index
       
   665 !
       
   666 
       
   667 at:aString putMenu:aMenu
       
   668     "set the menu under the title, aString"
       
   669 
       
   670     |index|
       
   671 
       
   672     index := self indexOf:aString.
       
   673     (index == 0) ifTrue:[
       
   674 	self error:'no such menu entry'.
       
   675 	^ nil
       
   676     ].
       
   677 
       
   678 "/ not needed:
       
   679 "/    aMenu origin:((left + (self titleLenUpTo:index)) 
       
   680 "/                  @
       
   681 "/                  (height + aMenu borderWidth)).
       
   682     aMenu hiddenOnRealize:true.
       
   683     menus at:index put:aMenu.
       
   684     aMenu masterView:self.
       
   685 !
       
   686 
       
   687 at:aString putLabels:labels selectors:selectors args:args receiver:anObject
       
   688     "create and set the menu under the title, aString"
       
   689 
       
   690     |menuView|
       
   691 
       
   692     menuView := MenuView labels:labels
       
   693 		      selectors:selectors
       
   694 			   args:args
       
   695 		       receiver:anObject
       
   696 			    for:self.
       
   697     self at:aString putMenu:menuView
       
   698 !
       
   699 
       
   700 at:aString putLabels:labels selector:selector args:args receiver:anObject
       
   701     "create and set the menu under the title, aString"
       
   702 
       
   703     |menuView|
       
   704 
       
   705     menuView := MenuView labels:labels
       
   706 		       selector:selector
       
   707 			   args:args
       
   708 		       receiver:anObject
       
   709 			    for:self.
       
   710     self at:aString putMenu:menuView
       
   711 !
       
   712 
       
   713 at:aString putLabels:labels selectors:selectors receiver:anObject
       
   714     "create and set the menu under the title, aString"
       
   715 
       
   716     |menuView|
       
   717 
       
   718     menuView := MenuView labels:labels
       
   719 		      selectors:selectors
       
   720 		       receiver:anObject
       
   721 			    for:self.
       
   722     self at:aString putMenu:menuView
       
   723 ! !
   530 ! !
   724 
   531 
   725 !PullDownMenu methodsFor:'queries'!
   532 !PullDownMenu methodsFor:'accessing-look'!
   726 
   533 
   727 preferredExtent
   534 backgroundColor:aColor
   728     |w|
   535     "set the background drawing color.
   729 
   536      You should not use this method; instead leave the value as
   730     w := self titleLenUpTo:(titles size + 1).
   537      defined in the styleSheet."
   731     ^ w @ (font height + (font descent * 2) "+ topMargin" + (margin*2)).
   538 
   732 ! !
   539     bgColor := aColor on:device
   733 
   540 !
   734 !PullDownMenu methodsFor:'private'!
   541 
   735 
   542 font:aFont
   736 titleLenUpTo:index
   543     "set the menus font.
   737     "answer len (in pixels) of all title-strings up-to 
   544      adjusts menu-origins when font changes.
   738      (but excluding) title-index. Used to compute x-position when drawing
   545      You should not use this method; instead leave the value as
   739      individual entries."
   546      defined in the styleSheet."
   740 
   547 
   741     |len "{ Class: SmallInteger }" 
   548     aFont ~~ font ifTrue:[
   742      wSpace wSep|
   549 	super font:(aFont on:device).
   743 
   550 	self height:(font height + (font descent * 2)).
   744     (index <= 1) ifTrue:[^ 0].
   551 	shown ifTrue:[
   745     wSpace := (font widthOf:' ').
   552 	    self setMenuOrigins
   746     showSeparatingLines ifTrue:[
       
   747 	self is3D ifTrue:[
       
   748 	    wSep := 2
       
   749 	] ifFalse:[
       
   750 	    wSep := 1
       
   751 	]
       
   752     ] ifFalse:[
       
   753 	wSep := 0
       
   754     ].
       
   755 
       
   756     len := 0.
       
   757     titles from:1 to:(index - 1) do:[:entry |
       
   758 	|thisLength|
       
   759 
       
   760 	entry isString ifTrue:[
       
   761 	    thisLength := (font widthOf:entry).
       
   762 	] ifFalse:[
       
   763 	    thisLength := entry width
       
   764 	].
       
   765 	len := len + thisLength + wSpace + wSep + wSpace.
       
   766     ].
       
   767     ^ len
       
   768 !
       
   769 
       
   770 indexOf:stringOrNumber
       
   771     "return the index of the menu with title; return 0 if not found.
       
   772      stringOrNumber may be a number, a selector from the selectorArray
       
   773      or a string from the title array."
       
   774 
       
   775     |idx|
       
   776 
       
   777     stringOrNumber isNumber ifTrue:[
       
   778 	^ stringOrNumber
       
   779     ].
       
   780     selectors notNil ifTrue:[
       
   781 	idx := selectors indexOf:stringOrNumber.
       
   782 	idx ~~ 0 ifTrue:[^ idx].
       
   783     ].
       
   784     ^ titles indexOf:stringOrNumber
       
   785 !
       
   786 
       
   787 someMenuItemLabeled:aLabel
       
   788     "find a menu item.
       
   789      Currently, in ST/X, instances of MenuItem are only created as dummy"
       
   790 
       
   791     |idx|
       
   792 
       
   793     idx := self indexOf:aLabel.
       
   794     idx ~~ 0 ifTrue:[
       
   795 	^ MenuItem new menu:self index:idx
       
   796     ].
       
   797     menus notNil ifTrue:[
       
   798 	menus do:[:aMenu |
       
   799 	    |item|
       
   800 
       
   801 	    aMenu notNil ifTrue:[
       
   802 		(item := aMenu someMenuItemLabeled:aLabel) notNil ifTrue:[
       
   803 		    ^ item
       
   804 		]
       
   805 	    ]
       
   806 	]
       
   807     ].
       
   808     ^ nil
       
   809 !
       
   810 
       
   811 setMenuOrigins
       
   812     "adjust origins of menus when font changes"
       
   813 
       
   814     (font device == device) ifTrue:[
       
   815 	menus keysAndValuesDo:[:index :aMenu |
       
   816 	    aMenu notNil ifTrue:[
       
   817 		aMenu origin:((left + (self titleLenUpTo:index)) 
       
   818 			      @
       
   819 			      (height + aMenu borderWidth))
       
   820 	    ].
       
   821 	]
   553 	]
   822     ]
   554     ]
   823 !
   555 !
   824 
   556 
   825 titleIndexForX:x
   557 foregroundColor:aColor
   826     "given a click x-position, return index in title or nil"
   558     "set the foreground drawing color.
   827 
   559      You should not use this method; instead leave the value as
   828     |xstart "{ Class: SmallInteger }"
   560      defined in the styleSheet."
   829      xend   "{ Class: SmallInteger }" 
   561 
   830      wSpace wSep|
   562     fgColor := aColor on:device
   831 
   563 !
   832     wSpace := (font widthOf:' ') * 2. 
   564 
   833     showSeparatingLines ifTrue:[
   565 showSeparatingLines:aBoolean
   834 	self is3D ifTrue:[
   566     "turn on/off drawing of separating lines.
   835 	    wSep := 2
   567      You should not use this method; instead leave the value as
   836 	] ifFalse:[
   568      defined in the styleSheet."
   837 	    wSep := 1
   569 
   838 	]
   570     showSeparatingLines := aBoolean.
   839     ] ifFalse:[
   571     shown ifTrue:[
   840 	wSep := 0
   572 	self setMenuOrigins.
   841     ].
   573 	self redraw
   842     xstart := 0.
       
   843     1 to:(titles size) do:[:index |
       
   844 	|entry thisLength|
       
   845 
       
   846 	entry := titles at:index.
       
   847 	entry isString ifTrue:[
       
   848 	    thisLength := font widthOf:entry.
       
   849 	] ifFalse:[
       
   850 	    thisLength := entry width
       
   851 	].
       
   852 	xend := xstart + thisLength + wSpace + wSep.
       
   853 	(x between:xstart and:xend) ifTrue:[^ index].
       
   854 	xstart := xend
       
   855     ].
       
   856     ^ nil
       
   857 ! !
       
   858 
       
   859 !PullDownMenu methodsFor:'hiding/showing menus'!
       
   860 
       
   861 hideActiveMenuRelease:aBoolean
       
   862     "hide currently active menu - release grab if aBoolean is true
       
   863      and a grab was set (keepMenu)"
       
   864 
       
   865     |m|
       
   866 
       
   867     activeMenuNumber notNil ifTrue:[
       
   868 	(m := menus at:activeMenuNumber) notNil ifTrue:[
       
   869 	    m hiddenOnRealize:true.
       
   870 	    m unrealize.
       
   871 	].
       
   872 	self unHighlightActiveTitle.
       
   873 	activeMenuNumber := nil
       
   874     ].
       
   875     aBoolean ifTrue:[
       
   876 	device ungrabPointer. 
       
   877 	self cursor:Cursor normal
       
   878     ].
       
   879 !
       
   880 
       
   881 hideActiveMenu
       
   882     "hide currently active menu - release grab if there is any grab (keepMenu)"
       
   883 
       
   884     ^ self hideActiveMenuRelease:true
       
   885 !
       
   886 
       
   887 pullMenu:aNumber
       
   888     "activate a menu, return it or nil"
       
   889 
       
   890     |subMenu r posY|
       
   891 
       
   892     activeMenuNumber notNil ifTrue:[self hideActiveMenuRelease:false].
       
   893     activeMenuNumber := aNumber.
       
   894     subMenu := menus at:aNumber.
       
   895 
       
   896     raiseTopWhenActivated ifTrue:[
       
   897 	self topView raise.
       
   898     ].
       
   899 
       
   900     (activeMenuNumber notNil 
       
   901     and:[
       
   902 	 subMenu notNil
       
   903 	 or:[selectors notNil and:[(selectors at:activeMenuNumber) notNil]]]) ifTrue:[
       
   904 	    self highlightActiveTitle.
       
   905 	 ].
       
   906 
       
   907     subMenu notNil ifTrue:[
       
   908 	subMenu origin:((left + (self titleLenUpTo:aNumber)) 
       
   909 		       @
       
   910 		       (posY := height + subMenu borderWidth)).
       
   911 	subMenu hiddenOnRealize:false.
       
   912 	subMenu deselect.
       
   913 	subMenu create.
       
   914 	subMenu saveUnder:true.
       
   915 	subMenu superMenu:self.
       
   916 
       
   917 	subMenu right > (r := self right) ifTrue:[
       
   918 	    subMenu origin:((r - subMenu width) @ posY).
       
   919 	].
       
   920 	subMenu raise show.
       
   921     ].
       
   922     ^ subMenu
       
   923 !
       
   924 
       
   925 regainControl
       
   926     keepMenu ifTrue:[
       
   927 	device grabPointerInView:self.
       
   928 	self cursor:Cursor upRightArrow
       
   929     ]
   574     ]
   930 ! !
   575 ! !
   931 
   576 
   932 !PullDownMenu methodsFor:'drawing '!
   577 !PullDownMenu methodsFor:'drawing '!
   933 
   578 
   934 redraw
   579 drawActiveTitleSelected:selected
   935     |x     "{ Class: SmallInteger }"
   580     |x|
   936      y     "{ Class: SmallInteger }"
   581     activeMenuNumber notNil ifTrue:[
   937      index "{ Class: SmallInteger }" 
   582 	x := self titleLenUpTo:activeMenuNumber.
   938      wSpace clr|
   583 	self drawTitle:(titles at:activeMenuNumber) x:x selected:selected 
   939 
       
   940     shown ifFalse: [ ^ self ].
       
   941     titles isNil ifTrue:[^ self].
       
   942 
       
   943     wSpace := (font widthOf:' ').
       
   944     x := 0.
       
   945     y := height "- 1".
       
   946     index := 1.
       
   947     titles do:[:title |
       
   948 	self drawTitle:title x:x selected:(index == activeMenuNumber).
       
   949 
       
   950 	title isString ifTrue:[
       
   951 	    x := x + (font widthOf:title).
       
   952 	] ifFalse:[
       
   953 	    x := x + title width
       
   954 	].
       
   955 	x := x + wSpace + wSpace.
       
   956 	showSeparatingLines ifTrue:[
       
   957 	    self is3D ifTrue:[
       
   958 		self paint:shadowColor.
       
   959 		self displayLineFromX:x y:0 toX:x y:y.
       
   960 		x := x + 1.
       
   961 		clr := lightColor.
       
   962 	    ] ifFalse:[
       
   963 		clr := fgColor.
       
   964 	    ].
       
   965 	    self paint:clr.
       
   966 	    self displayLineFromX:x y:0 toX:x y:y.
       
   967 	    x := x + 1
       
   968 	].
       
   969 	index := index + 1
       
   970     ]
   584     ]
   971 !
   585 !
   972 
   586 
   973 drawTitle:stringOrImage x:x0 selected:selected
   587 drawTitle:stringOrImage x:x0 selected:selected
   974     |y w x wSpace fg bg map|
   588     |y w x wSpace fg bg map|
  1021     ]
   635     ]
  1022 
   636 
  1023     "Modified: 20.10.1995 / 22:03:27 / cg"
   637     "Modified: 20.10.1995 / 22:03:27 / cg"
  1024 !
   638 !
  1025 
   639 
  1026 drawActiveTitleSelected:selected
       
  1027     |x|
       
  1028     activeMenuNumber notNil ifTrue:[
       
  1029 	x := self titleLenUpTo:activeMenuNumber.
       
  1030 	self drawTitle:(titles at:activeMenuNumber) x:x selected:selected 
       
  1031     ]
       
  1032 !
       
  1033 
       
  1034 highlightActiveTitle
   640 highlightActiveTitle
  1035     self drawActiveTitleSelected:true 
   641     self drawActiveTitleSelected:true 
       
   642 !
       
   643 
       
   644 redraw
       
   645     |x     "{ Class: SmallInteger }"
       
   646      y     "{ Class: SmallInteger }"
       
   647      index "{ Class: SmallInteger }" 
       
   648      wSpace clr|
       
   649 
       
   650     shown ifFalse: [ ^ self ].
       
   651     titles isNil ifTrue:[^ self].
       
   652 
       
   653     wSpace := (font widthOf:' ').
       
   654     x := 0.
       
   655     y := height "- 1".
       
   656     index := 1.
       
   657     titles do:[:title |
       
   658 	self drawTitle:title x:x selected:(index == activeMenuNumber).
       
   659 
       
   660 	title isString ifTrue:[
       
   661 	    x := x + (font widthOf:title).
       
   662 	] ifFalse:[
       
   663 	    x := x + title width
       
   664 	].
       
   665 	x := x + wSpace + wSpace.
       
   666 	showSeparatingLines ifTrue:[
       
   667 	    self is3D ifTrue:[
       
   668 		self paint:shadowColor.
       
   669 		self displayLineFromX:x y:0 toX:x y:y.
       
   670 		x := x + 1.
       
   671 		clr := lightColor.
       
   672 	    ] ifFalse:[
       
   673 		clr := fgColor.
       
   674 	    ].
       
   675 	    self paint:clr.
       
   676 	    self displayLineFromX:x y:0 toX:x y:y.
       
   677 	    x := x + 1
       
   678 	].
       
   679 	index := index + 1
       
   680     ]
  1036 !
   681 !
  1037 
   682 
  1038 unHighlightActiveTitle
   683 unHighlightActiveTitle
  1039     self drawActiveTitleSelected:false 
   684     self drawActiveTitleSelected:false 
  1040 ! !
   685 ! !
  1041 
   686 
  1042 !PullDownMenu methodsFor:'submenu notifications'!
       
  1043 
       
  1044 showActive
       
  1045     "sent by a menu to tell me that it starts to perform
       
  1046      its menu action."
       
  1047 
       
  1048     windowGroup notNil ifTrue:[windowGroup showCursor:Cursor wait]
       
  1049 !
       
  1050 
       
  1051 showPassive
       
  1052     "sent by a menu to tell me that it finished its menu-action.
       
  1053      Here, we hide the currently active menu."
       
  1054 
       
  1055     self hideActiveMenu.
       
  1056     windowGroup notNil ifTrue:[windowGroup restoreCursors]
       
  1057 !
       
  1058 
       
  1059 submenuTriggered 
       
  1060     "sent by a sub-submenu to tell me that it finished its menu-action."
       
  1061 
       
  1062     self showPassive
       
  1063 ! !
       
  1064 
       
  1065 !PullDownMenu methodsFor:'event handling'!
   687 !PullDownMenu methodsFor:'event handling'!
  1066 
   688 
  1067 showNoFocus
   689 buttonMotion:state x:x y:y
  1068     "when stepping focus, hide any active menu"
   690     |titleIndex activeMenu activeLeft activeTop|
  1069 
   691 
  1070     self hideActiveMenu.
   692     state == 0 ifTrue:[^ self].
  1071     super showNoFocus
   693 
  1072 !
   694     activeMenuNumber notNil ifTrue:[
  1073 
   695 	activeMenu := menus at:activeMenuNumber.
  1074 keyPress:key x:x y:y
   696     ].
  1075     <resource: #keyboard (#CursorLeft #CursorRight #MenuSelect)>
   697 
  1076 
   698     (y < height) ifTrue:[
  1077     |index m sel|
   699 	"moving around in title line"
  1078 
   700 	activeMenu notNil ifTrue:[
  1079     "
   701 	    activeMenu selection:nil
  1080      handle CursorLeft/Right for non-mouse operation
   702 	].
  1081      (for example, if it has the explicit focus)
   703 	titleIndex := self titleIndexForX:x.
  1082      These will pull the previous/next menu
   704 	titleIndex notNil ifTrue:[
  1083     "
   705 	    (titleIndex ~~ activeMenuNumber) ifTrue:[
  1084     ((key == #CursorRight) or:[key == #CursorLeft]) ifTrue:[
   706 		self pullMenu:titleIndex
  1085 	activeMenuNumber isNil ifTrue:[
   707 	    ]
  1086 	    index := (key == #CursorRight) ifTrue:[1] ifFalse:[menus size].
       
  1087 	] ifFalse:[
   708 	] ifFalse:[
  1088 	    (key == #CursorRight) ifTrue:[
   709 	    self hideActiveMenu
  1089 		index := activeMenuNumber+1
   710 	]
  1090 	    ] ifFalse:[
   711     ] ifFalse:[
  1091 		index := activeMenuNumber-1
   712 	"moving around below"
  1092 	    ].
   713 	activeMenu isNil ifTrue:[^self].
  1093 	    index == 0 ifTrue:[index := menus size]
   714 	activeLeft := activeMenu left.
  1094 	    ifFalse:[
   715 	(x between:activeLeft and:(activeMenu right)) ifTrue:[
  1095 		index > menus size ifTrue:[index := 1]
   716 	    activeTop := activeMenu top.
       
   717 	    (y between:activeTop and:(activeMenu bottom)) ifTrue:[
       
   718 		"moving around in menu"
       
   719 		activeMenu buttonMotion:state
       
   720 				      x:(x - activeLeft)
       
   721 				      y:(y - activeTop).
       
   722 		^ self
  1096 	    ]
   723 	    ]
  1097 	].
   724 	].
  1098 	self pullMenu:index.
   725 	"moved outside menu"
  1099 	^ self
   726 	activeMenu selection:nil
  1100     ].
   727     ]
  1101 
       
  1102     activeMenuNumber isNil ifTrue:[^self].
       
  1103 
       
  1104     "
       
  1105      Return, space or the (virtual) MenuSelect key trigger
       
  1106      a menu entry (for non-submenu entries).
       
  1107      Otherwise, if we have a submenu open,
       
  1108      pass the key on to it ...
       
  1109     "
       
  1110     m := menus at:activeMenuNumber.
       
  1111     m isNil ifTrue:[
       
  1112 	(key == #Return 
       
  1113 	or:[key == #MenuSelect
       
  1114 	or:[key == Character space]]) ifTrue:[
       
  1115 	    sel := selectors at:activeMenuNumber.
       
  1116 	    sel notNil ifTrue:[
       
  1117 		receiver perform:sel
       
  1118 	    ]
       
  1119 	].
       
  1120     ] ifFalse:[
       
  1121 	m keyPress:key x:0 y:0.
       
  1122     ].
       
  1123 !
   728 !
  1124 
   729 
  1125 buttonPress:button x:x y:y
   730 buttonPress:button x:x y:y
  1126     |titleIndex activeMenu activeLeft activeTop m|
   731     |titleIndex activeMenu activeLeft activeTop m|
  1127 
   732 
  1164 	].
   769 	].
  1165 	self hideActiveMenu
   770 	self hideActiveMenu
  1166     ]
   771     ]
  1167 !
   772 !
  1168 
   773 
  1169 buttonMotion:state x:x y:y
       
  1170     |titleIndex activeMenu activeLeft activeTop|
       
  1171 
       
  1172     state == 0 ifTrue:[^ self].
       
  1173 
       
  1174     activeMenuNumber notNil ifTrue:[
       
  1175 	activeMenu := menus at:activeMenuNumber.
       
  1176     ].
       
  1177 
       
  1178     (y < height) ifTrue:[
       
  1179 	"moving around in title line"
       
  1180 	activeMenu notNil ifTrue:[
       
  1181 	    activeMenu selection:nil
       
  1182 	].
       
  1183 	titleIndex := self titleIndexForX:x.
       
  1184 	titleIndex notNil ifTrue:[
       
  1185 	    (titleIndex ~~ activeMenuNumber) ifTrue:[
       
  1186 		self pullMenu:titleIndex
       
  1187 	    ]
       
  1188 	] ifFalse:[
       
  1189 	    self hideActiveMenu
       
  1190 	]
       
  1191     ] ifFalse:[
       
  1192 	"moving around below"
       
  1193 	activeMenu isNil ifTrue:[^self].
       
  1194 	activeLeft := activeMenu left.
       
  1195 	(x between:activeLeft and:(activeMenu right)) ifTrue:[
       
  1196 	    activeTop := activeMenu top.
       
  1197 	    (y between:activeTop and:(activeMenu bottom)) ifTrue:[
       
  1198 		"moving around in menu"
       
  1199 		activeMenu buttonMotion:state
       
  1200 				      x:(x - activeLeft)
       
  1201 				      y:(y - activeTop).
       
  1202 		^ self
       
  1203 	    ]
       
  1204 	].
       
  1205 	"moved outside menu"
       
  1206 	activeMenu selection:nil
       
  1207     ]
       
  1208 !
       
  1209 
       
  1210 buttonRelease:button x:x y:y
   774 buttonRelease:button x:x y:y
  1211     |activeMenu activeLeft activeTop hideMenu sel|
   775     |activeMenu activeLeft activeTop hideMenu sel|
  1212 
   776 
  1213     activeMenuNumber isNil ifTrue:[^self].
   777     activeMenuNumber isNil ifTrue:[^self].
  1214     activeMenu := menus at:activeMenuNumber.
   778     activeMenu := menus at:activeMenuNumber.
  1252 	]
   816 	]
  1253     ].                  
   817     ].                  
  1254     hideMenu ifTrue:[
   818     hideMenu ifTrue:[
  1255        self hideActiveMenu.
   819        self hideActiveMenu.
  1256     ]
   820     ]
       
   821 !
       
   822 
       
   823 keyPress:key x:x y:y
       
   824     <resource: #keyboard (#CursorLeft #CursorRight #MenuSelect)>
       
   825 
       
   826     |index m sel|
       
   827 
       
   828     "
       
   829      handle CursorLeft/Right for non-mouse operation
       
   830      (for example, if it has the explicit focus)
       
   831      These will pull the previous/next menu
       
   832     "
       
   833     ((key == #CursorRight) or:[key == #CursorLeft]) ifTrue:[
       
   834 	activeMenuNumber isNil ifTrue:[
       
   835 	    index := (key == #CursorRight) ifTrue:[1] ifFalse:[menus size].
       
   836 	] ifFalse:[
       
   837 	    (key == #CursorRight) ifTrue:[
       
   838 		index := activeMenuNumber+1
       
   839 	    ] ifFalse:[
       
   840 		index := activeMenuNumber-1
       
   841 	    ].
       
   842 	    index == 0 ifTrue:[index := menus size]
       
   843 	    ifFalse:[
       
   844 		index > menus size ifTrue:[index := 1]
       
   845 	    ]
       
   846 	].
       
   847 	self pullMenu:index.
       
   848 	^ self
       
   849     ].
       
   850 
       
   851     activeMenuNumber isNil ifTrue:[^self].
       
   852 
       
   853     "
       
   854      Return, space or the (virtual) MenuSelect key trigger
       
   855      a menu entry (for non-submenu entries).
       
   856      Otherwise, if we have a submenu open,
       
   857      pass the key on to it ...
       
   858     "
       
   859     m := menus at:activeMenuNumber.
       
   860     m isNil ifTrue:[
       
   861 	(key == #Return 
       
   862 	or:[key == #MenuSelect
       
   863 	or:[key == Character space]]) ifTrue:[
       
   864 	    sel := selectors at:activeMenuNumber.
       
   865 	    sel notNil ifTrue:[
       
   866 		receiver perform:sel
       
   867 	    ]
       
   868 	].
       
   869     ] ifFalse:[
       
   870 	m keyPress:key x:0 y:0.
       
   871     ].
       
   872 !
       
   873 
       
   874 showNoFocus
       
   875     "when stepping focus, hide any active menu"
       
   876 
       
   877     self hideActiveMenu.
       
   878     super showNoFocus
  1257 ! !
   879 ! !
       
   880 
       
   881 !PullDownMenu methodsFor:'hiding/showing menus'!
       
   882 
       
   883 hideActiveMenu
       
   884     "hide currently active menu - release grab if there is any grab (keepMenu)"
       
   885 
       
   886     ^ self hideActiveMenuRelease:true
       
   887 !
       
   888 
       
   889 hideActiveMenuRelease:aBoolean
       
   890     "hide currently active menu - release grab if aBoolean is true
       
   891      and a grab was set (keepMenu)"
       
   892 
       
   893     |m|
       
   894 
       
   895     activeMenuNumber notNil ifTrue:[
       
   896 	(m := menus at:activeMenuNumber) notNil ifTrue:[
       
   897 	    m hiddenOnRealize:true.
       
   898 	    m unrealize.
       
   899 	].
       
   900 	self unHighlightActiveTitle.
       
   901 	activeMenuNumber := nil
       
   902     ].
       
   903     aBoolean ifTrue:[
       
   904 	device ungrabPointer. 
       
   905 	self cursor:Cursor normal
       
   906     ].
       
   907 !
       
   908 
       
   909 pullMenu:aNumber
       
   910     "activate a menu, return it or nil"
       
   911 
       
   912     |subMenu r posY|
       
   913 
       
   914     activeMenuNumber notNil ifTrue:[self hideActiveMenuRelease:false].
       
   915     activeMenuNumber := aNumber.
       
   916     subMenu := menus at:aNumber.
       
   917 
       
   918     raiseTopWhenActivated ifTrue:[
       
   919 	self topView raise.
       
   920     ].
       
   921 
       
   922     (activeMenuNumber notNil 
       
   923     and:[
       
   924 	 subMenu notNil
       
   925 	 or:[selectors notNil and:[(selectors at:activeMenuNumber) notNil]]]) ifTrue:[
       
   926 	    self highlightActiveTitle.
       
   927 	 ].
       
   928 
       
   929     subMenu notNil ifTrue:[
       
   930 	subMenu origin:((left + (self titleLenUpTo:aNumber)) 
       
   931 		       @
       
   932 		       (posY := height + subMenu borderWidth)).
       
   933 	subMenu hiddenOnRealize:false.
       
   934 	subMenu deselect.
       
   935 	subMenu create.
       
   936 	subMenu saveUnder:true.
       
   937 	subMenu superMenu:self.
       
   938 
       
   939 	subMenu right > (r := self right) ifTrue:[
       
   940 	    subMenu origin:((r - subMenu width) @ posY).
       
   941 	].
       
   942 	subMenu raise show.
       
   943     ].
       
   944     ^ subMenu
       
   945 !
       
   946 
       
   947 regainControl
       
   948     keepMenu ifTrue:[
       
   949 	device grabPointerInView:self.
       
   950 	self cursor:Cursor upRightArrow
       
   951     ]
       
   952 ! !
       
   953 
       
   954 !PullDownMenu methodsFor:'initialize / release'!
       
   955 
       
   956 create
       
   957     super create.
       
   958     self setMenuOrigins
       
   959 !
       
   960 
       
   961 destroy
       
   962     "have to destroy the menus manually here,
       
   963      since they are no real subviews of myself"
       
   964 
       
   965     menus notNil ifTrue:[
       
   966 	menus do:[:m |
       
   967 	    m notNil ifTrue:[m destroy]
       
   968 	].
       
   969 	menus := nil
       
   970     ].
       
   971     activeMenuNumber := nil.
       
   972     super destroy.
       
   973 !
       
   974 
       
   975 initCursor
       
   976     "set up a hand cursor"
       
   977 
       
   978     cursor := Cursor hand
       
   979 !
       
   980 
       
   981 initStyle
       
   982     |style|
       
   983 
       
   984     super initStyle.
       
   985 
       
   986     showSeparatingLines := DefaultSeparatingLines. "/ false.
       
   987     DefaultViewBackground notNil ifTrue:[
       
   988 	viewBackground := DefaultViewBackground on:device
       
   989     ].
       
   990 
       
   991     DefaultFont notNil ifTrue:[
       
   992 	font := DefaultFont on:device
       
   993     ].
       
   994     DefaultForegroundColor notNil ifTrue:[
       
   995 	fgColor := DefaultForegroundColor
       
   996     ] ifFalse:[
       
   997 	fgColor := Black.
       
   998     ].
       
   999     DefaultBackgroundColor notNil ifTrue:[
       
  1000 	bgColor := DefaultBackgroundColor
       
  1001     ] ifFalse:[
       
  1002 	bgColor := viewBackground.
       
  1003     ].
       
  1004     onLevel := DefaultHilightLevel.
       
  1005     offLevel := DefaultLevel.
       
  1006 
       
  1007     self is3D ifTrue:[
       
  1008 	device hasColors ifTrue:[
       
  1009 	    activeFgColor := Color name:'yellow'
       
  1010 	] ifFalse:[
       
  1011 	    activeFgColor := White
       
  1012 	].
       
  1013 	device hasGreyscales ifTrue:[
       
  1014 	    activeBgColor := bgColor.
       
  1015 	] ifFalse:[
       
  1016 	    activeBgColor := fgColor.
       
  1017 	].
       
  1018 	topMargin := 2.
       
  1019 
       
  1020 	style := styleSheet name.
       
  1021 	((style == #iris) or:[style == #motif]) ifTrue:[
       
  1022 	    self level:2.
       
  1023 	    onLevel := 2.
       
  1024 	    offLevel := 0.
       
  1025 	    activeFgColor := fgColor
       
  1026 	]
       
  1027     ] ifFalse:[
       
  1028 	activeFgColor := bgColor.
       
  1029 	activeBgColor := fgColor.
       
  1030 	topMargin := 0
       
  1031     ].
       
  1032 
       
  1033     edgeStyle := DefaultEdgeStyle.
       
  1034     keepMenu := DefaultKeepMenu.
       
  1035     toggleKeep := DefaultToggleKeep.
       
  1036 
       
  1037     DefaultHilightForegroundColor notNil ifTrue:[
       
  1038 	activeFgColor := DefaultHilightForegroundColor
       
  1039     ].
       
  1040     DefaultHilightBackgroundColor notNil ifTrue:[
       
  1041 	activeBgColor := DefaultHilightBackgroundColor
       
  1042     ].
       
  1043     DefaultShadowColor notNil ifTrue:[
       
  1044 	shadowColor := DefaultShadowColor on:device
       
  1045     ].
       
  1046     DefaultLightColor notNil ifTrue:[
       
  1047 	lightColor := DefaultLightColor on:device
       
  1048     ].
       
  1049 
       
  1050     bgColor := bgColor on:device.
       
  1051     fgColor := fgColor on:device.
       
  1052     activeBgColor := activeBgColor on:device.
       
  1053     activeFgColor := activeFgColor on:device.
       
  1054 
       
  1055     raiseTopWhenActivated := styleSheet at:'pullDownMenuRaiseTop' default:true.
       
  1056 !
       
  1057 
       
  1058 initialize
       
  1059     super initialize.
       
  1060 
       
  1061     font := font on:device.
       
  1062     self origin:(0.0 @ 0.0)
       
  1063 	 extent:(1.0 @ self preferredExtent y)
       
  1064 "/         extent:(1.0 @ (font height + (font descent * 2)  + topMargin)).
       
  1065 !
       
  1066 
       
  1067 recreate
       
  1068     "if the image was saved with an active menu, hide it"
       
  1069 
       
  1070     |m|
       
  1071 
       
  1072     activeMenuNumber notNil ifTrue:[
       
  1073 	(m := menus at:activeMenuNumber) notNil ifTrue:[
       
  1074 	    m unrealize.
       
  1075 	].
       
  1076 	activeMenuNumber := nil.
       
  1077     ].
       
  1078     super recreate.
       
  1079     self setMenuOrigins
       
  1080 !
       
  1081 
       
  1082 superView:aView
       
  1083     "when my superView changes, all of my menus must change as well"
       
  1084 
       
  1085     super superView:aView.
       
  1086     menus notNil ifTrue:[
       
  1087 	menus do:[:aMenu |
       
  1088 	    aMenu notNil ifTrue:[
       
  1089 		aMenu superView:aView
       
  1090 	    ]
       
  1091 	]
       
  1092     ]
       
  1093 ! !
       
  1094 
       
  1095 !PullDownMenu methodsFor:'private'!
       
  1096 
       
  1097 indexOf:stringOrNumber
       
  1098     "return the index of the menu with title; return 0 if not found.
       
  1099      stringOrNumber may be a number, a selector from the selectorArray
       
  1100      or a string from the title array."
       
  1101 
       
  1102     |idx|
       
  1103 
       
  1104     stringOrNumber isNumber ifTrue:[
       
  1105 	^ stringOrNumber
       
  1106     ].
       
  1107     selectors notNil ifTrue:[
       
  1108 	idx := selectors indexOf:stringOrNumber.
       
  1109 	idx ~~ 0 ifTrue:[^ idx].
       
  1110     ].
       
  1111     ^ titles indexOf:stringOrNumber
       
  1112 !
       
  1113 
       
  1114 setMenuOrigins
       
  1115     "adjust origins of menus when font changes"
       
  1116 
       
  1117     (font device == device) ifTrue:[
       
  1118 	menus keysAndValuesDo:[:index :aMenu |
       
  1119 	    aMenu notNil ifTrue:[
       
  1120 		aMenu origin:((left + (self titleLenUpTo:index)) 
       
  1121 			      @
       
  1122 			      (height + aMenu borderWidth))
       
  1123 	    ].
       
  1124 	]
       
  1125     ]
       
  1126 !
       
  1127 
       
  1128 someMenuItemLabeled:aLabel
       
  1129     "find a menu item.
       
  1130      Currently, in ST/X, instances of MenuItem are only created as dummy"
       
  1131 
       
  1132     |idx|
       
  1133 
       
  1134     idx := self indexOf:aLabel.
       
  1135     idx ~~ 0 ifTrue:[
       
  1136 	^ MenuItem new menu:self index:idx
       
  1137     ].
       
  1138     menus notNil ifTrue:[
       
  1139 	menus do:[:aMenu |
       
  1140 	    |item|
       
  1141 
       
  1142 	    aMenu notNil ifTrue:[
       
  1143 		(item := aMenu someMenuItemLabeled:aLabel) notNil ifTrue:[
       
  1144 		    ^ item
       
  1145 		]
       
  1146 	    ]
       
  1147 	]
       
  1148     ].
       
  1149     ^ nil
       
  1150 !
       
  1151 
       
  1152 titleIndexForX:x
       
  1153     "given a click x-position, return index in title or nil"
       
  1154 
       
  1155     |xstart "{ Class: SmallInteger }"
       
  1156      xend   "{ Class: SmallInteger }" 
       
  1157      wSpace wSep|
       
  1158 
       
  1159     wSpace := (font widthOf:' ') * 2. 
       
  1160     showSeparatingLines ifTrue:[
       
  1161 	self is3D ifTrue:[
       
  1162 	    wSep := 2
       
  1163 	] ifFalse:[
       
  1164 	    wSep := 1
       
  1165 	]
       
  1166     ] ifFalse:[
       
  1167 	wSep := 0
       
  1168     ].
       
  1169     xstart := 0.
       
  1170     1 to:(titles size) do:[:index |
       
  1171 	|entry thisLength|
       
  1172 
       
  1173 	entry := titles at:index.
       
  1174 	entry isString ifTrue:[
       
  1175 	    thisLength := font widthOf:entry.
       
  1176 	] ifFalse:[
       
  1177 	    thisLength := entry width
       
  1178 	].
       
  1179 	xend := xstart + thisLength + wSpace + wSep.
       
  1180 	(x between:xstart and:xend) ifTrue:[^ index].
       
  1181 	xstart := xend
       
  1182     ].
       
  1183     ^ nil
       
  1184 !
       
  1185 
       
  1186 titleLenUpTo:index
       
  1187     "answer len (in pixels) of all title-strings up-to 
       
  1188      (but excluding) title-index. Used to compute x-position when drawing
       
  1189      individual entries."
       
  1190 
       
  1191     |len "{ Class: SmallInteger }" 
       
  1192      wSpace wSep|
       
  1193 
       
  1194     (index <= 1) ifTrue:[^ 0].
       
  1195     wSpace := (font widthOf:' ').
       
  1196     showSeparatingLines ifTrue:[
       
  1197 	self is3D ifTrue:[
       
  1198 	    wSep := 2
       
  1199 	] ifFalse:[
       
  1200 	    wSep := 1
       
  1201 	]
       
  1202     ] ifFalse:[
       
  1203 	wSep := 0
       
  1204     ].
       
  1205 
       
  1206     len := 0.
       
  1207     titles from:1 to:(index - 1) do:[:entry |
       
  1208 	|thisLength|
       
  1209 
       
  1210 	entry isString ifTrue:[
       
  1211 	    thisLength := (font widthOf:entry).
       
  1212 	] ifFalse:[
       
  1213 	    thisLength := entry width
       
  1214 	].
       
  1215 	len := len + thisLength + wSpace + wSep + wSpace.
       
  1216     ].
       
  1217     ^ len
       
  1218 ! !
       
  1219 
       
  1220 !PullDownMenu methodsFor:'queries'!
       
  1221 
       
  1222 preferredExtent
       
  1223     |w|
       
  1224 
       
  1225     w := self titleLenUpTo:(titles size + 1).
       
  1226     ^ w @ (font height + (font descent * 2) "+ topMargin" + (margin*2)).
       
  1227 ! !
       
  1228 
       
  1229 !PullDownMenu methodsFor:'submenu notifications'!
       
  1230 
       
  1231 showActive
       
  1232     "sent by a menu to tell me that it starts to perform
       
  1233      its menu action."
       
  1234 
       
  1235     windowGroup notNil ifTrue:[windowGroup showCursor:Cursor wait]
       
  1236 !
       
  1237 
       
  1238 showPassive
       
  1239     "sent by a menu to tell me that it finished its menu-action.
       
  1240      Here, we hide the currently active menu."
       
  1241 
       
  1242     self hideActiveMenu.
       
  1243     windowGroup notNil ifTrue:[windowGroup restoreCursors]
       
  1244 !
       
  1245 
       
  1246 submenuTriggered 
       
  1247     "sent by a sub-submenu to tell me that it finished its menu-action."
       
  1248 
       
  1249     self showPassive
       
  1250 ! !
       
  1251