MenuEditor.st
author tz
Thu, 29 Jan 1998 19:44:04 +0100
changeset 526 7a4749b25748
parent 525 3c59244da8c8
child 532 de091386bbae
permissions -rw-r--r--
style revised

"
 COPYRIGHT (c) 1997 by eXept Software AG / 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.
"



ToolApplicationModel subclass:#MenuEditor
	instanceVariableNames:'isModified specClass specCanvas helpCanvas tabSelection aspects
		slices didInstall'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

Object subclass:#Item
	instanceVariableNames:'activeHelpKey enabled label value nameKey indication shortcutKey
		accessCharacterPos retriever icon iconAndLabel submenuChannel
		argument translateLabel isButton'
	classVariableNames:''
	poolDictionaries:''
	privateIn:MenuEditor
!

SelectionInTreeView subclass:#TreeView
	instanceVariableNames:'images'
	classVariableNames:'CopyBuffer Images'
	poolDictionaries:''
	privateIn:MenuEditor
!

!MenuEditor class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by eXept Software AG / 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.
"


!

documentation
"
    create and modify or inspect popup and pullDown menus of the
    new style( derives from Menu).

    [start with:]
        MenuEditor open
        MenuEditor new openOnClass:MenuEditor andSelector:#menuPullDown

    [see also:]
        UIPainter
        UIHelpTool
        UISpecificationTool
        SelectionInTreeView

    [author:]
        Claus Atzkern, Thomas Zwick
"

! !

!MenuEditor class methodsFor:'initialization'!

initialize

    super initialize.

    TreeView initialize
! !

!MenuEditor class methodsFor:'instance creation'!

openModalOnClass:aClass andSelector:aSelector
    ^ self new openModalOnClass:aClass andSelector:aSelector


!

openOnClass:aClass andSelector:aSelector
    ^ self new openOnClass:aClass andSelector:aSelector


! !

!MenuEditor class methodsFor:'code generation'!

sourceCategory
    "returns the category where to install the menu
    "
    ^ 'accessing menu'
! !

!MenuEditor class methodsFor:'help specs'!

helpSpec
    "return a dictionary filled with helpKey -> helptext associations.
     These are used by the activeHelp tool."

    "
    UIHelpTool openOnClass:MenuEditor    
    "

  ^ super helpSpec addPairsFrom:#(

#accessCharaterPos
'The index of the access character position into the textual label (optional).'

#argument
'An argument passed to the value method, if the value  selector is a one- or two-arg selector (i.e. ends with '':''). The argument is passed as a string.'

#enbled
'This enabled field specifies the name of the aspect (-method or binding) in your application, which returns a value holder holding a boolean, a block which evaluates to either true or false, a selector which returns either true or false or simply true or false. The value, true or false, specifies whether  the respective field can be selected, a value of true, or not, a value of false.'

#icon
'Selector which returns an image to be displayed.'

#iconAndLabel
'Boolean flag to specify that both image and textual label shall be shown.'

#indication
'This indication field specifies the name of the aspect (-method or binding) in your application, a value holder holding a boolean, a block which evaluates to either true or false, a selector which returns either true or false or simply true or false. The value, true or false, specifies whether the shown indicator is switched on or off.'

#label
'The label of the item. If the ''retriever/selector'' is set,  and returns an image, the image is used as the displayed label.  Dependent on the state of the ''Image & Label'' flag, both the image and the label are shown.'

#menuSelector
'The name of the selector under which the generated  menu should be installed and is accessable.'

#nameKey
'An unique identifier of the item (optional)'

#retriever
'The name of the class, which implements the image selector.  This selector is specified by ''selector''. If no class is given,  the current application should implement the specified image selector.'

#seperatorList
'The list of valid separators'

#shortcutKey
'The key to be pressed, to select the menu item from the keyboard (accelerator key).'

#submenuChannel
'A value holder, which provides the submenu (Menu) to be opened if the item is selected. Useful if the items submenu is to be  changed dynamically.'

#value
'An action which can be either a block or a selector. Depending on the number of arguments to the action, the action will be called with the respective arguments. There can either zero, one or two arguments. The first argument to the action is the argument derived from the argument field and the second argument the selected item.'

)
! !

!MenuEditor class methodsFor:'interface specs'!

basicsItemSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#basicsItemSpec
     MenuEditor new openInterface:#basicsItemSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 170 0 315 0 436 0 633 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1160 870)
              #'bounds:' #(#Rectangle 170 315 437 634)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'nameKeyLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'label:' 'NameKey:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'nameKeyField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #nameKey
                    #'tabable:' true
                    #'model:' #nameKey
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'labelLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #'label:' 'Label:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'labelField'
                    #'layout:' #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #'activeHelpKey:' #label
                    #'tabable:' true
                    #'model:' #label
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'valueLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 90 0 1 0.5)
                    #'label:' 'Value:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'valueField'
                    #'layout:' #(#LayoutFrame 110 0 79 0 -5 1.0 101 0)
                    #'activeHelpKey:' #value
                    #'tabable:' true
                    #'model:' #value
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'argumentLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 115 0 1 0.5)
                    #'label:' 'Argument:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'argumentField'
                    #'layout:' #(#LayoutFrame 110 0 104 0 -5 1.0 126 0)
                    #'activeHelpKey:' #argument
                    #'tabable:' true
                    #'model:' #argument
                    #'type:' #string
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'indicationLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 155 0 1 0.5)
                    #'label:' 'Indication:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'indicationField'
                    #'layout:' #(#LayoutFrame 110 0 144 0 -5 1.0 166 0)
                    #'activeHelpKey:' #indication
                    #'tabable:' true
                    #'model:' #indication
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#CheckBoxSpec
                    #'name:' 'translateLabelCheckBox'
                    #'layout:' #(#Point 20 192)
                    #'activeHelpKey:' #translateLabel
                    #'tabable:' true
                    #'model:' #translateLabel
                    #'label:' 'Translate Label'
                )
                 #(#CheckBoxSpec
                    #'name:' 'isButtonCheckBox'
                    #'layout:' #(#Point 20 221)
                    #'activeHelpKey:' #translateLabel
                    #'tabable:' true
                    #'model:' #isButton
                    #'label:' 'Is Button'
                )
              )
          )
      )
!

basicsLinkSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#basicsLinkSpec
     MenuEditor new openInterface:#basicsLinkSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 374 0 432 0 640 0 750 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 374 432 641 751)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'nameKeyLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'activeHelpKey:' #nameKey
                    #'label:' 'NameKey:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'nameKeyField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #nameKey
                    #'tabable:' true
                    #'model:' #nameKey
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'labelLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #'label:' 'Label:'
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'labelField'
                    #'layout:' #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #'activeHelpKey:' #label
                    #'tabable:' true
                    #'model:' #label
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'menuLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 76 0 1 0.5)
                    #'label:' 'Menu:'
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'menuField'
                    #'layout:' #(#LayoutFrame 110 0 65 0 -5 1.0 87 0)
                    #'activeHelpKey:' #submenuChannel
                    #'tabable:' true
                    #'model:' #submenuChannel
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'ArgumentLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 100 0 1 0.5)
                    #'label:' 'Argument:'
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'argumentField'
                    #'layout:' #(#LayoutFrame 110 0 90 0 -5 1.0 112 0)
                    #'activeHelpKey:' #submenuChannel
                    #'tabable:' true
                    #'model:' #submenuArgument
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#CheckBoxSpec
                    #'name:' 'translateLabelCheckBox'
                    #'layout:' #(#Point 20 128)
                    #'activeHelpKey:' #translateLabel
                    #'tabable:' true
                    #'model:' #translateLabel
                    #'label:' 'Translate Label'
                )
              )
          )
      )
