eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'PullDownMenu':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: PullDownMenu


Inheritance:

   Object
   |
   +--GraphicsMedium
      |
      +--DisplaySurface
         |
         +--SimpleView
            |
            +--View
               |
               +--PullDownMenu

Package:
stx:libwidg
Category:
Views-Menus
Version:
rev: 1.116 date: 2018/11/09 23:32:45
user: cg
file: PullDownMenu.st directory: libwidg
module: stx stc-classLibrary: libwidg
Author:
Claus Gittinger

Description:


Notice: this class is obsolete now 
- please use a MenuPanel in new applications, 
which provides all of this functionality, plus more and a nicer look.

PullDown menu provides the top (always visible) part of these menus. 
It controls display of its menus, which become visible when one of the 
PullDownMenus entries is pressed.

A PullDownMenu itself consists of a single row of labels, which activate
a pulled menu when clicked. Entries may be empty (i.e. have no menu)
and empty entries may (optionally) also perform some action when clicked.
An entries selector is used as the key to define and access submenus
and (for empty entries:) the selector sent to the receiver of the menu.

[Instance variables:]

  menus                   <Collection>    the sub menus

  titles                  <Collection>    the strings in the menu

  selectors               <Collection>    the selectors to send to the menu-
                                          receiver (for empty pull-menus)
                                          if nil (the default), title entries
                                          do not send anything.

  activeMenuNumber        <Number>        the index of the currently active menu

  showSeparatingLines     <Boolean>       show separating lines between my menu-strings

  topMargin               <Number>        number of pixels at top

  fgColor                 <Color>         fg color to draw passive menu-titles
  bgColor                 <Color>         bg color to draw passive menu-titles

  activeFgColor           <Color>         fg color to draw activated menu-titles
  activeBgColor           <Color>         bg color to draw activated menu-titles

  onLevel                 <Integer>       3D level of entry-buttons when pressed
  offLevel                <Integer>       3D level of entry-buttons when released

  edgeStyle               <Symbol>        how to draw edges

  toggleMode              <Symbol>        if #toggle, press pulls menu,
                                          another press hides it.
                                          if other, its hidden on release.

 except menus, titles and selectors, instvars are usually defined from
 defaults in the styleSheet; you should not care for them.


[StyleSheet values:]

  pullDownMenuViewBackground              view background Color for the menu bar
                                          default: menuViewBackground

  pullDownMenuForegroundColor             foreground drawing color for the menu bar
                                          default: menuForegroundColor

  pullDownMenuBackgroundColor             background drawing color for the menu bar
                                          default: menuBackgroundColor

  pullDownMenuHilightForegroundColor      active foreground drawing color for the menu bar
                                          default: menuHilightForegroundColor

  pullDownMenuHilightBackgroundColor      active background drawing color for the menu bar
                                          default: menuHilightBackgroundColor

  pullDownMenuHilightLevel                level (3D only) when active
                                          default: menuHilightLevel

  pullDownMenuEdgeStyle                   edge style (nil or #soft)

  pullDownMenuKeepMenu                    if true, pulled menu stays open until button
                                          is pressed again outside of the item-area (motif behavior)
                                          if false, menu closes on release (default)

  pullDownMenuToggleKeep                  if true, pulled menu closes when an entry is pressed
                                          again. Otherwise, only press outside of the items area
                                          hides it. default is false

  pullDownMenuLevel                       level (3D only)

  pullDownMenuFont                        font to use for the menu bar
                                          default: menuFont

  pullDownMenuShowSeparatingLines         if true, lines are drawn between items.
                                          default: false

  pullDownMenuRaiseTop                    if true, topview is raised whenever an entry
                                          is activated.
                                          default: true


Class protocol:

defaults
o  updateStyleCache
extract values from the styleSheet and cache them in class variables

usage example(s):

     PullDownMenu updateStyleCache

instance creation
o  labels: titleArray
create and return a new PullDownMenu


Instance protocol:

accessing
o  add: label selector: selector
add a new title-item at the end.
The corresponding label can later be set with #at:putMenu:
or #at:putLabels:selectors:...

o  add: label selector: selector after: indexOrString
add a new title-item after an existing item, indexOrString,
or at the end if the after-arg is nil.
The corresponding label can later be set with #at:putMenu:
or #at:putLabels:selectors:...

o  add: label selector: selector before: indexOrString
add a new title-item before an existing item, indexOrString,
or at the beginning if the before-arg is nil.
The corresponding label can later be set with #at:putMenu:
or #at:putLabels:selectors:...

o  at: aString putLabels: labels selector: selector args: args receiver: anObject
create and set the menu under the title, aString
OBSOLETE protocol: labels:selectors:args:receiver: knows how to handle a
single symbol-arg for selectors ...

o  at: aString putLabels: labels selectors: selectors
create and set the menu under the title, aString

o  at: aString putLabels: labels selectors: selectors accelerators: shorties args: args receiver: anObject
create and set the menu under the title, aString

o  at: aString putLabels: labels selectors: selectors accelerators: shorties receiver: anObject
create and set the menu under the title, aString

o  at: aString putLabels: labels selectors: selectors args: args receiver: anObject
create and set the menu under the title, aString

o  at: aString putLabels: labels selectors: selectors receiver: anObject
create and set the menu under the title, aString

o  at: aString putMenu: aMenu
set the menu under the title, aString

o  labels
return the menu-titles (group-headers)

o  labels: titleArray
define the menu-titles (group-headers)

o  labels: titleArray selectors: selectorArray
define the menu-titles (group-headers) and selectors.
Selectors are mostly used as access keys to get to submenus later.

o  menuAt: stringOrNumber
return the menu with the title; nil if not found

o  numberOfTitles: n
setup blank title-space to be filled in later

o  receiver: anObject
set the menu-receiver.
That's the one who gets the messages (both from myself and from my submenus).
This only sets the receiver for menus which are already
created - menus added later should get their receiver in
the creation send.

o  remove: indexOrString
remove the menu, indexOrString.

o  selectors
return the menu-selectors

o  selectors: selectorArray
define the menu-selectors. These are used as accesskey only
in menuAt: accesses. This makes PullDownMenu access
somewhat more compatible to PopUpMenus.

o  subMenuAt: stringOrNumber
return the menu with the title; nil if not found.

accessing-behavior
o  actionAt: stringOrNumber
return the actionBlock associated with stringOrNumber;
nil if there is none (but there may be still a selector there).

o  actionAt: stringOrNumber put: aBlock
return the actionBlock associated with stringOrNumber;
nil if there is none (but there may be still a selector there).

o  disable: anItem

o  enable: anItem

accessing-look
o  backgroundColor: aColor
set the background drawing color.
You should not use this method; instead leave the value as
defined in the styleSheet.

o  font: aFont
set the menus font.
adjusts menu-origins when font changes.
You should not use this method; instead leave the value as
defined in the styleSheet.
CAVEAT: with the addition of Text objects,
this method is going to be obsoleted by a textStyle
method, which allows specific control over
normalFont/boldFont/italicFont parameters.

o  foregroundColor: aColor
set the foreground drawing color.
You should not use this method; instead leave the value as
defined in the styleSheet.

o  showSeparatingLines: aBoolean
turn on/off drawing of separating lines.
You should not use this method; instead leave the value as
defined in the styleSheet.

converting
o  asMenu

o  asMenu: aView

drawing
o  drawActiveTitleSelected: selected

o  drawTitle: stringOrImage x: x0 selected: selected
+ topMargin

o  highlightActiveTitle

o  redraw
}