!

basicsMenuSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#basicsMenuSpec
     MenuEditor new openInterface:#basicsMenuSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 456 0 430 0 722 0 748 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 456 430 723 749)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'nameKeyLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'label:' 'NameKey:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'nameKeyField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #nameKey
                    #'tabable:' true
                    #'model:' #nameKey
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'labelLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #'label:' 'Label:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'labelField'
                    #'layout:' #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #'activeHelpKey:' #label
                    #'tabable:' true
                    #'model:' #label
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#CheckBoxSpec
                    #'name:' 'translateLabelCheckBox'
                    #'layout:' #(#Point 20 100)
                    #'activeHelpKey:' #translateLabel
                    #'tabable:' true
                    #'model:' #translateLabel
                    #'label:' 'Translate Label'
                )
              )
          )
      )
!

basicsRootSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#basicsRootSpec
     MenuEditor new openInterface:#basicsRootSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 230 0 231 0 496 0 549 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 230 231 497 550)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'selectorLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'label:' 'Selector:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'selectorField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #menuSelector
                    #'tabable:' true
                    #'model:' #label
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
              )
          )
      )
!

basicsSeparatorSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#basicsSeparatorSpec
     MenuEditor new openInterface:#basicsSeparatorSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 359 0 319 0 625 0 637 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1160 870)
              #'bounds:' #(#Rectangle 359 319 626 638)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'separatorLabel'
                    #'layout:' #(#AlignmentOrigin 127 0 26 0 1 0.5)
                    #'label:' 'Separator Type:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#ComboListSpec
                    #'name:' 'seperatorList'
                    #'layout:' #(#LayoutFrame 132 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #seperatorList
                    #'tabable:' true
                    #'model:' #seperatorSelection
                    #'useIndex:' true
                )
              )
          )
      )
!

classDefineSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#classDefineSpec
     MenuEditor new openInterface:#classDefineSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'Menu Editor'
              #'layout:' #(#LayoutFrame 262 0 426 0 508 0 519 0)
              #'label:' 'Menu Editor'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1152 900)
              #'bounds:' #(#Rectangle 262 426 509 520)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'boxLabel'
                    #'layout:' #(#LayoutFrame 2 0.0 4 0 -2 1.0 24 0)
                    #'label:' 'Class for code:'
                    #'adjust:' #left
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'classNameField'
                    #'layout:' #(#LayoutFrame 2 0.0 27 0 -2 1.0 49 0)
                    #'tabable:' true
                    #'model:' #classNameChannel
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#UISubSpecification
                    #'name:' 'SubSpecification'
                    #'layout:' #(#LayoutFrame 0 0 -29 1 0 1 -5 1)
                    #'majorKey:' #ToolApplicationModel
                    #'minorKey:' #windowSpecForCommitWithoutChannels
                )
              )
          )
      )
!

detailsEditSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#detailsEditSpec
     MenuEditor new openInterface:#detailsEditSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 237 0 249 0 495 0 536 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 237 249 496 537)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'shortcutKeyLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'label:' 'Accelerator:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'shortcutKeyField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #shortcutKey
                    #'tabable:' true
                    #'model:' #shortcutKey
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'enabledLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #'label:' 'Enabled:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'enabledField'
                    #'layout:' #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #'activeHelpKey:' #enbled
                    #'tabable:' true
                    #'model:' #enabled
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'accessCharLabel'
                    #'layout:' #(#AlignmentOrigin 217 0 90 0 1 0.5)
                    #'label:' 'Access Character Position:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'accessCharField'
                    #'layout:' #(#LayoutFrame 220 0 79 0 -5 1.0 101 0)
                    #'activeHelpKey:' #accessCharaterPos
                    #'tabable:' true
                    #'model:' #accessCharacterPos
                    #'type:' #numberOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
              )
          )
      )
!

imageEditSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#imageEditSpec
     MenuEditor new openInterface:#imageEditSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'unnamed canvas'
              #'layout:' #(#LayoutFrame 104 0 316 0 348 0 457 0)
              #'label:' 'unnamed canvas'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 104 316 349 458)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'retrieverLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #'label:' 'Retriever:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'retrieverField'
                    #'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #'activeHelpKey:' #retriever
                    #'tabable:' true
                    #'model:' #retriever
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#LabelSpec
                    #'name:' 'iconLabel'
                    #'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #'label:' 'Selector:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'iconField'
                    #'layout:' #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #'activeHelpKey:' #icon
                    #'tabable:' true
                    #'model:' #icon
                    #'type:' #symbolOrNil
                    #'acceptOnReturn:' false
                    #'acceptOnTab:' false
                )
                 #(#ActionButtonSpec
                    #'name:' 'imageEditorButton'
                    #'layout:' #(#LayoutFrame 110 0 66 0 -5 1 90 0)
                    #'label:' 'Image Editor'
                    #'tabable:' true
                    #'model:' #doEditImage
                )
                 #(#CheckBoxSpec
                    #'name:' 'iconAndLabel'
                    #'layout:' #(#LayoutOrigin 20 0 104 0)
                    #'activeHelpKey:' #iconAndLabel
                    #'tabable:' true
                    #'model:' #iconAndLabel
                    #'label:' 'Image & Label'
                )
              )
          )
      )
!

windowSpec
    "this window spec was automatically generated by the ST/X UIPainter"

    "do not manually edit this - the painter/builder may not be able to
     handle the specification if its corrupted."

    "
     UIPainter new openOnClass:MenuEditor andSelector:#windowSpec
     MenuEditor new openInterface:#windowSpec
    "
    "MenuEditor open"

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'Menu Builder'
              #'layout:' #(#LayoutFrame 221 0 394 0 800 0 777 0)
              #'label:' 'Menu Builder'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1152 900)
              #'bounds:' #(#Rectangle 221 394 801 778)
              #'menu:' #menu
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#MenuPanelSpec
                    #'name:' 'menuToolbarView'
                    #'layout:' #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
                    #'menu:' #menuToolbar
                    #'showSeparatingLines:' true
                )
                 #(#VariableHorizontalPanelSpec
                    #'name:' 'variableHorizontalPanel1'
                    #'layout:' #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -22 1.0)
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ArbitraryComponentSpec
                              #'name:' 'painterView'
                              #'menu:' #menuEdit
                              #'hasHorizontalScrollBar:' true
                              #'hasVerticalScrollBar:' true
                              #'component:' #treeView
                              #'hasBorder:' false
                          )
                           #(#ViewSpec
                              #'name:' 'view1'
                              #'component:' 
                               #(#SpecCollection
                                  #'collection:' 
                                   #(
                                     #(#NoteBookViewSpec
                                        #'name:' 'specificationView'
                                        #'layout:' #(#LayoutFrame 1 0.0 0 0.0 1 1.0 -26 1.0)
                                        #'tabable:' true
                                        #'model:' #tabModel
                                        #'menu:' #tabList
                                        #'useIndex:' true
                                        #'canvas:' #noteBookView
                                    )
                                     #(#UISubSpecification
                                        #'name:' 'SubSpecification'
                                        #'layout:' #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
                                        #'majorKey:' #ToolApplicationModel
                                        #'minorKey:' #windowSpecForCommit
                                    )
                                  )
                              )
                              #'level:' -1
                          )
                        )
                    )
                    #'level:' 1
                    #'handles:' #(#Any 0.384483 1.0)
                )
                 #(#UISubSpecification
                    #'name:' 'infoBarSubSpec'
                    #'layout:' #(#LayoutFrame 0 0.0 -22 1 0 1.0 0 1.0)
                    #'majorKey:' #ToolApplicationModel
                    #'minorKey:' #windowSpecForInfoBar
                )
              )
          )
      )
! !

!MenuEditor class methodsFor:'menu specs'!

menu
    "this window spec was automatically generated by the ST/X MenuEditor"

    "do not manually edit this - the builder may not be able to
     handle the specification if its corrupted."

    "
     MenuEditor new openOnClass:MenuEditor andSelector:#menu
     (Menu new fromLiteralArrayEncoding:(MenuEditor menu)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'About'
                #'accessCharacterPosition:' 1
                #'labelImage:' #(#ResourceRetriever nil #icon)
                #'submenuChannel:' #menuAbout
            )
             #(#MenuItem
                #'label:' 'File'
                #'translateLabel:' true
                #'value:' #file
                #'submenu:' 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #'label:' 'New'
                          #'value:' #doNew
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Load...'
                          #'translateLabel:' true
                          #'value:' #doFromClass
                          #'enabled:' #isStandAlone
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Save'
                          #'value:' #doInstallSpec
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Pick A Menu'
                          #'value:' #doPickAMenu
                          #'enabled:' #isStandAlone
                      )
                       #(#MenuItem
                          #'label:' 'Define Menu Class...'
                          #'value:' #doDefineClass
                          #'enabled:' #isStandAlone
                      )
                       #(#MenuItem
                          #'label:' 'Browse Menu Class'
                          #'value:' #doBrowseAppClass
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Exit'
                          #'translateLabel:' true
                          #'value:' #closeRequest
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #'label:' 'Edit'
                #'submenuChannel:' #menuEdit
            )
             #(#MenuItem
                #'label:' 'Add'
                #'submenuChannel:' #menuAdd
            )
             #(#MenuItem
                #'label:' 'Test'
                #'submenuChannel:' #submenuTest
            )
             #(#MenuItem
                #'label:' 'History'
                #'submenuChannel:' #menuHistory
            )
             #(#MenuItem
                #'label:' 'Help'
                #'submenuChannel:' #menuHelp
            )
          ) nil
          nil
      )
!

menuAdd
    "this window spec was automatically generated by the ST/X MenuEditor"

    "do not manually edit this - the builder may not be able to
     handle the specification if its corrupted."

    "
     MenuEditor new openOnClass:MenuEditor andSelector:#menuAdd
     (Menu new fromLiteralArrayEncoding:(MenuEditor menuAdd)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'Item'
                #'value:' #doCreateItem
                #'labelImage:' #(#ResourceRetriever #MenuEditor #menuItemImage 'Item')
            )
             #(#MenuItem
                #'label:' 'Separator'
                #'value:' #doCreateSep
                #'labelImage:' #(#ResourceRetriever #MenuEditor #menuSeparatorImage 'Separator')
            )
             #(#MenuItem
                #'label:' '-'
            )
             #(#MenuItem
                #'label:' 'Submenu'
                #'value:' #doCreateMenu
                #'labelImage:' #(#ResourceRetriever #MenuEditor #submenuImage 'Submenu')
            )
             #(#MenuItem
                #'label:' 'Submenu Link'
                #'value:' #doCreateLink
                #'labelImage:' #(#ResourceRetriever #MenuEditor #linkSubmenuImage 'Submenu Link')
            )
          ) nil
          nil
      )
!

menuDefaultLink
    "this window spec was automatically generated by the ST/X MenuEditor"

    "do not manually edit this - the builder may not be able to
     handle the specification if its corrupted."

    "
     MenuEditor new openOnClass:MenuEditor andSelector:#menuDefaultLink
     (Menu new fromLiteralArrayEncoding:(MenuEditor menuDefaultLink)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' '!! derives from application !!'
            )
          ) nil
          nil
      )
!

menuEdit
    "this window spec was automatically generated by the ST/X MenuEditor"

    "do not manually edit this - the builder may not be able to
     handle the specification if its corrupted."

    "
     MenuEditor new openOnClass:MenuEditor andSelector:#menuEdit
     (Menu new fromLiteralArrayEncoding:(MenuEditor menuEdit)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'Cut'
                #'value:' #doCut
                #'enabled:' #hasValidSelection
                #'shortcutKeyCharacter:' #Cut
            )
             #(#MenuItem
                #'label:' 'Copy'
                #'value:' #doCopy
                #'enabled:' #hasValidSelection
                #'shortcutKeyCharacter:' #Copy
            )
             #(#MenuItem
                #'label:' 'Paste'
                #'value:' #doPaste
                #'enabled:' #hasAnySingleSelection
                #'shortcutKeyCharacter:' #Paste
            )
             #(#MenuItem
                #'label:' '-'
            )
             #(#MenuItem
                #'label:' 'Move Up'
                #'value:' #doStepUp
                #'enabled:' #enabledStepOver
                #'labelImage:' #(#ResourceRetriever #MenuEditor #upIcon 'Move Up')
            )
             #(#MenuItem
                #'label:' 'Move Down'
                #'value:' #doStepDown
                #'enabled:' #enabledStepOver
                #'labelImage:' #(#ResourceRetriever #MenuEditor #downIcon 'Move Down')
            )
             #(#MenuItem
                #'label:' 'Move In'
                #'value:' #doStepIn
                #'enabled:' #enabledStepIn
                #'labelImage:' #(#ResourceRetriever #MenuEditor #downRightIcon 'Move In')
            )
             #(#MenuItem
                #'label:' 'Move Out'
                #'value:' #doStepOut
                #'enabled:' #enabledStepOut
                #'labelImage:' #(#ResourceRetriever #MenuEditor #leftDownIcon 'Move Out')
            )
          ) nil
          nil
      )
!

menuToolbar
    "this window spec was automatically generated by the ST/X MenuEditor"

    "do not manually edit this - the builder may not be able to
     handle the specification if its corrupted."

    "
     MenuEditor new openOnClass:MenuEditor andSelector:#menuToolbar
     (Menu new fromLiteralArrayEncoding:(MenuEditor menuToolbar)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'New'
                #'isButton:' true
                #'value:' #doNew
                #'labelImage:' #(#ResourceRetriever nil #newIcon)
            )
             #(#MenuItem
                #'label:' 'Load'
                #'isButton:' true
                #'value:' #doFromClass
                #'labelImage:' #(#ResourceRetriever nil #loadIcon)
            )
             #(#MenuItem
                #'label:' 'Save'
                #'isButton:' true
                #'value:' #doInstallSpec
                #'labelImage:' #(#ResourceRetriever nil #saveIcon)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'Create Item'
                #'isButton:' true
                #'value:' #doCreateItem
                #'enabled:' #hasAnySingleSelection
                #'labelImage:' #(#ResourceRetriever nil #menuItemImage)
            )
             #(#MenuItem
                #'label:' 'Create Separator'
                #'isButton:' true
                #'value:' #doCreateSep
                #'enabled:' #hasAnySingleSelection
                #'labelImage:' #(#ResourceRetriever nil #menuSeparatorImage)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'Create Menu'
                #'isButton:' true
                #'value:' #doCreateMenu
                #'enabled:' #hasAnySingleSelection
                #'labelImage:' #(#ResourceRetriever nil #submenuImage)
            )
             #(#MenuItem
                #'label:' 'Create Link'
                #'isButton:' true
                #'value:' #doCreateLink
                #'enabled:' #hasAnySingleSelection
                #'labelImage:' #(#ResourceRetriever nil #linkSubmenuImage)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'Move Up'
                #'isButton:' true
                #'value:' #doStepUp
                #'enabled:' #enabledStepOver
                #'labelImage:' #(#ResourceRetriever nil #upIcon)
            )
             #(#MenuItem
                #'label:' 'Move Down'
                #'isButton:' true
                #'value:' #doStepDown
                #'enabled:' #enabledStepOver
                #'labelImage:' #(#ResourceRetriever nil #downIcon)
            )
             #(#MenuItem
                #'label:' 'Move In'
                #'isButton:' true
                #'value:' #doStepIn
                #'enabled:' #enabledStepIn
                #'labelImage:' #(#ResourceRetriever nil #downRightIcon)
            )
             #(#MenuItem
                #'label:' 'Move Out'
                #'isButton:' true
                #'value:' #doStepOut
                #'enabled:' #enabledStepOut
                #'labelImage:' #(#ResourceRetriever nil #leftDownIcon)
            )
          ) nil
          nil
      )