o  unHighlightActiveTitle

event handling
o  buttonMotion: state x: x y: y
self hideActiveMenu.

o  buttonPress: button x: x y: y
now, titleIndex is non-nil if pressed within myself

o  buttonRelease: button x: x y: y
release below title-line

o  keyPress: key x: x y: y
handle CursorLeft/Right for non-mouse operation
(for example, if it has the explicit focus)
These will pull the previous/next menu

o  showNoFocus: explicit
when stepping focus, hide any active menu

hiding/showing menus
o  cancelDelayedSubmenuHideOrShowAction

o  hide
sent by an aborted menu

o  hideActiveMenu
hide currently active menu - release grab if there is any grab

o  hideActiveMenuRelease: aBoolean
hide currently active menu - release grab if aBoolean is true
and a grab was set

o  pullMenu: aNumber
activate a menu, return it or nil

o  regainControl
self cursor:Cursor upRightArrow

initialization & release
o  container: aView
when my container changes, all of my menus must change as well

o  create

o  destroy
have to destroy the menus manually here,
since they are no real subviews of myself

o  fetchDeviceResources
fetch device colors, to avoid reallocation at redraw time

o  initCursor
set up a hand cursor

o  initStyle
initialize style specifics

o  initialize

o  recreate
sent after a snapin or a migration;
if the image was saved with an active menu, hide it

private
o  indexOf: stringOrNumber
return the index of the menu with title; return 0 if not found.
stringOrNumber may be a number, a selector from the selectorArray
or a string from the title array.
If stringOrNumber is not a valid item, return 0.

o  performEntry: itemIndex

o  performSelectedAction

o  setMenuOrigins
adjust origins of menus when font changes

o  someMenuItemLabeled: aLabel
find a menu item.
Currently, in ST/X, instances of MenuItem are only created as dummy

o  titleIndexForX: x
given a click x-position, return index in title or nil

o  titleLenUpTo: index
answer len (in pixels) of all title-strings up-to
(but excluding) title-index. Used to compute x-position when drawing
individual entries.

queries
o  computePreferredExtent
return my preferredExtent from the title-item widths & font height

o  specClass
redefined, since the name of my specClass is nonStandard (i.e. not PullDownMenuSpec)

submenu notifications
o  hideSubmenu
sent by an escaped menu - ignored here

o  showActive
sent by a menu to tell me that it starts to perform
its menu action.

o  showPassive
sent by a menu to tell me that it finished its menu-action.
Here, we hide the currently active menu.