! !

!MenuEditor class methodsFor:'resources'!

linkSubmenuImage
    "Generated by the Image Editor"
    "
    ImageEditor openOnClass:self andSelector:#linkSubmenuImage
    "

    <resource: #image>

    ^Icon
        constantNamed:#'MenuEditor linkSubmenuImage'
        ifAbsentPut:[(Depth4Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@ADQDQDQDQDQDQH@D"H"H"H"H"H"K0@RH"H"H"H"H"H/@A????????????<@D@@@@@@@@@@@C0@PL3L0DQDQDQD_@A@3L3LBH"H"H"<@DCL3L3@"H"H"K0@PL3L3L0??????@A@@@@L3L@@@@@<@DQDQDCL3@PLAG0@RH"H"@3L0@3@/@AH"H"H L3L3L0<@G?????<CL3L3L@@P@@@@@@@3L3LO@ADQDQDQDP@CLA<@D"H"H"H"H LBK0@RH"H"H"H"@BH/@B????????????<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@b'); colorMap:((OrderedCollection new add:(Color black); add:(Color white); add:(Color grey:66.9978); add:(Color red:100.0 green:0.0 blue:0.0); add:(Color red:0.0 green:100.0 blue:0.0); add:(Color red:0.0 green:0.0 blue:100.0); add:(Color red:0.0 green:100.0 blue:100.0); add:(Color red:100.0 green:100.0 blue:0.0); add:(Color red:100.0 green:0.0 blue:100.0); add:(Color red:49.9962 green:0.0 blue:0.0); add:(Color red:0.0 green:49.9962 blue:0.0); add:(Color red:0.0 green:0.0 blue:49.9962); add:(Color red:0.0 green:49.9962 blue:49.9962); add:(Color red:49.9962 green:49.9962 blue:0.0); add:(Color red:49.9962 green:0.0 blue:49.9962); add:(Color grey:49.9962); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a'); yourself); yourself]!

menuItemImage
    "Generated by the Image Editor"
    "
    ImageEditor openOnClass:self andSelector:#menuItemImage
    "

    <resource: #image>

    ^Icon
        constantNamed:#'MenuEditor menuItemImage'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'UUUUUUUQUUUUUUUPUUUUUUU_UUUUUUUPUUUUUUUP@@@@@@@@EUUUUUVAF*****+HF:?+::;@F:.+*?;@F:.+::;@F:.+*:;@F:.+::;@F*****+DK??????A@@@@@@@@UUUUUUUPUUUUUUUXUUUUUUUPUUUUUUUPUUUUUUUPUUUUUUUX'); colorMap:(((Array new:4) at:1 put:((Color black)); at:2 put:((Color white)); at:3 put:((Color grey:66.9978)); at:4 put:((Color grey:49.9962)); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a'); yourself); yourself]!

menuSeparatorImage
    "Generated by the Image Editor"
    "
    ImageEditor openOnClass:self andSelector:#menuSeparatorImage
    "

    <resource: #image>

    ^Icon
        constantNamed:#'MenuEditor menuSeparatorImage'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'UUUUUUURUUUUUUUPUUUUUUUPUUUUUUUPUUUUUUUP@@@@@@@@EUUUUUV@F*****+DF*****+CF?????+@F0@@@@[@F%UUUU[HF*****+@F*****+@K??????N@@@@@@@HUUUUUUUPUUUUUUUPUUUUUUUWUUUUUUUXUUUUUUUPUUUUUUUP'); colorMap:(((Array new:4) at:1 put:((Color black)); at:2 put:((Color white)); at:3 put:((Color grey:66.9978)); at:4 put:((Color grey:49.9962)); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a'); yourself); yourself]!

submenuImage
    "Generated by the Image Editor"
    "
    ImageEditor openOnClass:self andSelector:#submenuImage
    "

    <resource: #image>

    ^Icon
        constantNamed:#'MenuEditor submenuImage'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@EUUUUUV@F*****+@F*****+@G??????GD@@@@@C@EUUUUUWLF*****+@F*****+@G??????HD@@@@@C@EUUUUUW@F*****+@F*****+OG??????@D@@@@@C@EUUUUUW@F*****+@F*****+@K??????@@@@@@@@@@@@@@@@@'); colorMap:(((Array new:4) at:1 put:((Color black)); at:2 put:((Color white)); at:3 put:((Color grey:66.9978)); at:4 put:((Color grey:49.9962)); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a'); yourself); yourself]! !

!MenuEditor class methodsFor:'slices'!

slicesItem
    ^#(
            (Basics     basicsItemSpec)
            (Details    detailsEditSpec)
            (Image      imageEditSpec)
      )

!

slicesLink
    ^#(
            (Basics     basicsLinkSpec)
            (Details    detailsEditSpec)
            (Image      imageEditSpec)
      )

!

slicesMenu
    ^#(
            (Basics     basicsMenuSpec)
            (Details    detailsEditSpec)
            (Image      imageEditSpec)
      )

!

slicesRootMenu
    ^#(
            (Basics   basicsRootSpec)
      )

!

slicesSeparatorMenu
    ^#(
            (Basics   basicsSeparatorSpec)
      )

! !

!MenuEditor methodsFor:'accessing'!

isModified: aBoolean         
    "sets menu tree modifications; invoked by the painter."

    isModified := aBoolean
!

specClass

    ^specClass
!

specClass:aClass

    aClass isBehavior ifTrue:[specClass := aClass name]
                     ifFalse:[specClass := aClass]
!

submenuTest
    "returns submenu assigned to item test"

    |menu|

    (menu := self treeView asMenu) allItemsDo:
    [:anItem|
        anItem value:nil.
        anItem enabled:true.
    ].
    ^menu
!

useHelpDictionary:aDictionary

    self noteBookView.
    self helpTool dictionary:aDictionary
! !

!MenuEditor methodsFor:'active help'!

defaultInfoLabel

    specClass isNil ifTrue: [^'No menu class defined'].
    ^specClass printString, ' >> ', self treeView selectorName
  
! !

!MenuEditor methodsFor:'aspects'!

aspectFor:aKey
    "returns aspect for a key or nil"

    ^aspects at: aKey ifAbsent: [super aspectFor:aKey]


!

enabledStepIn
    "returns whether user can put selected item in next submenu"

    ^builder booleanValueAspectFor: #enabledStepIn
!

enabledStepOut
    "returns whether user can put selected item out of current parent submenu"

    ^builder booleanValueAspectFor: #enabledStepOut
                         
!

enabledStepOver
    "returns whether user can shift selected item up or down"

    ^builder booleanValueAspectFor:#enabledStepOver
!

hasAnySingleSelection

    ^builder booleanValueAspectFor: #hasAnySingleSelection
!

hasValidSelection

    ^builder booleanValueAspectFor: #hasValidSelection
!

hasValidSingleSelection

    ^builder booleanValueAspectFor: #hasValidSingleSelection
!

noteBookView

    |noteBook helpTool|

    (noteBook := builder bindingAt:#noteBookView) isNil ifTrue:[
        noteBook := View new.
        helpTool := UIHelpTool new.

        helpTool masterApplication:self.
        helpCanvas := SubCanvas origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        specCanvas := SubCanvas origin:0.0@0.0 corner:1.0@1.0 in:noteBook.

        helpCanvas client:helpTool.
        helpTool masterApplication:self.      
        helpTool modifiedHolder: self valueOfEnablingCommitButtons.

        builder aspectAt:#noteBookView put:noteBook.
    ].
    ^ noteBook
!

tabList

    |holder|
    (holder := builder bindingAt:#tabList) isNil ifTrue:[
        builder aspectAt:#tabList put:(holder := #('Properties') asValue).
    ].
    ^ holder


!

tabModel

    |holder|
    (holder := builder bindingAt:#tabModel) isNil ifTrue:[
        holder := AspectAdaptor new subject:self; forAspect:#tabSelection.
        builder aspectAt:#tabModel put:holder.
    ].
    ^ holder

!

treeView
    "returns the tree view representing hierarchically all the menu items"

    |treeView|
    (treeView := builder bindingAt:#treeView) isNil ifTrue:[
        treeView := TreeView new.
        treeView action:[:dummy|self menuChanged].
        builder aspectAt: #treeView put: treeView
    ].
    ^treeView
! !

!MenuEditor methodsFor:'change & update'!

update:something with:aParameter from:changedObject
    "one of my value holders has changed its value, so let me set the editing menu as modified"            

    self valueOfEnablingCommitButtons value: true
!

updateEnabledChannels
    "update enabled channels"

    |node parent next state|

    state := false.   

    (node  := self treeView selectedNode) notNil
    ifTrue:
    [
        self hasAnySingleSelection value:true.
        (parent := node parent) notNil
        ifTrue:
        [
            next := parent childAt:((parent indexOfChild:node) + 1).
            self enabledStepIn           value:(next notNil and:[next hasChildren]).
            self enabledStepOver         value:(parent children size > 1).
            self enabledStepOut          value:(parent parent notNil).
            self hasValidSingleSelection value:true.
            self hasValidSelection       value:true.
          ^ self
        ]
    ]
    ifFalse:
    [
        self hasAnySingleSelection value:false.
        self treeView numberOfSelections ~~ 0 ifTrue:[
            state := (self treeView isInSelection:1) not
        ]
    ].          
    self enabledStepOver         value:false.
    self enabledStepIn           value:false.
    self enabledStepOut          value:false.
    self hasValidSingleSelection value:false.
    self hasValidSelection       value:state.
! !

!MenuEditor methodsFor:'event handling'!

doesNotUnderstand: aMessage
    "detour incoming messages to the tree view"

    (self treeView respondsTo: aMessage selector)
    ifTrue:
    [
        ^aMessage sendTo: self treeView
    ].
    super doesNotUnderstand:aMessage


! !

!MenuEditor methodsFor:'private'!