o  submenuTriggered
sent by a sub-submenu to tell me that it finished its menu-action.


Examples:


with default level (from styleSheets 'pullDownMenuLevel' setting):
      |top menu|

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu origin:0.0@0.0 corner:1.0@30 in:top.
      menu labels:#('foo' 'bar').
      menu selectors:#(foo bar).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      menu at:#bar 
           putLabels:#('bar1' 'bar2' 'bar3')
           selectors:#(bar1 bar2 bar3)
           receiver:nil.
      top open
with a defined level:
      |top menu|

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu origin:0.0@0.0 corner:1.0@30 in:top.
      menu level:1.
      menu labels:#('foo' 'bar').
      menu selectors:#(foo bar).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      menu at:#bar 
           putLabels:#('bar1' 'bar2' 'bar3')
           selectors:#(bar1 bar2 bar3)
           receiver:nil.
      top open
empty entries are possible as selectable items (with non-nil seletor) ...
      |top menu|

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu origin:0.0@0.0 corner:1.0@30 in:top.
      menu labels:#('foo' 'bar' 'baz').
      menu selectors:#(foo bar baz).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      menu at:#baz 
           putLabels:#('baz1' 'baz2' 'baz3')
           selectors:#(baz1 baz2 baz3)
           receiver:nil.
      top open
... or as separators (with nil selector)
      |top menu|

      top := StandardSystemView new.
      top extent:500@200.

      menu := PullDownMenu origin:0.0@0.0 corner:1.0@30 in:top.
      menu labels:#('foo' '    ' 'bar' ' baz' '    ' 'moreFoo' 'moreBar' 'moreBaz').
      menu selectors:#(foo nil bar baz nil moreFoo moreBar moreBaz).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      menu at:#bar 
           putLabels:#('bar1' 'bar2' 'bar3')
           selectors:#(bar1 bar2 bar3)
           receiver:nil.
      menu at:#baz 
           putLabels:#('baz1' 'baz2' 'baz3')
           selectors:#(baz1 baz2 baz3)
           receiver:nil.
      top open
use the menus default height
      |top menu|

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu in:top.
      menu origin:0.0@0.0 corner:1.0@(menu height).
      menu labels:#('foo' 'bar').
      menu selectors:#(foo bar).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      top open
although you can change the font, colors etc. (as shown below) you should NOT do it - since if you do so, the styleSheet settings are ineffective (which users probably won't like) BTW: The styleSheet entries for below are pullDownMenuForegroundColor, pullDownMenuBackgroundColor and pullDownMenuFont
      |top menu|

      top := StandardSystemView new.
      menu := PullDownMenu in:top.
      menu font:(Font family:'courier' size:20).
      menu foregroundColor:Color red.
      menu backgroundColor:Color yellow.
      menu viewBackground:Color green.
      menu showSeparatingLines:true.

      menu origin:0.0@0.0 corner:1.0@(menu height).
      menu labels:#('foo' 'bar').
      menu selectors:#(foo bar).
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      (menu menuAt:#foo) font:(Font family:'courier' size:36).
      top open
you can use icons, too ...
      |labels top menu|

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu in:top.
      menu origin:0.0@0.0 corner:1.0@(menu height).
      labels := Array with:((Image fromFile:'SmalltalkX.xbm') magnifiedTo:16@16)
                      with:'foo'
                      with:'bar'.
      menu labels:labels.
      menu selectors:#(about foo bar).
      menu at:#about 
           putLabels:#('about PullDownMenus')
           selectors:#(aboutMenus)
           receiver:nil.
      menu at:#foo
           putLabels:#('foo1' 'foo2' 'foo3')
           selectors:#(foo1 foo2 foo3)
           receiver:nil.
      top open
a concrete example (combining things described above) (using a Plug, since we have no application class here):
      |labels top menu textView appModel|

      appModel := Plug new.
      appModel respondTo:#quit with:[top destroy].
      appModel respondTo:#showAbout with:[self information:'some info here ...'].
      appModel respondTo:#help with:[self information:'some help here ...'].

      top := StandardSystemView new.
      top extent:300@300.

      menu := PullDownMenu in:top.
      menu receiver:appModel.
      menu origin:0.0@0.0 corner:1.0@(menu height).

      textView := ScrollableView forView:(EditTextView new).
      textView origin:0.0@menu height corner:1.0@1.0.
      top addSubView:textView.

      labels := Array with:((Image fromFile:'SmalltalkX.xbm') magnifiedTo:16@16)
                      with:'file'
                      with:'edit'
                      with:'help'.
      menu labels:labels.
      menu selectors:#(about file edit help).
      menu at:#about 
           putLabels:#('about PullDownMenus')
           selectors:#(showAbout)
           receiver:appModel.
      menu at:#file 
           putLabels:#('quit')
           selectors:#(quit)
           receiver:appModel.
      menu at:#edit 
           putLabels:#('copy' 'cut' 'paste')
           selectors:#(copySelection cut paste)
           receiver:textView.
      top open


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Fri, 29 Mar 2024 06:09:28 GMT