checkMenuItemModified
    "check menu item modification"

    self valueOfEnablingCommitButtons value
    ifTrue:
    [
        ((YesNoBox title:'Menu item was modified!!\Save it?\' withCRs)        
            noText:'No';
            yesText:'Yes';
            showAtPointer;
            accepted) 
        ifFalse: 
        [
            self valueOfEnablingCommitButtons value: false. 
            isModified := false.
            ^true
        ].
        self accept
    ].
    ^true
!

helpKey

    |node|
    (node := self treeView selectedNode) notNil ifTrue:[
        ^ node contents activeHelpKey
    ].
    ^ nil
!

helpTool

    ^helpCanvas application
! !

!MenuEditor methodsFor:'queries'!

didInstall
    "returns true if the menu was installed"

    ^didInstall
!

isHelpToolSelected
    "returns true if current selection is help tool"

    (tabSelection ~~ 0 and:[slices notNil]) ifTrue:[
        ^(slices at:tabSelection) first = UIHelpTool label
    ].
    ^false
!

isStandAlone
    "returns true in case of owner of the helptool"

    ^self masterApplication isNil
! !

!MenuEditor methodsFor:'selection'!

menuChanged

    |node item slc sel old dep|

    aspects do: [:holder| holder removeDependent:self].
    (node := self treeView selectedNode) notNil ifTrue:[
        aspects do:[:anAspect| anAspect value:nil ].
        item := node contents.
        item toAspects:aspects.

        item isSeparator ifFalse:[
            node parent isNil ifFalse:[
                node hasChildren ifTrue:[
                    slc := #slicesMenu
                ] ifFalse:[
                    item submenuChannel isNil ifTrue:[slc := #slicesItem]
                                             ifFalse:[slc := #slicesLink]
                ].
                slc := (self class perform:slc) copyWith:#( 'Help' #dummy ).
            ] ifTrue:[
                slc := self class perform:#slicesRootMenu
            ].
        ] ifTrue:[
            slc := self class perform:#slicesSeparatorMenu.
        ]
    ].

    self helpTool helpKey: self helpKey.
    "Next line helps me to preserve myself against unnecessary settings of
     valueOfEnablingCommitButtons to true in the help tool."
    self valueOfEnablingCommitButtons value: false.

    slc ~= slices  ifTrue:[
        tabSelection ~~ 0 ifTrue:[
            old := (slices at:tabSelection) first
        ].

        (slices := slc) notNil ifTrue:[
            sel := slices collect:[:s| s first].
            tabSelection := 0.
            self tabList value:sel.

            (old notNil and:[(sel := sel findFirst:[:n|n = old]) ~~ 0]) ifFalse:[
                sel := 1
            ].
            self tabModel value:sel
        ] ifFalse:[
            self tabList value:nil.
            self tabSelection:0.
        ]
    ].
    self updateEnabledChannels.
    aspects do: [:holder| holder addDependent:self].
!

tabSelection

    ^tabSelection ? 0
!

tabSelection: aSelection

    |sel|                 
    tabSelection = aSelection ifTrue:[
        ^ self
    ].
    (aSelection ~~ 0 and:[slices isNil]) ifTrue:[
        ^ self
    ].
    (tabSelection := aSelection) == 0 ifTrue:[
        slices isNil ifTrue:[
            specCanvas client:nil.
            ^ specCanvas raise.
        ].
        tabSelection == 1 ifTrue:[^ self].
        tabSelection := 1
    ].

    self isHelpToolSelected ifTrue:[  
        self helpTool helpKey:(self helpKey).
        helpCanvas raise.
    ] ifFalse:[                       
        sel := (slices at:tabSelection) last.   
        aspects do: [:holder| holder release].
        specCanvas client:self spec:(self class perform:sel) builder:builder.
        aspects do: [:holder| holder addDependent:self].
        specCanvas raise.  
    ]    

! !

!MenuEditor methodsFor:'startup / release'!

buildFrom:aClass andSelector:aSelector

    |oldClass newClass|

    self valueOfEnablingCommitButtons value: false.
    oldClass := self specClass.
    self specClass:aClass.
    newClass := self specClass.

    (self isStandAlone and:[oldClass ~= newClass]) ifTrue:[
        self helpTool helpSpecFrom:newClass
    ].
    self treeView buildFrom: newClass andSelector: aSelector.

    aClass notNil & aSelector notNil
    ifTrue:
    [
        |className message|
        aClass isClass ifTrue: [className := aClass name].
        aClass isString ifTrue: [className := aClass].
        message := className, ' ', aSelector.
        self addToHistory: message -> #loadFromMessage:
    ].

    self valueOfInfoLabel value: self defaultInfoLabel.
    self treeView selection: 2.
    self menuChanged

!

checkModified
    "check menu modification
    "
    isModified
    ifTrue:
    [
        ((YesNoBox title:'Menu was modified!!')        
            noText:'Cancel';
            yesText:'Waste it and proceed';
            showAtPointer;
            accepted) ifFalse: [^false].
        isModified := false
    ].
    ^true


!

closeRequest
    "close request"

    (self checkMenuItemModified and: [self checkModified]) ifTrue: [super closeRequest]





!

initialize
    "initialize value holders for the menu item properties"

    |holder|

    super initialize.
    aspects := IdentityDictionary new.
    tabSelection := 0.

    #(
        label
        accessCharacterPos
        argument
        submenuChannel
        submenuArgument
        enabled
        value
        nameKey
        indication
        translateLabel
        isButton
        shortcutKey
        retriever
        iconAndLabel
        icon

     ) do:[:aKey|
        aspects at:aKey put:(holder := ValueHolder new).
        holder addDependent: self
    ].

    aspects at:#seperatorSelection put:(holder := SelectionInList new).
    holder list: Item separatorList.
    holder addDependent:self.
!

loadFromMessage: aMessage

    (((aMessage size > 0) and: [self checkMenuItemModified]) and: [self checkModified])
    ifTrue:
    [
        |readStream aClass aSelector|
        readStream := aMessage readStream.
        aClass := Smalltalk at: (readStream upTo: $ ) asSymbol.
        aSelector :=  readStream upToEnd asSymbol.
        self buildFrom: aClass andSelector: aSelector
    ]
!

openModalOnClass:aClass andSelector:aSelector

    specClass := Association key:aClass value:aSelector.
    super openInterfaceModal.

!

openOnClass:aClass andSelector:aSelector

    specClass := Association key:aClass value:aSelector.
    super openInterface.
    self buildFrom:aClass andSelector:aSelector.

!

postBuildWith:builder
    |cls sel|

    didInstall := false.
    isModified := false.

    specClass isAssociation ifTrue:[
        cls := specClass key.
        sel := specClass value.

        specClass := nil.

        (sel isKindOf:Menu) ifTrue:[
            self buildFrom:cls andSelector:nil.
            ^self treeView buildFromMenu:sel.
        ]
        
    ].
    self buildFrom:cls andSelector:sel
!

postOpenWith:aBuilder

    self isHelpToolSelected 
        ifTrue:  [helpCanvas raise] 
        ifFalse: [specCanvas raise]    
! !

!MenuEditor methodsFor:'user interactions'!

accept
    "invoked by button 'OK' and by save requests of menu item changes"

    |node|
    node := self treeView selectedNode.
    node notNil
    ifTrue:
    [
        self isHelpToolSelected
        ifTrue:
        [
            self helpTool accept.
            node contents activeHelpKey: self helpTool helpKey
        ]
        ifFalse:
        [
            self treeView updateNode: (node contents buildFromAspects: aspects)
        ]
    ].
    self valueOfEnablingCommitButtons value:false.
    isModified := true
!

cancel
    "invoked by button 'Cancel'"

    |node|
    (node := self treeView selectedNode) notNil
    ifTrue:
    [          
        self helpTool helpKey:(self helpKey).
        aspects do:[:anAspect| anAspect value:nil].
        node contents toAspects:aspects
    ].
    self valueOfEnablingCommitButtons value: false.
    isModified := false
!

doBrowseAppClass
    "open a browser on the class"

    |cls|

    (cls := self resolveName: self specClass) notNil
    ifTrue:
    [
        SystemBrowser openInClass:cls class selector: self treeView selectorName
    ]
    ifFalse:
    [
        self information:'No valid class defined!!'.
    ]
!

doDefineClass

    aspects at:#classNameChannel  put:(self specClass asValue).

    (self openDialogInterface:#classDefineSpec) ifTrue:[
        self specClass:((aspects at:#classNameChannel) value)
    ].

!

doEditImage

    |cls resourceClass resourceSelector imageResourceMessage readStream|

    cls := self resolveName: self specClass.
    cls isNil ifTrue:[
        ^ self information:'No valid class defined!!'.
    ].
    (aspects at:#icon) value size > 0
        ifTrue:  [resourceSelector := (aspects at:#icon) value]
        ifFalse: [resourceSelector := #stxIcon].
    (aspects at:#retriever) value size > 0
        ifTrue:  [resourceClass := (aspects at:#retriever) value]
        ifFalse: [resourceClass := cls withAllSuperclasses detect: [:cls| cls class implements: resourceSelector] ifNone: [cls]].

    (imageResourceMessage := ImageEditor openModalOnClass: resourceClass andSelector: resourceSelector) notNil
    ifTrue:
    [
        readStream := imageResourceMessage readStream.
        resourceClass := (readStream upTo: $ ) asSymbol.
        resourceSelector := readStream upToEnd asSymbol.
        resourceClass size > 0 ifTrue: [(aspects at:#retriever) value: resourceClass].
        resourceSelector size > 0 ifTrue: [(aspects at:#icon) value: resourceSelector. self valueOfEnablingCommitButtons value: true]
    ]
!

doFromClass

    self loadFromInClassesOf: #Object
!

doInstallSpec
    |cls selector treeView menu spec mthd category code|

    cls := self resolveName:(self specClass).

    cls isNil ifTrue:[
        ^ self information:'No valid class defined!!'.
    ].
    treeView  := self treeView.
    selector := treeView selectorName.
    menu     := treeView asMenu.

    menu isNil ifTrue:[
        ^ self information:'No menu defined.'
    ].
    menu := menu literalArrayEncoding.
    spec := WriteStream on:String new.
    UISpecification prettyPrintSpecArray:menu on:spec indent:5.
    spec := spec contents.

    "/ if that method already exists, do not overwrite the category

    category := 'interface specs'.
    (mthd := cls class compiledMethodAt:selector) notNil ifTrue:[
        category := mthd category.
    ].

    code := Character excla asString 
            , cls name , ' class methodsFor:' , category storeString
            , Character excla asString , '\\'

            , selector , '\'
            , '    "this window spec was automatically generated by the ST/X MenuEditor"\\'
            , '    "do not manually edit this - the builder may not be able to\'
            , '     handle the specification if its corrupted."\\'
            , '    "\'
            , '     MenuEditor new openOnClass:' , cls name , ' andSelector:#' , selector , '\'
            , '     (Menu new fromLiteralArrayEncoding:(' , cls name , ' ' , selector , ')) startUp\'
            , '    "\'.

    code := code 
            , '\'
            , '    <resource: #menu>\\'
            , '    ^\' 
            , '     ', spec
            , '\'
            , Character excla asString
            , ' '
            , Character excla asString
            , '\\'.

    code := code withCRs.
    (ReadStream on:code) fileIn.

    self isStandAlone ifTrue:[
        self helpTool installHelpSpecInto:(self specClass)
    ].
    didInstall := true.
    isModified := false.

!

doNew

    self buildFrom:nil andSelector: self treeView selectorName
!

doPickAMenu

    |view|

    view := Screen current viewFromUser.

    (view isNil or:[view == Screen current rootView]) ifTrue:[
        ^ self
    ].
    view specClass == MenuPanelSpec ifTrue:[
        ^ self treeView buildFromMenu: view asMenu
    ].
    ^ nil
!

doStepDown
    "shift selected menu item one step down"

    self treeView selectedNodeChangeSequenceOrder:1.
    isModified := true.




!

doStepIn
    "move selected menu item into next submenu"

    self treeView selectedNodeBecomeChildOfNext.
    isModified := true.





!

doStepOut
    "move selected menu item out from parent submenu"

    self treeView selectedNodeBecomeSisterOfParent.
    isModified := true.
!

doStepUp
    "shift selected menu item one step up"

    self treeView selectedNodeChangeSequenceOrder:-1.
    isModified := true.
!

loadFromInClassesOf: aSuperclassOrSymbol

    self loadFromMessage: 
        (ResourceSelectionBrowser
            request: 'Load Menu From Class'
            onSuperclass: aSuperclassOrSymbol
            andClass: specClass
            andSelector: self treeView selectorName
            withResourceTypes: #(menu))
! !

!MenuEditor::Item class methodsFor:'constants'!

separatorList

    ^#('blank' 'single line' 'double line')
!

separatorSlices
   ^ #(
        ( #blank        ''  )
        ( #single       '-' )
        ( #double       '=' )
      )
! !

!MenuEditor::Item class methodsFor:'documentation'!

documentation
"
    implements the contents assigned to a TreeItem. An instance
    is associated with one item and keeps all its information

    [see also:]
        TreeItem
        MenuEditor

    [author:]
        Claus Atzkern
"


! !

!MenuEditor::Item methodsFor:'accessing'!

activeHelpKey

    ^activeHelpKey
!

activeHelpKey:aKey

    activeHelpKey := aKey
!

label
    "return the value of the instance variable 'label' (automatically generated)"

    ^label
!

label:something
    "set the value of the instance variable 'label' (automatically generated)"

    label := something ? '-'
!

separatorType
    "returns separator type assigned to item or nil"

    label size > 1 
    ifFalse:
    [
        label size  == 0  ifTrue:[^#blank].
        label first == $- ifTrue:[^#single].
        label first == $= ifTrue:[^#double].
    ].    
    ^nil

!

submenuChannel
    "return the value of the instance variable 'submenuChannel' (automatically generated)"

    ^submenuChannel
!

submenuChannel:aChannel
    "return the value of the instance variable 'submenuChannel' (automatically generated)"

    submenuChannel := aChannel
! !

!MenuEditor::Item methodsFor:'conversion'!

asMenuItem
    "converts self to a menu item"

    |item rcv|

    item := MenuItem labeled:label.

    self isSeparator ifFalse:[    
        item activeHelpKey:activeHelpKey.
        item enabled:enabled.
        item accessCharacterPosition:accessCharacterPos.
        item argument:argument.
        item submenuChannel:submenuChannel.
        item nameKey:nameKey.
        item shortcutKeyCharacter:shortcutKey.
        item value:value.
        item indication:indication.
        item translateLabel: translateLabel.
        item isButton: isButton.

        icon notNil ifTrue:[
            rcv := ResourceRetriever new.
            rcv className:retriever.
            rcv selector:icon.
            iconAndLabel == true ifTrue:[
                rcv labelText:label
            ].
            item labelImage:rcv
        ]
    ].
    ^item
!

buildFromAspects:aspects

    |name|
    self isSeparator 
    ifFalse:
    [
        name  := label.
        label := (aspects at:#label) value.

        (label isNil or:[self isSeparator]) ifTrue:[
            (aspects at:#label) value:(label := name)
        ].

        enabled            := (aspects at:#enabled) value.
        value              := (aspects at:#value) value.
        nameKey            := (aspects at:#nameKey) value.
        indication         := (aspects at:#indication) value.
        shortcutKey        := (aspects at:#shortcutKey) value.
        accessCharacterPos := (aspects at:#accessCharacterPos) value.
        argument           := (aspects at:#argument) value.
        translateLabel     := (aspects at:#translateLabel) value.
        isButton           := (aspects at:#isButton) value.

        argument isString ifTrue:[
            argument size > 1 ifTrue:[
                (argument at:1) == $# ifTrue:[
                    argument := (argument copyFrom:2) asSymbol
                ]
            ]
        ].
        submenuChannel    := (aspects at:#submenuChannel) value.
        retriever         := (aspects at:#retriever) value.
        icon              := (aspects at:#icon) value.
        iconAndLabel      := (aspects at:#iconAndLabel) value.
    ]
    ifTrue:
    [
        name  := (aspects at:#seperatorSelection) selectionIndex.
        label := (self class separatorSlices at:name) last.
    ]
!

buildFromMenuItem:anItem

    |rtv|

    self label:(anItem label).
    activeHelpKey := anItem activeHelpKey.

    (enabled := anItem enabled) isSymbol ifFalse:[
        enabled := nil
    ].

    (value := anItem value) isSymbol ifFalse:[
        value := nil.
    ].

    (indication := anItem indication) isSymbol ifFalse:[
        indication := nil
    ].

    nameKey            := anItem nameKey.
    shortcutKey        := anItem shortcutKeyCharacter.
    accessCharacterPos := anItem accessCharacterPosition.
    argument           := anItem argument.
    submenuChannel     := anItem submenuChannel.
    translateLabel     := anItem translateLabel.
    isButton           := anItem isButton.

    (((rtv := anItem adornment) notNil)
    and:[(rtv := rtv labelImage) isKindOf:ResourceRetriever])
    ifTrue:
    [
        retriever := rtv className.
        icon      := rtv selector.
        (iconAndLabel := rtv labelText notNil) ifTrue:[
            label := rtv labelText.
        ]
    ]
!

toAspects:aspects

    |type|
    (type := self separatorType) notNil
    ifTrue:
    [
        type := self class separatorSlices findFirst:[:el| el first == type ].
        (aspects at:#seperatorSelection) selectionIndex:type.
    ] 
    ifFalse:
    [
        (aspects at:#label)                value:label.
        (aspects at:#enabled)              value:enabled.
        (aspects at:#value)                value:value.
        (aspects at:#nameKey)              value:nameKey.
        (aspects at:#indication)           value:indication.
        (aspects at:#shortcutKey)          value:shortcutKey.
        (aspects at:#accessCharacterPos)   value:accessCharacterPos.
        (aspects at:#translateLabel)       value:translateLabel.
        (aspects at:#isButton)             value:isButton.
        (aspects at:#submenuChannel)       value:submenuChannel.
        (aspects at:#retriever)            value:retriever.
        (aspects at:#icon)                 value:icon.
        (aspects at:#iconAndLabel)         value:iconAndLabel.
        argument isSymbol
            ifTrue: [(aspects at:#argument)value:'#', argument] 
            ifFalse:[(aspects at:#argument)value:argument].
    ]
! !

!MenuEditor::Item methodsFor:'queries'!

isSeparator
    "returns true if item is a seperator"

    ^self separatorType notNil
! !

!MenuEditor::TreeView class methodsFor:'defaults'!

defaultMenuMessage   
    "this message is the default yo be sent to the menuHolder to get a menu"

    ^#menu


! !

!MenuEditor::TreeView class methodsFor:'documentation'!

documentation
"
    menu selection list

    [see also:]
        SelectionInTreeView
        SelectionInTree
        TreeItem

    [author:]
        Claus Atzkern
"


! !

!MenuEditor::TreeView class methodsFor:'initialization'!

initialize

    super initialize.

    Images := nil
! !

!MenuEditor::TreeView class methodsFor:'resources'!

images
    "returns an IdentityDictionary containing a list of images and keys used
    "
    ^ Images ?
        (Images := IdentityDictionary new
            at: #menuItemImage      put: MenuEditor menuItemImage;
            at: #menuSeparatorImage put: MenuEditor menuSeparatorImage;
            at: #submenuImage       put: MenuEditor submenuImage;
            at: #linkSubmenuImage   put: MenuEditor linkSubmenuImage;
            yourself)



! !

!MenuEditor::TreeView methodsFor:'accessing'!

selectorName
    ^ (listOfNodes first contents label) asSymbol
! !

!MenuEditor::TreeView methodsFor:'building'!

buildFrom:aClass andSelector:aSelector

    |spec cls menu node|

    (aClass notNil and:[aSelector notNil]) ifTrue:[
        cls := self application resolveName:aClass.

        (cls respondsTo:aSelector) ifTrue:[
            spec := cls perform:aSelector
        ]
    ].

    spec isNil ifFalse:[
        (spec isMemberOf:Menu) ifFalse:[
            menu := Menu new fromLiteralArrayEncoding:spec.
        ] ifTrue:[
            menu := spec.
        ].
        node := self nodeLabel:(aSelector asString).
        self subMenu:menu parent:node.
    ] ifTrue:[
        aSelector notNil ifTrue:[cls := aSelector asString]
                        ifFalse:[cls := 'menu'].

        node := self nodeLabel:cls.
    ].

    node hasChildren ifFalse:[
        node add:(self nodeLabel:'undefined')
    ].
    node expand.
    model root:node.

!

buildFromMenu:aMenu

    |node|

    node := self nodeLabel:'menu'.
    self subMenu:aMenu parent:node.

    node hasChildren ifFalse:[
        node add:(self nodeLabel:'undefined')
    ].
    node expand.
    model root:node.

!

menuItem:anItem

    |node|

    node := self nodeLabel: anItem label.
    node contents buildFromMenuItem:anItem.
    node name: node contents label.
    self subMenu: anItem submenu parent:node.
    ^node.


!

subMenu:aMenu parent:aParent

    |idx grp|

    aMenu isNil ifFalse:[
        grp := aMenu groupSizes.
        aMenu itemsDo:[:i| aParent add:(self menuItem:i)].

        grp notNil ifTrue:[
            idx := 0.

            grp do:[:i|
                idx := idx + i + 1.
                aParent add:(self nodeLabel:nil) beforeIndex:idx.
            ]
        ]
    ]
! !

!MenuEditor::TreeView methodsFor:'conversion'!

asMenu
    |menu root|

    root := self root.

    root hasChildren ifTrue:[
        menu := Menu new.
        root children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
    ].
  ^ menu
!

asMenuItem:aNode

    |menu item|

    item := aNode contents asMenuItem.

    aNode hasChildren ifTrue:[
        menu := Menu new.
        aNode children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
        item submenu:menu
    ].
  ^ item

! !

!MenuEditor::TreeView methodsFor:'drawing basics'!

drawLabelIndex:anIndex atX:x y:yCenter
    "draw text label assigned to a node at x y( center)"

    |y x2 type item|

    item := (listOfNodes at:anIndex) contents.
    type := item separatorType.

    type isNil ifTrue:[
        super drawLabelIndex:anIndex atX:x y:yCenter
    ] ifFalse:[
        type == #blank ifFalse:[
            x2 := x + 80.

            self displayLineFromX:x y:yCenter toX:x2 y:yCenter.

            type == #double ifTrue:[
                y := yCenter + 2.
                self displayLineFromX:x y:y toX:x2 y:y.
            ]    
        ]
    ]
!

figureFor:aNode
    "access figure for a node"

    aNode hasChildren
    ifFalse:
    [
        |item|
        (item := aNode contents) submenuChannel notNil ifTrue:[^images at: #linkSubmenuImage].
        item isSeparator ifTrue:[^images at: #menuSeparatorImage].
        ^images at: #menuItemImage
    ].
    ^images at: #submenuImage
! !

!MenuEditor::TreeView methodsFor:'event handling'!

keyPress:key x:x y:y
    "invoked if any key was pressed"

    <resource: #keyboard (#Delete #BackSpace #Cut #Copy #Paste)>

    (key == #Cut or:[key == #Delete or:[key == #BackSpace]]) ifTrue: [^self doCut].

    key == #Copy  ifTrue:[^self doCopy].
    key == #Paste ifTrue:[^self doPaste].

    super keyPress:key x:x y:y

! !

!MenuEditor::TreeView methodsFor:'initialization'!

fetchImageResources
    "initialize heavily used device resources - to avoid rendering
     images again and again later; returns maximum extent of the images used."

    |defaultExtent imageWidth imageHeight maxWidth maxHeight|

    defaultExtent := super fetchImageResources.
    maxHeight := defaultExtent y.
    maxWidth := defaultExtent x.

    images do:
    [:anIcon|
        (imageWidth  := anIcon widthOn:self)  > maxWidth  ifTrue:[maxWidth  := imageWidth].
        (imageHeight := anIcon heightOn:self) > maxHeight ifTrue:[maxHeight := imageHeight].
    ].
    ^maxWidth@maxHeight

!

initialize

    super initialize.

    images := IdentityDictionary new.

    self class images associationsDo:[:imageAsso|images at: imageAsso key put:(imageAsso value onDevice:device)].
    self multipleSelectOk:true.
    self showDirectoryIndicator: true.
    self showDirectoryIndicatorForRoot: false.
    self selectConditionBlock: [:i|self application checkMenuItemModified].
    self validateDoubleClickBlock: [:node| node ~~ listOfNodes first].
! !

!MenuEditor::TreeView methodsFor:'menus'!

doCopy

    self hasSelection ifTrue:[
        CopyBuffer := OrderedCollection new.
        self selectionDo:[:i| CopyBuffer add:((listOfNodes at:i) copy)]
    ]
!

doCreateItem

    self addElement:(self nodeLabel:'undefined')

!

doCreateLink

    |node item|

    node := self nodeLabel:'undefined'.
    item := node contents.
    item submenuChannel:#menuDefaultLink.
    self addElement:node.
    self setModified.


!

doCreateMenu

    |node|
    node := self nodeLabel:'undefined'.
    node add:(self nodeLabel:'undefined').
    self addElement:node
!

doCreateSep

    self addElement:(self nodeLabel:nil)
!

doCut

    self doCopy.
    self selectedNodesRemove.
    self setModified.


!

doPaste

    (CopyBuffer notNil and:[self selectedNode notNil]) ifTrue:[
        self addElement:(CopyBuffer collect:[:el| el copy])
    ].
! !

!MenuEditor::TreeView methodsFor:'private'!

addElement:something
    "add something after selection"

    self selectedNodeAdd:something.
    self setModified.
!

nodeLabel:aLabel

    ^TreeItem name:aLabel contents: (MenuEditor::Item new label:aLabel)
!

setModified 

    self topView application isModified: true.

    self topView application updateEnabledChannels
! !

!MenuEditor::TreeView methodsFor:'selection'!

updateNode: aNode

    |name treeItem index|

    name := aNode label.
    treeItem := listOfNodes detect: [:n| n contents = aNode] ifNone: [1].
    index := self indexOfNode: treeItem.
    treeItem name: name.
    self redrawLine: index.
! !

!MenuEditor::TreeView methodsFor:'startup / release'!

destroy
    "destroy images"

    super destroy.

    Images := nil


! !

!MenuEditor class methodsFor:'documentation'!

version
    ^ '$Header$'
! !
MenuEditor initialize!