MenuEditor.st
author Claus Gittinger <cg@exept.de>
Fri, 26 Oct 2001 18:51:35 +0200
changeset 1517 3f0c8ccd0c33
parent 1506 6525741c998e
child 1539 3e6fd1cb8eae
permissions -rw-r--r--
checkin from browser

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



"{ Package: 'stx:libtool2' }"

ResourceSpecEditor subclass:#MenuEditor
	instanceVariableNames:'treeView typeOfCanvas listOfCanvas listOfSlices
		lastImageRetriever slices'
	classVariableNames:'ImageRetrieverClasses'
	poolDictionaries:''
	category:'Interface-UIPainter'
!

Object subclass:#Item
	instanceVariableNames:'activeHelpKey enabled label value nameKey indication shortcutKey
		accessCharacterPos retriever icon iconAndLabel submenuChannel
		startGroup argument translateLabel isButton isVisible choice
		choiceValue auxValue hideMenuOnActivated font
		showBusyCursorWhilePerforming keepLinkedMenu triggerOnDown'
	classVariableNames:''
	poolDictionaries:''
	privateIn:MenuEditor
!

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

!MenuEditor class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by eXept Software AG
              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
"
    The MenuEditor allows you to create, modify or just inspect
    hierarchical menus of menu bars, popup menu, or tool bar menus.

    [start with:]
        MenuEditor open
        MenuEditor openOnClass:MenuEditor andSelector:#menu

    [see also:]
        UIPainter

    [author:]
        Claus Atzkern, eXept Software AG
        Thomas Zwick, eXept Software AG
"

! !

!MenuEditor class methodsFor:'initialization'!

initialize
    ImageRetrieverClasses := #( Icon
                                NewLauncher
                                SystemBrowser 
                              ) asList.
! !

!MenuEditor class methodsFor:'instance creation'!

openModalOnMenu: aMenu
    "Open a MenuEditor modal on aMenu"
    "self openModalOnMenu: (self perform: #menu) decodeAsLiteralArray"

    ^self new openModalOnMenu: aMenu
! !

!MenuEditor class methodsFor:'accessing'!

iconUnknown
    "returns an image used for picked items containing an image
    "
    <resource: #fileImage>

    ^ MenuPanelSpec icon
!

resourceType
    "get the type of resource of the method generated by the MenuEditor"

    ^#menu




! !

!MenuEditor class methodsFor:'accessing image retriever'!

addNewImageRetriever:aSymbolOrClass
    |key|

    aSymbolOrClass isString ifFalse:[
        aSymbolOrClass isBehavior ifTrue:[
            key := aSymbolOrClass nameWithNameSpacePrefix
        ]
    ] ifTrue:[
        key := aSymbolOrClass
    ].

    key size ~~ 0 ifTrue:[
        key := key asSymbol.

        (ImageRetrieverClasses identityIndexOf:key) == 0 ifTrue:[
            ImageRetrieverClasses add:key.
        ]
    ].
!

imageRetrieverClasses
    "returns a collection of image retrievers
    "
    ^ ImageRetrieverClasses
! !

!MenuEditor class methodsFor:'aspects'!

aspects
    "get the aspects for the attributes of the menu components"

    ^#(
        label
        accessCharacterPos
        showBusyCursorWhilePerforming
        triggerOnDown
        font
        argument
        submenuChannel
        keepLinkedMenu
        enabled
        value
        nameKey
        indication
        choice
        choiceValue
        translateLabel
        isButton
        shortcutKey
        startGroup
        retriever
        iconAndLabel
        icon
        isVisible
        hideMenuOnActivated
        auxValue
     )

    "Modified: / 14.8.1998 / 14:46:36 / cg"
! !

!MenuEditor class methodsFor:'help specs'!

helpSpec
    "This resource specification was automatically generated
     by the UIHelpTool of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIHelpTool may not be able to read the specification."

    "
     UIHelpTool openOnClass:MenuEditor    
    "

    <resource: #help>

    ^super helpSpec addPairsFrom:#(

#addMenuItem
'Add a new menu item.'

#addMenuSeparator
'Add a new menu separator.'

#addSubMenu
'Add a new sub menu.'

#addSubMenuLink
'Add a new linked sub menu.'

#basicsAction
'An action selector with 0, 1 (the argument field), or 2 (the selected item) arguments.'

#basicsArgument
'An optional arg passed with above selector, if it is a 1 or 2 arg selector (enter a Smalltalk literal).'

#basicsChoice
'Aspect for a boolean holder, block or method, specifying the choices state (RadioButton behavior).'

#basicsChoiceValue
'That choices value (typically number or symbol).'

#basicsIndication
'Aspect for boolean holder, block, or method, specifying the indication state (CheckToggle behavior).'

#basicsIsButton
'Enable/disable button-like behavior.'

#basicsKey
'Internal key of the item (optional, for programmed accesses).'

#basicsLabel
'Label of the item.'

#basicsMenu
'Aspect providing the sub menu to be opened if item is selected (provide spec or valueHolder).'

#basicsMenuArgument
'An argument passed with the menu selector.'

#basicsNameKey
'Unique identifier of the item (optional).'

#basicsSelector
'Selector under which the generated menu spec is saved.'

#basicsSeparatorType
'List of valid separators.'

#basicsTranslateLabel
'Translate the label via the classes resource file (internationalization).'

#browseResource
'Search for methods with image resource.'

#detailsAccelerator
'Key to be pressed to select the menu item from the keyboard (accelerator key).'

#detailsAccessCharaterPosition
'Index of the access character position of the textual label (optional).'

#detailsAuxValue
'Some additional value - for arbitrary use by the program'

#detailsEnabled
'Aspect or binding providing a boolean value holder for the enable-state of the menu item.'

#detailsStartGroup
'Specify start of a right-aligned item group.'

#detailsVisibility
'Aspect or binding providing a boolean value holder for the visibility-state of the menu item.'

#fileLoad
'Open a dialog to select and load a menu spec from a class.'

#fileNew
'Create a new menu spec.'

#filePickAMenu
'Select a menu from an open view and read its specification'

#fileSave
'Save the menu spec (and the help spec, if modified).'

#fileSaveAs
'Open a dialog to save the menu spec (and the help spec, if modified).'

#hideMenuOnActivated
'If on, the menu hides itself after the item was activated.'

#imageImageAndLabel
'Toggle display of both image and textual label.'

#imageImageEditor
'Open an Image Editor on the resource method defined by retriever and selector.'

#imageImageList
'Currently existing image resources.'

#imageRetriever
'Class implementing the image resource method. If no class is given, the current application class will be taken.'

#imageSelector
'Selector returning an image (sent to above or the application).'

#keepLinkedMenu
'Keep the linked menu after activation (do not destroy).'

#showBusyCursorWhilePerforming
'If on, a busy cursor is shown while the items action is performing.'

#triggerOnDown
'If on, the items action is performed on mouse-button press (default is on button-release).'

)
! !

!MenuEditor class methodsFor:'image specs'!

linkSubmenuImage
    "This resource specification was automatically generated
     by the ImageEditor of ST/X."

    "Do not manually edit this!!!! If it is corrupted,
     the ImageEditor may not be able to read the specification."

    "
     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') ; colorMapFromArray:#[0 0 0 255 255 255 170 170 170 255 0 0 0 255 0 0 0 255 0 255 255 255 255 0 255 0 255 127 0 0 0 127 0 0 0 127 0 127 127 127 127 0 127 0 127 127 127 127]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
!

menuItemImage
    "This resource specification was automatically generated
     by the ImageEditor of ST/X."

    "Do not manually edit this!!!! If it is corrupted,
     the ImageEditor may not be able to read the specification."

    "
     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') ; colorMapFromArray:#[0 0 0 255 255 255 170 170 170 127 127 127]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
!

menuSeparatorImage
    "This resource specification was automatically generated
     by the ImageEditor of ST/X."

    "Do not manually edit this!!!! If it is corrupted,
     the ImageEditor may not be able to read the specification."

    "
     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') ; colorMapFromArray:#[0 0 0 255 255 255 170 170 170 127 127 127]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
!

submenuImage
    "This resource specification was automatically generated
     by the ImageEditor of ST/X."

    "Do not manually edit this!!!! If it is corrupted,
     the ImageEditor may not be able to read the specification."

    "
     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??????@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 170 170 170 127 127 127]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<???<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
! !

!MenuEditor class methodsFor:'interface specs'!

basicsItemSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #basicsItemSpec
        #window: 
       #(#WindowSpec
          #label: 'Basics Item'
          #name: 'Basics Item'
          #min: #(#Point 10 10)
          #max: #(#Point 1160 870)
          #bounds: #(#Rectangle 898 390 1173 751)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Name Key:'
              #name: 'nameKeyLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #activeHelpKey: #basicsKey
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'nameKeyField'
              #layout: #(#LayoutFrame 110 0 16 0 -5 1.0 38 0)
              #activeHelpKey: #basicsKey
              #tabable: true
              #model: #nameKey
              #group: #inputGroup1
              #type: #symbolOrNil
              #acceptOnLeave: false
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Label:'
              #name: 'labelLabel'
              #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
              #activeHelpKey: #basicsLabel
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'labelField'
              #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
              #activeHelpKey: #basicsLabel
              #tabable: true
              #model: #label
              #group: #inputGroup1
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Action:'
              #name: 'valueLabel'
              #layout: #(#AlignmentOrigin 107 0 85 0 1 0.5)
              #activeHelpKey: #basicsAction
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'valueField'
              #layout: #(#LayoutFrame 110 0 74 0 -5 1.0 96 0)
              #activeHelpKey: #basicsAction
              #tabable: true
              #model: #value
              #group: #inputGroup1
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Argument:'
              #name: 'argumentLabel'
              #layout: #(#AlignmentOrigin 107 0 110 0 1 0.5)
              #activeHelpKey: #basicsArgument
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'argumentField'
              #layout: #(#LayoutFrame 110 0 99 0 -5 1.0 121 0)
              #activeHelpKey: #basicsArgument
              #tabable: true
              #model: #argument
              #group: #inputGroup1
              #type: #smalltalkObject
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Indication:'
              #name: 'indicationLabel'
              #layout: #(#AlignmentOrigin 107 0 144 0 1 0.5)
              #activeHelpKey: #basicsIndication
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'indicationField'
              #layout: #(#LayoutFrame 110 0 133 0 -5 1.0 155 0)
              #activeHelpKey: #basicsIndication
              #enableChannel: #indicationEnabled
              #tabable: true
              #model: #indication
              #group: #inputGroup1
              #type: #symbolOrNil
              #immediateAccept: true
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Choice:'
              #name: 'choiceLabel'
              #layout: #(#AlignmentOrigin 107 0 169 0 1 0.5)
              #activeHelpKey: #basicsChoice
              #translateLabel: true
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'choiceField'
              #layout: #(#LayoutFrame 110 0 158 0 -5 1.0 180 0)
              #activeHelpKey: #basicsChoice
              #enableChannel: #choiceEnabled
              #tabable: true
              #model: #choice
              #group: #inputGroup1
              #type: #symbolOrNil
              #immediateAccept: true
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Value:'
              #name: 'choiceValueLabel'
              #layout: #(#AlignmentOrigin 107 0 194 0 1 0.5)
              #activeHelpKey: #basicsChoiceValue
              #translateLabel: true
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'choiceValueField'
              #layout: #(#LayoutFrame 110 0 183 0 -5 1.0 205 0)
              #activeHelpKey: #basicsChoiceValue
              #enableChannel: #choiceValueEnabled
              #tabable: true
              #model: #choiceValue
              #group: #inputGroup1
              #type: #smalltalkObject
              #acceptOnLeave: false
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: false
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#CheckBoxSpec
              #label: 'Translate Label'
              #name: 'translateLabelCheckBox'
              #layout: #(#Point 20 218)
              #activeHelpKey: #basicsTranslateLabel
              #tabable: true
              #model: #translateLabel
            )
           #(#CheckBoxSpec
              #label: 'Is Button'
              #name: 'isButtonCheckBox'
              #layout: #(#Point 20 243)
              #activeHelpKey: #basicsIsButton
              #tabable: true
              #model: #isButton
            )
           #(#CheckBoxSpec
              #label: 'Hide Menu after Activation'
              #name: 'hideMenuOnActivated'
              #layout: #(#Point 20 267)
              #activeHelpKey: #hideMenuOnActivated
              #tabable: true
              #model: #hideMenuOnActivated
            )
           #(#CheckBoxSpec
              #label: 'BusyCursor while Active'
              #name: 'showBusyCursorWhilePerforming'
              #layout: #(#Point 20 291)
              #activeHelpKey: #showBusyCursorWhilePerforming
              #tabable: true
              #model: #showBusyCursorWhilePerforming
              #translateLabel: true
            )
           #(#CheckBoxSpec
              #label: 'Trigger On Down'
              #name: 'triggerOnDown'
              #layout: #(#Point 20 315)
              #activeHelpKey: #triggerOnDown
              #tabable: true
              #model: #triggerOnDown
              #translateLabel: true
            )
           )
         
        )
      )
!

basicsLinkSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #basicsLinkSpec
        #window: 
       #(#WindowSpec
          #label: 'Basics Link'
          #name: 'Basics Link'
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 900 124 1167 443)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Name Key:'
              #name: 'nameKeyLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #activeHelpKey: #nameKey
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'nameKeyField'
              #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #basicsNameKey
              #tabable: true
              #model: #nameKey
              #group: #inputGroup2
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Label:'
              #name: 'labelLabel'
              #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #name: 'labelField'
              #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
              #activeHelpKey: #basicsLabel
              #tabable: true
              #model: #label
              #group: #inputGroup2
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Menu:'
              #name: 'menuLabel'
              #layout: #(#AlignmentOrigin 107 0 76 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #name: 'menuField'
              #layout: #(#LayoutFrame 110 0 65 0 -5 1.0 87 0)
              #activeHelpKey: #basicsMenu
              #tabable: true
              #model: #submenuChannel
              #group: #inputGroup2
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Argument:'
              #name: 'ArgumentLabel'
              #layout: #(#AlignmentOrigin 107 0 100 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #name: 'argumentField'
              #layout: #(#LayoutFrame 110 0 90 0 -5 1.0 112 0)
              #activeHelpKey: #basicsMenuArgument
              #tabable: true
              #model: #argument
              #group: #inputGroup2
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#CheckBoxSpec
              #label: 'Translate Label'
              #name: 'translateLabelCheckBox'
              #layout: #(#Point 20 190)
              #activeHelpKey: #basicsTranslateLabel
              #tabable: true
              #model: #translateLabel
            )
           #(#CheckBoxSpec
              #label: 'Do not destroy linked Menu'
              #name: 'keepLinkedMenu'
              #layout: #(#Point 20 217)
              #tabable: true
              #activeHelpKey: #keepLinkedMenu
              #model: #keepLinkedMenu
              #translateLabel: true
            )
           )
         
        )
      )
!

basicsMenuSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #basicsMenuSpec
        #window: 
       #(#WindowSpec
          #label: 'Basics Menu'
          #name: 'Basics Menu'
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 93 223 360 542)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Name Key:'
              #name: 'nameKeyLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'nameKeyField'
              #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #basicsNameKey
              #tabable: true
              #model: #nameKey
              #group: #inputGroup3
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Label:'
              #name: 'labelLabel'
              #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'labelField'
              #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
              #activeHelpKey: #basicsLabel
              #tabable: true
              #model: #label
              #group: #inputGroup3
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#CheckBoxSpec
              #label: 'Translate Label'
              #name: 'translateLabelCheckBox'
              #layout: #(#Point 20 190)
              #activeHelpKey: #basicsTranslateLabel
              #tabable: true
              #model: #translateLabel
            )
           )
         
        )
      )
!

basicsRootSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #basicsRootSpec
        #window: 
       #(#WindowSpec
          #label: 'Basics Root'
          #name: 'Basics Root'
          #layout: #(#LayoutFrame 11 0 100 0 277 0 418 0)
          #level: 0
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 11 100 278 419)
          #usePreferredExtent: false
          #returnIsOKInDialog: true
          #escapeIsCancelInDialog: true
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Selector:'
              #name: 'selectorLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
              #activeHelpKey: #basicsSelector
            )
           #(#InputFieldSpec
              #name: 'selectorField'
              #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #basicsSelector
              #tabable: true
              #model: #label
              #group: #inputGroup
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           )
         
        )
      )
!

basicsSeparatorSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #basicsSeparatorSpec
        #window: 
       #(#WindowSpec
          #label: 'Basics Separator'
          #name: 'Basics Separator'
          #layout: #(#LayoutFrame 9 0 149 0 275 0 467 0)
          #level: 0
          #min: #(#Point 10 10)
          #max: #(#Point 1160 870)
          #bounds: #(#Rectangle 9 149 276 468)
          #usePreferredExtent: false
          #returnIsOKInDialog: true
          #escapeIsCancelInDialog: true
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Separator Type:'
              #name: 'separatorLabel'
              #layout: #(#AlignmentOrigin 127 0 26 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#ComboListSpec
              #name: 'seperatorList'
              #layout: #(#LayoutFrame 132 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #basicsSeparatorType
              #tabable: true
              #model: #seperatorSelection
              #useIndex: true
            )
           #(#LabelSpec
              #label: 'Visibility:'
              #name: 'visibilityLabel'
              #layout: #(#AlignmentOrigin 127 0 76 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'visibilityInputField'
              #layout: #(#LayoutFrame 132 0 65 0 -5 1.0 87 0)
              #activeHelpKey: #detailsVisibility
              #tabable: true
              #model: #isVisible
              #group: #inputGroup
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           )
         
        )
      )
!

detailsEditSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #detailsEditSpec
        #window: 
       #(#WindowSpec
          #label: 'Details Edit'
          #name: 'Details Edit'
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 12 22 327 306)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Accelerator:'
              #name: 'shortcutKeyLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #activeHelpKey: #detailsAccelerator
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'shortcutKeyField'
              #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #detailsAccelerator
              #tabable: true
              #model: #shortcutKey
              #group: #inputGroup4
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Enabled:'
              #name: 'enabledLabel'
              #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
              #activeHelpKey: #detailsEnabled
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'enabledField'
              #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
              #activeHelpKey: #detailsEnabled
              #tabable: true
              #model: #enabled
              #group: #inputGroup4
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Visibility:'
              #name: 'visibilityLabel'
              #layout: #(#AlignmentOrigin 107 0 76 0 1 0.5)
              #activeHelpKey: #detailsVisibility
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'isVisibleInputField'
              #layout: #(#LayoutFrame 110 0 65 0 -5 1.0 87 0)
              #activeHelpKey: #detailsVisibility
              #tabable: true
              #model: #isVisible
              #group: #inputGroup4
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Aux Value'
              #name: 'auxLabel'
              #layout: #(#AlignmentOrigin 107 0 101 0 1 0.5)
              #activeHelpKey: #detailsAuxValue
              #translateLabel: true
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'auxInputField'
              #layout: #(#LayoutFrame 110 0 90 0 -5 1.0 112 0)
              #activeHelpKey: #detailsAuxValue
              #tabable: true
              #model: #auxValue
              #group: #inputGroup4
              #type: #smalltalkObject
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Start Group:'
              #name: 'StartGroupLabel'
              #layout: #(#AlignmentOrigin 107 0 139 0 1 0.5)
              #activeHelpKey: #detailsStartGroup
              #resizeForLabel: true
              #adjust: #right
            )
           #(#PopUpListSpec
              #label: 'PopUpList'
              #name: 'StartGroupPopUp'
              #layout: #(#LayoutFrame 110 0 128 0 -5 1.0 150 0)
              #activeHelpKey: #detailsStartGroup
              #tabable: true
              #model: #startGroup
              #menu: 
             #(nil
                #right
              )
              #useIndex: false
            )
           #(#LabelSpec
              #label: 'Access Character Position:'
              #name: 'accessCharLabel'
              #layout: #(#AlignmentOrigin 217 0 170 0 1 0.5)
              #activeHelpKey: #detailsAccessCharaterPosition
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'accessCharField'
              #layout: #(#LayoutFrame 220 0 159 0 -5 1.0 181 0)
              #activeHelpKey: #detailsAccessCharaterPosition
              #tabable: true
              #model: #accessCharacterPos
              #group: #inputGroup4
              #type: #numberOrNil
              #immediateAccept: false
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Font:'
              #name: 'fontLabel'
              #layout: #(#AlignmentOrigin 75 0 231 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#FontMenuSpec
              #attributes: 
             #(#tabable
                true
              )
              #name: 'fontMenu'
              #layout: #(#LayoutFrame 78 0 220 0 -5 1.0 242 0)
              #activeHelpKey: #fontMenu
              #model: #font
            )
           )
         
        )
      )
!

imageEditSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #imageEditSpec
        #window: 
       #(#WindowSpec
          #label: 'Image Item'
          #name: 'Image Item'
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 12 22 300 317)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Retriever:'
              #name: 'retrieverLabel'
              #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
              #activeHelpKey: #imageRetriever
              #resizeForLabel: true
              #adjust: #right
            )
           #(#ComboBoxSpec
              #name: 'retrieverField'
              #layout: #(#LayoutFrame 110 0 15 0 -20 1.0 37 0)
              #activeHelpKey: #imageRetriever
              #tabable: true
              #model: #retriever
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #acceptOnPointerLeave: false
              #comboList: #retrieverClassList
            )
           #(#LabelSpec
              #label: 'Selector:'
              #name: 'iconLabel'
              #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
              #activeHelpKey: #imageSelector
              #resizeForLabel: true
              #adjust: #right
            )
           #(#InputFieldSpec
              #name: 'iconField'
              #layout: #(#LayoutFrame 110 0 40 0 -42 1.0 62 0)
              #activeHelpKey: #imageSelector
              #tabable: true
              #model: #icon
              #group: #inputGroup5
              #type: #symbolOrNil
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#ActionButtonSpec
              #label: '...'
              #name: 'browseButton'
              #layout: #(#LayoutFrame -40 1 40 0 -20 1 62 0)
              #activeHelpKey: #browseResource
              #tabable: true
              #model: #doBrowseForImageResource
            )
           #(#SelectionInListModelViewSpec
              #name: 'selectionOfImage'
              #layout: #(#LayoutFrame 20 0.0 67 0 -20 1.0 -30 1.0)
              #activeHelpKey: #imageImageList
              #tabable: true
              #model: #selectionOfImage
              #menu: #menuEditImage
              #hasHorizontalScrollBar: true
              #hasVerticalScrollBar: true
              #miniScrollerHorizontal: true
              #listModel: #listOfImages
              #useIndex: false
              #highlightMode: #line
              #doubleClickSelector: #doEditImage
              #valueChangeSelector: #imageSelected
            )
           #(#ViewSpec
              #name: 'Box1'
              #layout: #(#LayoutFrame 20 0.0 -30 1.0 -20 1.0 0 1.0)
              #level: 0
              #component: 
             #(#SpecCollection
                #collection: #(
                 #(#CheckBoxSpec
                    #label: 'Image & Label'
                    #name: 'iconAndLabelCheckBox'
                    #layout: #(#AlignmentOrigin 0 0 0 0.5 0 0.5)
                    #activeHelpKey: #imageImageAndLabel
                    #tabable: true
                    #model: #iconAndLabel
                  )
                 #(#ActionButtonSpec
                    #label: 'Image Editor'
                    #name: 'imageEditorButton'
                    #layout: #(#AlignmentOrigin 0 1.0 0 0.5 1 0.5)
                    #activeHelpKey: #imageImageEditor
                    #tabable: true
                    #model: #doEditImage
                  )
                 )
               
              )
            )
           )
         
        )
      )
!

windowSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #windowSpec
        #window: 
       #(#WindowSpec
          #label: 'Menu Editor'
          #name: 'Menu Editor'
          #min: #(#Point 550 440)
          #max: #(#Point 1152 900)
          #bounds: #(#Rectangle 61 493 618 974)
          #menu: #menu
          #returnIsOKInDialog: false
          #escapeIsCancelInDialog: false
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#MenuPanelSpec
              #name: 'menuToolbarView'
              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
              #tabable: true
              #menu: #menuToolbar
              #showSeparatingLines: true
            )
           #(#VariableHorizontalPanelSpec
              #name: 'VariableHorizontalPanel'
              #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
              #component: 
             #(#SpecCollection
                #collection: #(
                 #(#ArbitraryComponentSpec
                    #name: 'TreeView'
                    #menu: #menuEdit
                    #hasHorizontalScrollBar: true
                    #hasVerticalScrollBar: true
                    #hasBorder: false
                    #component: #treeView
                  )
                 #(#ViewSpec
                    #name: 'Box'
                    #level: -1
                    #component: 
                   #(#SpecCollection
                      #collection: #(
                       #(#NoteBookViewSpec
                          #name: 'NoteBook'
                          #layout: #(#LayoutFrame 1 0.0 0 0.0 1 1.0 -30 1.0)
                          #enableChannel: #hasAnySingleSelection
                          #tabable: true
                          #model: #tabModel
                          #menu: #tabList
                          #useIndex: true
                          #canvas: #tabCanvasHolder
                          #keepCanvasAlive: true
                        )
                       #(#UISubSpecification
                          #name: 'SubSpecification'
                          #layout: #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
                          #majorKey: #ToolApplicationModel
                          #minorKey: #windowSpecForCommit
                        )
                       )
                     
                    )
                  )
                 )
               
              )
              #handles: #(#Any 0.346499 1.0)
            )
           #(#UISubSpecification
              #name: 'InfoBarSubSpec'
              #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
              #majorKey: #ToolApplicationModel
              #minorKey: #windowSpecForInfoBar
            )
           )
         
        )
      )
! !

!MenuEditor class methodsFor:'menu specs'!

menu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: '&File'
                #activeHelpKey: #file
                #translateLabel: true
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'New'
                          #value: #doNew
                          #translateLabel: true
                          #activeHelpKey: #fileNew
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Load...'
                          #translateLabel: true
                          #value: #doLoad
                          #activeHelpKey: #fileLoad
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Save'
                          #translateLabel: true
                          #value: #doSave
                          #activeHelpKey: #fileSave
                      )
                       #(#MenuItem
                          #label: 'Save As...'
                          #translateLabel: true
                          #value: #doSaveAs
                          #activeHelpKey: #fileSaveAs
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Pick A Menu...'
                          #translateLabel: true
                          #value: #doPickAMenu
                          #activeHelpKey: #filePickAMenu
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Browse Class'
                          #translateLabel: true
                          #value: #doBrowseClass
                          #activeHelpKey: #fileBrowseClass
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Exit'
                          #translateLabel: true
                          #value: #closeRequest
                          #activeHelpKey: #fileExit
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Edit'
                #activeHelpKey: #edit
                #translateLabel: true
                #submenuChannel: #menuEdit
            )
             #(#MenuItem
                #label: 'Add'
                #activeHelpKey: #add
                #translateLabel: true
                #submenuChannel: #menuAdd
            )
             #(#MenuItem
                #label: 'Test'
                #activeHelpKey: #test
                #translateLabel: true
                #submenuChannel: #submenuTest
            )
"/             #(#MenuItem
"/                #label: 'Settings'
"/                #submenu: 
"/                 #(#Menu
"/                    
"/                     #(
"/                       #(#MenuItem
"/                          #label: 'Fonts'
"/                          #translateLabel: true
"/                          #submenuChannel: #menuFont
"/                      )
"/                    ) nil
"/                    nil
"/                )
"/            )
             #(#MenuItem
                #label: 'History'
                #activeHelpKey: #history
                #translateLabel: true
                #submenuChannel: #menuHistory
            )
             #(#MenuItem
                #label: 'Help'
                #translateLabel: true
                #startGroup: #right
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Documentation'
                          #value: #openHTMLDocument:
                          #translateLabel: true
                          #activeHelpKey: #helpTutorial
                          #argument: 'tools/uipainter/MenuEditor.html'
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Help Tool'
                          #value: #openHTMLDocument:
                          #translateLabel: true
                          #activeHelpKey: #helpHelpTool
                          #argument: 'tools/uipainter/HelpTool.html'
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Show Help Texts'
                          #translateLabel: true
                          #activeHelpKey: #helpShowHelp
                          #indication: #showingHelp:
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'About MenuEditor...'
                          #translateLabel: true
                          #value: #openAboutThisApplication
                          #activeHelpKey: #aboutThisAppliaction
                      )

                    ) nil
                    nil
                )
            )
          ) nil
          nil
      )

    "Modified: / 31.7.1998 / 18:19:47 / cg"
!

menuAdd
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Menu Item'
                #translateLabel: true
                #value: #doCreateItem
                #activeHelpKey: #addMenuItem
                #labelImage: #(#ResourceRetriever #MenuEditor #menuItemImage 'Menu Item')
            )
             #(#MenuItem
                #label: 'Menu Separator'
                #translateLabel: true
                #value: #doCreateSep
                #activeHelpKey: #addMenuSeparator
                #labelImage: #(#ResourceRetriever #MenuEditor #menuSeparatorImage 'Menu Separator')
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Submenu'
                #translateLabel: true
                #value: #doCreateMenu
                #activeHelpKey: #addSubMenu
                #labelImage: #(#ResourceRetriever #MenuEditor #submenuImage 'Submenu')
            )
             #(#MenuItem
                #label: 'Submenu Link'
                #translateLabel: true
                #value: #doCreateLink
                #activeHelpKey: #addSubMenuLink
                #labelImage: #(#ResourceRetriever #MenuEditor #linkSubmenuImage 'Submenu Link')
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Standard Submenu'
                #translateLabel: true
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Standard Menu: File'
                          #translateLabel: true
                          #value: #doCreateStandardFileMenu
                      )
                       #(#MenuItem
                          #label: 'Standard Menu: Edit'
                          #translateLabel: true
                          #value: #doCreateStandardEditMenu
                      )
                       #(#MenuItem
                          #label: 'Standard Menu: Help'
                          #translateLabel: true
                          #value: #doCreateStandardHelpMenu
                      )
                    ) nil
                    nil
                )
            )
          ) nil
          nil
      )

    "Modified: / 23.8.1998 / 15:48:21 / cg"
!

menuDefaultLink
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^

       #(#Menu

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

menuEdit
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Cut'
                #translateLabel: true
                #value: #doCut
                #activeHelpKey: #editCut
                #enabled: #hasValidSelection
            )
             #(#MenuItem
                #label: 'Copy'
                #translateLabel: true
                #value: #doCopy
                #activeHelpKey: #editCopy
                #enabled: #hasValidSelection
            )
             #(#MenuItem
                #label: 'Paste'
                #translateLabel: true
                #value: #doPaste
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPaste
            )
             #(#MenuItem
                #label: 'Delete'
                #translateLabel: true
                #value: #doDelete
                #activeHelpKey: #editDelete
                #enabled: #hasValidSelection
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Move Up'
                #translateLabel: true
                #value: #doStepUp
                #activeHelpKey: #editMoveUp
                #enabled: #valueOfEnableMovingUpOrDown
                #labelImage: #(#ResourceRetriever #Icon #upIcon 'Move Up')
            )
             #(#MenuItem
                #label: 'Move Down'
                #translateLabel: true
                #value: #doStepDown
                #activeHelpKey: #editMoveDown
                #enabled: #valueOfEnableMovingUpOrDown
                #labelImage: #(#ResourceRetriever #Icon #downIcon 'Move Down')
            )
             #(#MenuItem
                #label: 'Move In'
                #translateLabel: true
                #value: #doStepIn
                #activeHelpKey: #editMoveIn
                #enabled: #valueOfEnableMovingIn
                #labelImage: #(#ResourceRetriever #Icon #downRightIcon 'Move In')
            )
             #(#MenuItem
                #label: 'Move Out'
                #translateLabel: true
                #value: #doStepOut
                #activeHelpKey: #editMoveOut
                #enabled: #valueOfEnableMovingOut
                #labelImage: #(#ResourceRetriever #Icon #leftDownIcon 'Move Out')
            )
          ) nil
          nil
      )
!

menuEditImage
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Edit'
                #translateLabel: true
                #value: #doEditImage
                #activeHelpKey: #editCut
                #enabled: #hasValidSelection
            )
             #(#MenuItem
                #label: 'Remove'
                #translateLabel: true
                #value: #doRemoveImage
                #activeHelpKey: #editCopy
                #enabled: #hasValidSelection
            )
          ) nil
          nil
      )
!

menuToolbar
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."

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

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'New'
            #isButton: true
            #value: #doNew
            #activeHelpKey: #fileNew
            #labelImage: #(#ResourceRetriever #Icon #newIcon)
          )
         #(#MenuItem
            #label: 'Load'
            #isButton: true
            #value: #doLoad
            #activeHelpKey: #fileLoad
            #labelImage: #(#ResourceRetriever #Icon #loadIcon)
          )
         #(#MenuItem
            #label: 'Save'
            #isButton: true
            #value: #doSave
            #activeHelpKey: #fileSave
            #labelImage: #(#ResourceRetriever #Icon #saveIcon)
          )
         #(#MenuItem
            #label: ''
          )
         #(#MenuItem
            #label: 'Cut'
            #isButton: true
            #value: #doCut
            #activeHelpKey: #editCut
            #enabled: #hasValidSelection
            #labelImage: #(#ResourceRetriever #Icon #cutIcon)
          )
         #(#MenuItem
            #label: 'Copy'
            #isButton: true
            #value: #doCopy
            #activeHelpKey: #editCopy
            #enabled: #hasValidSelection
            #labelImage: #(#ResourceRetriever #Icon #copyIcon)
          )
         #(#MenuItem
            #label: 'Paste'
            #isButton: true
            #value: #doPaste
            #activeHelpKey: #editPaste
            #enabled: #valueOfCanPaste
            #labelImage: #(#ResourceRetriever #Icon #pasteIcon)
          )
         #(#MenuItem
            #label: 'Delete'
            #isButton: true
            #value: #doDelete
            #activeHelpKey: #editDelete
            #enabled: #hasValidSelection
            #labelImage: #(#ResourceRetriever #Icon #deleteIcon)
          )
         #(#MenuItem
            #label: ''
          )
         #(#MenuItem
            #label: 'Add Item'
            #isButton: true
            #value: #doCreateItem
            #activeHelpKey: #addMenuItem
            #enabled: #hasAnySingleSelection
            #labelImage: #(#ResourceRetriever nil #menuItemImage)
          )
         #(#MenuItem
            #label: 'Add Separator'
            #isButton: true
            #value: #doCreateSep
            #activeHelpKey: #addMenuSeparator
            #enabled: #hasAnySingleSelection
            #labelImage: #(#ResourceRetriever nil #menuSeparatorImage)
          )
         #(#MenuItem
            #label: 'Add Submenu'
            #isButton: true
            #value: #doCreateMenu
            #activeHelpKey: #addSubMenu
            #enabled: #hasAnySingleSelection
            #labelImage: #(#ResourceRetriever nil #submenuImage)
          )
         #(#MenuItem
            #label: 'Add Linked Submenu'
            #isButton: true
            #value: #doCreateLink
            #activeHelpKey: #addSubMenuLink
            #enabled: #hasAnySingleSelection
            #labelImage: #(#ResourceRetriever nil #linkSubmenuImage)
          )
         #(#MenuItem
            #label: ''
          )
         #(#MenuItem
            #label: 'Move Up'
            #isButton: true
            #value: #doStepUp
            #activeHelpKey: #editMoveUp
            #enabled: #valueOfEnableMovingUpOrDown
            #labelImage: #(#ResourceRetriever #Icon #upIcon)
          )
         #(#MenuItem
            #label: 'Move Down'
            #isButton: true
            #value: #doStepDown
            #activeHelpKey: #editMoveDown
            #enabled: #valueOfEnableMovingUpOrDown
            #labelImage: #(#ResourceRetriever #Icon #downIcon)
          )
         #(#MenuItem
            #label: 'Move In'
            #isButton: true
            #value: #doStepIn
            #activeHelpKey: #editMoveIn
            #enabled: #valueOfEnableMovingIn
            #labelImage: #(#ResourceRetriever #Icon #downRightIcon)
          )
         #(#MenuItem
            #label: 'Move In Above'
            #isButton: true
            #value: #doStepInAbove
            #activeHelpKey: #editMoveInAbove
            #enabled: #valueOfEnableMovingInAbove
            #labelImage: #(#ResourceRetriever #Icon #upRightIcon)
          )
         #(#MenuItem
            #label: 'Move Out'
            #isButton: true
            #value: #doStepOut
            #activeHelpKey: #editMoveOut
            #enabled: #valueOfEnableMovingOut
            #labelImage: #(#ResourceRetriever #Icon #leftDownIcon)
          )
         )
        nil
        nil
      )
! !

!MenuEditor class methodsFor:'queries'!

getAllImageSelectorsFrom: aClass
    "returns all image selectors implementing an image spec in class aClass"

     |iconClass imageMethodSelectors r|

     aClass isNil ifTrue:[
        ^ #()
     ].

     aClass isSymbol 
        ifTrue:  [iconClass := Smalltalk at: aClass]
        ifFalse: [iconClass := aClass].
     aClass isBehavior ifFalse:[
        ^ #()
     ].

     imageMethodSelectors := OrderedCollection new.

     iconClass withAllSuperclassesDo:[:cls |
        cls class selectorsAndMethodsDo:[:sel :m | 
            ((r := m resourceType) == #image
            or:[r == #programImage]) ifTrue:[
                imageMethodSelectors add:sel
            ]
        ]
     ].

     ^ imageMethodSelectors sort

    "Modified: / 24.8.1998 / 21:42:34 / cg"
    "Created: / 24.8.1998 / 21:53:20 / cg"
! !

!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'!

submenuTest
    "return the submenu assigned to item test;
     this is dynamically constructed, to reflect the current
     edited menu."

    |menu cls|

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

        cls := self resolveName:specClass.
        menu findGuiResourcesIn:cls.
    ].
    ^ menu
!

useHelpTool: aHelpTool
    "take the help dictionaries from aHelpTool into my helpTool"

    self helpTool buildFromClass: aHelpTool specClass.
    self helpTool dictionaries:   aHelpTool dictionaries.
    self helpTool dictionary:     aHelpTool dictionary


! !

!MenuEditor methodsFor:'aspects'!

hasAnySingleSelection

    ^builder booleanValueAspectFor: #hasAnySingleSelection
!

hasValidSelection

    ^builder booleanValueAspectFor: #hasValidSelection
!

listOfImages
    "get a list of the images
    "
    |list|

    (list := builder bindingAt:#listOfImages) isNil ifTrue:[
        builder aspectAt:#listOfImages put: (list := List new).
    ].
    ^ list


!

selectionOfImage
    "get selection of list of the images as value"

    |holder|
    (holder := builder bindingAt:#selectionOfImage) isNil ifTrue:[
        builder aspectAt:#selectionOfImage put: (holder := nil asValue).
    ].
    ^ holder


!

tabCanvasHolder
    "keep the canvas for the current selected item or nil
    "
    |holder|

    (holder := builder bindingAt:#tabCanvasHolder) isNil ifTrue:[
        builder aspectAt:#tabCanvasHolder put: (holder := ValueHolder new).
    ].
    ^ holder


!

tabList
    "get a value holder with the list of the attribute sections (slices)"

    |holder|

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


!

treeView
    "get a tree view representing hierarchically the menu items"

    ^ treeView
! !

!MenuEditor methodsFor:'building'!

buildFromClass:aClass andSelector:aSelector

    self isStandAlone ifTrue:[
        self helpTool buildFromClass:specClass
    ].              
    treeView buildFromClass: aClass andSelector: aSelector.

    self updateHistory.
    self updateInfoLabel.

!

buildFromResourceSpec:aResourceSpec
    |spec|

    spec := aResourceSpec isCollection ifTrue:[aResourceSpec decodeAsLiteralArray]
                                      ifFalse:[aResourceSpec].

    self buildFromMenu:spec  
! !

!MenuEditor methodsFor:'change & update'!

update:something with:aParameter from:changedObject
    super update:something with:aParameter from:changedObject.

    changedObject == (aspects at:#retriever) ifTrue:[
        self updateImageView.
    ].

    "Modified: / 24.8.1998 / 21:47:48 / cg"
!

updateChannels
    "update channels"

    |node parent next prev state canPaste selectedNodes firstParent
     enableMovingOut enableMovingIn indexOfLast|

    enableMovingOut := enableMovingIn := false.

    state := false.   
    node  := treeView selectedNode.

    node notNil ifTrue:[
        "/ single node selected
        self hasAnySingleSelection value:true.
        canPaste := self valueOfCanPaste value.

        (parent := node parent) notNil ifTrue:[
            next := parent childAt:((parent indexOfChild:node) + 1).
            prev := parent childAt:((parent indexOfChild:node) - 1).
            self valueOfEnableMovingIn       value:(next notNil and:[next hasChildren]).
            self valueOfEnableMovingInAbove  value:(prev notNil and:[prev hasChildren]).
            self valueOfEnableMovingUpOrDown value:(parent children size > 1).
            self valueOfEnableMovingOut      value:parent parent notNil.
            self hasValidSelection           value:true.  
            self valueOfCanPaste             value:canPaste. 
          ^ self
        ].
    ] ifFalse:[
        "/ multiple nodes selected
        canPaste := false.

        self hasAnySingleSelection value:false.

        treeView numberOfSelections ~~ 0 ifTrue:[
            canPaste := false.
            state    := (treeView isInSelection:1) not.

            selectedNodes := treeView selectedNodes.

            "/ see if all selected nodes have a common parent.
            firstParent := selectedNodes first parent.
            (selectedNodes conform:[:eachNode | eachNode parent == firstParent]) ifTrue:[
                "/ yes - they have
"/               next := firstParent childAt:((firstParent indexOfChild:node) + 1).
"/               self valueOfEnableMovingIn       value:(next notNil and:[next hasChildren]).
                enableMovingOut := firstParent parent notNil.
"/ self halt.

                indexOfLast := (selectedNodes collect:[:eachNode | firstParent indexOfChild:eachNode]) max.
                next := firstParent childAt:(indexOfLast + 1).
                enableMovingIn := (next notNil and:[next hasChildren]).
            ] ifFalse:[
"/ self halt.
            ].
        ]
    ].          
    self valueOfEnableMovingUpOrDown value:false.
    self valueOfEnableMovingIn       value:enableMovingIn.
    self valueOfEnableMovingOut      value:enableMovingOut.
    self hasValidSelection           value:state.     
    self valueOfCanPaste             value:canPaste. 
!

updateImageView
    "update the image view
    "
    |cls newList icon|

    self isImageViewSelected ifFalse:[
        ^ self
    ].
    cls := self currentImageRetrieverClass.

    lastImageRetriever == cls ifTrue:[
        newList := self listOfImages
    ] ifFalse:[
        cls notNil ifTrue:[
            self withWaitCursorDo:[
                lastImageRetriever := cls.

                newList := self class getAllImageSelectorsFrom:cls.
                newList := newList collect: [:sel| |img| 
                                img := cls perform: sel. 
                                img height > 32 ifTrue:[
                                    img := img magnifiedBy: 32 / img extent y
                                ].
                                LabelAndIcon icon:img string:sel
                           ].
                ].
        ] ifFalse:[
            newList := #()
        ].
        self listOfImages contents:newList.
    ].

    icon := (aspects at:#icon) value.

    icon notNil ifTrue:[
        icon := newList detect:[:el| el string == icon] ifNone:nil.
    ].
    self selectionOfImage value:icon.
! !

!MenuEditor methodsFor:'defaults'!

aboutImage
    "the image to be displayed in my about-box;
     If nil is returned, thhe ST/X default image is used."

    ^ Image fromFile:'bitmaps/xpmBitmaps/misc_tools/setup_menus.xpm'

    "Created: / 25.7.1998 / 20:48:12 / cg"
    "Modified: / 27.7.1998 / 10:21:55 / cg"
! !

!MenuEditor methodsFor:'event handling'!

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

    ^ aMessage sendTo:treeView
! !

!MenuEditor methodsFor:'private'!

currentImageRetrieverClass
    "returns the current class which provides the images dependent on
     the retriver or the current spec.
    "
    |clsName|

    clsName := (aspects at: #retriever) value.

    clsName size == 0 ifTrue:[
        clsName := specClass.
        clsName isNil ifTrue:[^ nil].
    ].
    ^ Smalltalk at:clsName ifAbsent:nil
!

helpKey
    "get the help key of the selected menu item"

    |node|

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

helpTool
    "get the help tool application
    "
    |helpView helpTool|

    helpTool := listOfCanvas at:#help ifAbsent:nil.

    helpTool isNil ifTrue:[
        helpTool := UIHelpTool new createBuilder.
        helpTool masterApplication:self.
        helpTool modifiedHolder: self valueOfEnablingCommitButtons.
        helpView := ApplicationSubView new client:helpTool.
        helpTool builder window:helpView.
        helpTool masterApplication:self.
        listOfCanvas at:#help put:helpTool.
    ].
    ^ helpTool


! !

!MenuEditor methodsFor:'queries'!

isHelpToolSelected
    "return true if current selection is help tool
    "
    ^ typeOfCanvas == #help

!

isImageViewSelected
    "return true if current selection is help tool
    "
    ^ typeOfCanvas == #imageEditSpec

!

preferredExtent

    ^super preferredExtent max: (Screen current width//3)@(Screen current height//2.5)


! !

!MenuEditor methodsFor:'selection'!

imageSelected
    |imgSel|

    imgSel := self selectionOfImage value.
    imgSel notNil ifTrue:[
        (aspects at: #icon) value: imgSel string
    ]
!

menuChanged

    |node item myClass oldLabel oldSlices newList index|

    node := treeView selectedNode.

    node isNil ifTrue:[
        slices := nil.
        index  := 0.
    ] ifFalse:[
        oldSlices := slices.
        myClass   := self class.
        item      := node contents.

        item isSeparator ifFalse:[
            node parent isNil ifFalse:[
                node hasChildren ifTrue:[
                    slices := #slicesMenu
                ] ifFalse:[
                    item submenuChannel isNil ifTrue:[slices := #slicesItem]
                                             ifFalse:[slices := #slicesLink]
                ].
                slices := listOfSlices at:slices
                              ifAbsentPut:[(myClass perform:slices) copyWith:#('Help' #help)].
            ] ifTrue:[
                slices := listOfSlices at:#slicesRootMenu
                              ifAbsentPut:[myClass perform:#slicesRootMenu].
            ].
        ] ifTrue:[
            slices := myClass perform:#slicesSeparatorMenu.
        ].
        index := tabSelection ? 0.

        slices ~~ oldSlices ifTrue:[
            tabSelection := 0.
            typeOfCanvas := 0.

            self tabCanvasHolder value:nil.

            newList := slices collect:[:el| el first].

            index ~~ 0 ifTrue:[
                oldLabel := self tabList value at:index ifAbsent:nil.

                oldLabel notNil ifTrue:[
                    index := newList indexOf:oldLabel.
                ]
            ].
            self tabList value:newList.
        ].
        index := index max:1.
    ].
    self tabModel value:index.
    aspects do:[:a| a removeDependent:self].
    self cancel.
    self updateChannels.
    aspects do:[:a| a addDependent:self].

!

tabSelection:aSelection
    "put the section aSelection into the note book
    "
    |view|

    aSelection = tabSelection ifTrue:[^self].

    (tabSelection := aSelection) isNil ifTrue:[
        tabSelection == 0 ifTrue:[^ self].
        tabSelection := 0.
    ].

    "/ before bringing up the new notebook page,
    "/ we must disable all now invisible input fields ...
    "/ (otherwise, those would fire on #accept.

    (view := self tabCanvasHolder value) notNil ifTrue:[
        view allSubViewsDo:[:aComponent |
            aComponent isInputField ifTrue:[
                aComponent disableIfInvisible:true
            ]
        ]
    ].

    tabSelection == 0 ifTrue:[
        ^ self tabCanvasHolder value:nil.
    ].

    typeOfCanvas := (slices at:tabSelection) last.

    self isHelpToolSelected ifTrue:[
        view := self helpTool window.
    ] ifFalse:[
        self updateImageView.

        view := listOfCanvas at:typeOfCanvas
                    ifAbsentPut:[SimpleView new client:self spec:typeOfCanvas builder:(self builder)].
    ].
    self tabCanvasHolder value:view.

! !

!MenuEditor methodsFor:'startup / release'!

initialize
    "initialize value holders for the attributes of the menu components"

    |holder|

    super initialize.

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

    listOfCanvas := IdentityDictionary new.
    listOfSlices := IdentityDictionary new.

    treeView := TreeView new.
    treeView action:[:dummy| self menuChanged ].

    aspects at:#indicationEnabled  put:(BlockValue 
                                            with:[:a | a size == 0]
                                            argument:(aspects at:#choice)).
    aspects at:#choiceEnabled      put:(BlockValue
                                            with:[:a | a size == 0]
                                            argument:(aspects at:#indication)).
    aspects at:#choiceValueEnabled put:(BlockValue
                                            with:[:a | a size > 0]
                                            argument:(aspects at:#choice)).

    aspects at:#retrieverClassList put:self class imageRetrieverClasses asValue.

    aspects do: [:holder| holder addDependent:self].
!

openModalOnMenu: aMenu
    "build a tree from aMenu and open it modal"

    super openModalOnResourceSpec: aMenu
!

postOpenWith:aBuilder
    "reset keyboardProcessor for menuBar
    "
    super postOpenWith: aBuilder.
    aBuilder keyboardProcessor menuBar:nil.
! !

!MenuEditor methodsFor:'user actions'!

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

    |node item|

    super accept.

    (node := treeView selectedNode) notNil ifTrue:[
        item := node contents.

        self isHelpToolSelected ifTrue:[
            self helpTool accept.
            item activeHelpKey: self helpTool helpKey.
            self valueOfEnablingCommitButtons value: false.
            self clearModifiedFlag.
        ] ifFalse:[
            item buildFromAspects:aspects.
            node changed.
            specSelector := treeView selectorName.
        ]
    ].   
    self updateInfoLabel.

!

cancel
    "invoked by button 'Cancel'"
    |node item|

    node := treeView selectedNode.

    aspects keysAndValuesDo:[:aKey :anAspect|
        aKey ~~ #retrieverClassList ifTrue:[
            anAspect setValue:''.  "/ to clear the field.
            anAspect value:''
        ]
    ].

    node notNil ifTrue:[
        item := node contents.
        item toAspects:aspects.
        self helpTool helpKey:(item activeHelpKey).
    ].
    self updateImageView.
    self valueOfEnablingCommitButtons value:false.
    self clearModifiedFlag.
!

doBrowseForImageResource
    "opens a browser on image-resource methods"

    |msg currClass w cls sel|

    currClass := self currentImageRetrieverClass.
    msg := 
        (ResourceSelectionBrowser
            request: 'Use Image From Class'
            onSuperclass: nil
            andClass: currClass
            andSelector: (aspects at: #icon)
            withResourceTypes: #(image fileImage programImage)).

    msg notNil ifTrue:[
        (w := msg asCollectionOfWords) size == 2 ifTrue:[
            cls := w at:1.
            sel := w at:2.
            cls ~= currClass ifTrue:[
                (aspects at: #retriever) value:cls asSymbol.
            ].
            sel ~= (aspects at:#icon) ifTrue:[
                (aspects at: #icon) value:sel asSymbol.
            ].
            self updateImageView.
        ].
    ].


!

doEditImage
    "opens a Image Editor on the resource retriever and the icon selector;
     then updates the list of images and select the line of the image"

    super doEditImage.
    lastImageRetriever := nil.
    self updateImageView.
!

doNew

    super doNew ifTrue: [self helpTool doNew]
!

doPickAMenu

    |view|

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

doRemoveImage
    "removes the image of the selected line"
    |cls sel|

    sel := self selectionOfImage value.

    sel size ~~ 0 ifTrue:[
        cls := self currentImageRetrieverClass.
        cls notNil ifTrue:[
            cls class removeSelector:(sel string)
        ].
        (aspects at:#icon) value:nil.
        lastImageRetriever := nil.
        self updateImageView.
    ] 
!

doSave
    |cls menu spec mthd category code excla|

    super doSave ifFalse: [^nil].

    cls  := self resolveName: specClass.
    menu := treeView asMenu 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 := 'menu specs'.
    (mthd := cls class compiledMethodAt:specSelector) notNil ifTrue:[
        category := mthd category.
    ].

    excla := Character excla asString.

    code := excla
            , (cls name , ' class methodsFor:' , category storeString)
            , excla , '\\'

            , specSelector , '\'
            , (self class codeGenerationComment replChar:$!! withString:'!!!!')
            , '\\    "\'
            , ('     MenuEditor new openOnClass:' , cls name , ' andSelector:#' , specSelector , '\')
            , ('     (Menu new fromLiteralArrayEncoding:(' , cls name , ' ' , specSelector , ')) startUp\')
            , '    "\'.

    code := code 
            , '\'
            , '    <resource: #menu>\\'
            , '    ^ ' , spec 
            , '\'
            , (excla , ' ' , excla)
            , '\\'.

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

    self isStandAlone ifTrue: [self helpTool installHelpSpecsOnClass:self specClass].

    self updateHistory.
    self updateInfoLabel.

    hasSaved := true.
    modified := false.

!

doSaveAs

    super doSaveAs ifTrue: [treeView selectorName:specSelector]
!

doStepDown
    "shift selected menu item one step down"

    treeView selectedNodeChangeSequenceOrder:1.
    modified := true.




!

doStepIn
    "move selected menu item into next submenu"

    "/ treeView selectedNodeBecomeChildOfNext.
    treeView selectedNodesBecomeChildrenOfNext.
    modified := true.
!

doStepInAbove
    "move selected menu item into previous submenu"

    treeView selectedNodeBecomeChildOfPrevious.
    modified := true.
!

doStepOut
    "move selected menu item(s) out from parent submenu"

    treeView selectedNodesBecomeSistersOfParent.
    modified := true.
!

doStepUp
    "shift selected menu item one step up"

    treeView selectedNodeChangeSequenceOrder:-1.
    modified := true.
! !

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

separatorList
    "get the list of available separator types"

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

separatorSlices
    "get the list of menu spec values of the corresponding separator types"

   ^ #(
        ( #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
    "get the help key of the menu item"

    ^activeHelpKey
!

activeHelpKey:aKey
    "set the help key of the menu item"

    activeHelpKey := aKey
!

label
    "get the value of the menu item"

    ^label
!

label:something
    "set the value of the menu item"

    label := something ? '-'
!

separatorType
    "get the 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

!

startGroup:aSymbolOrNil
    "set the startGroup attribute"

    startGroup := aSymbolOrNil

    "Created: / 23.8.1998 / 15:56:03 / cg"
!

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

    ^submenuChannel
!

submenuChannel:aChannel
    "get the submenuChannel"

    submenuChannel := aChannel
!

translateLabel:aBoolean
    "set/clear the translate to national-language flag"

    translateLabel := aBoolean

    "Created: / 6.6.1998 / 17:23:33 / cg"
!

value:aSymbol
    "set the value attribute"

    value := aSymbol

    "Created: / 23.8.1998 / 16:02:10 / cg"
! !

!MenuEditor::Item methodsFor:'building'!

buildFromAspects:aspects
    "read the values of the aspects into my values"

    |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.
        choice             := (aspects at:#choice) value.
        choiceValue        := (aspects at:#choiceValue) value.
        shortcutKey        := (aspects at:#shortcutKey) value.
        startGroup         := (aspects at:#startGroup) value.
        accessCharacterPos := (aspects at:#accessCharacterPos) value.
        showBusyCursorWhilePerforming := (aspects at:#showBusyCursorWhilePerforming) value.
        triggerOnDown      := (aspects at:#triggerOnDown) value.
        keepLinkedMenu     := (aspects at:#keepLinkedMenu) value ? false.
        font               := (aspects at:#font) value.
        argument           := (aspects at:#argument) value.
        translateLabel     := (aspects at:#translateLabel) value.
        isButton           := (aspects at:#isButton) value.
        auxValue           := (aspects at:#auxValue) 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.
    ].
    isVisible := (aspects at:#isVisible) value.
    hideMenuOnActivated := (aspects at:#hideMenuOnActivated) value.

    "Modified: / 14.8.1998 / 15:36:38 / cg"
!

buildFromMenuItem:anItem
    "read the attributes of anItem into my values"

    |rtv|

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

    (enabled := anItem enabled) isSymbol ifFalse:[
        enabled := nil
    ].
    (value := anItem value) isSymbol ifFalse:[
        value := nil.
    ].
    (indication := anItem indication) isSymbol ifFalse:[
        indication := nil
    ].
    (choice := anItem choice) isSymbol ifFalse:[
        choice := nil
    ].
    choiceValue         := anItem choiceValue.
    nameKey             := anItem nameKey.
    shortcutKey         := anItem shortcutKeyCharacter.
    startGroup          := anItem startGroup.
    accessCharacterPos  := anItem accessCharacterPosition.
    showBusyCursorWhilePerforming  := anItem showBusyCursorWhilePerforming.
    triggerOnDown       := anItem triggerOnDown.
    keepLinkedMenu      := anItem keepLinkedMenu.
    font                := anItem font.
    argument            := anItem argument.

    submenuChannel      := anItem submenuChannel.
    translateLabel      := anItem translateLabel.
    isButton            := anItem isButton.
    isVisible           := anItem isVisible.
    hideMenuOnActivated := anItem hideMenuOnActivated.
    auxValue            := anItem auxValue.

    (((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.
        ]
    ]

    "Modified: / 29.9.1998 / 11:18:25 / cg"
! !

!MenuEditor::Item methodsFor:'conversion'!

asMenuItem
    "converts self to a menu item"

    |item rcv|

    item := MenuItem labeled:label.
    item isVisible:isVisible.
    item hideMenuOnActivated:hideMenuOnActivated.

    self isSeparator ifFalse:[    
        item activeHelpKey:activeHelpKey.
        item enabled:enabled.
        item accessCharacterPosition:accessCharacterPos.
        item showBusyCursorWhilePerforming:showBusyCursorWhilePerforming.
        item triggerOnDown:triggerOnDown.
        item keepLinkedMenu:keepLinkedMenu.
        item font:font.
        item argument:argument.
        item submenuChannel:submenuChannel.
        item nameKey:nameKey.
        item shortcutKeyCharacter:shortcutKey.
        item startGroup:startGroup.
        item value:value.
        item indication:indication.
        item choice:choice.
        item choiceValue:choiceValue.
        item translateLabel: translateLabel.
        item isButton: isButton.
        item auxValue: auxValue.

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

    "Modified: / 14.8.1998 / 15:36:35 / cg"
!

toAspects:aspects
    "put my values into the values of 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:#choice)               value:choice.
        (aspects at:#choiceValue)          value:choiceValue.
        (aspects at:#shortcutKey)          value:shortcutKey.
        (aspects at:#startGroup)           value:startGroup.
        (aspects at:#accessCharacterPos)   value:accessCharacterPos.
        (aspects at:#showBusyCursorWhilePerforming)   value:showBusyCursorWhilePerforming.
        (aspects at:#triggerOnDown)        value:triggerOnDown.
        (aspects at:#keepLinkedMenu)       value:(keepLinkedMenu ? false).
        (aspects at:#font)                 value:font.
        (aspects at:#translateLabel)       value:translateLabel.
        (aspects at:#submenuChannel)       value:submenuChannel.
        (aspects at:#retriever)            value:retriever.
        (aspects at:#icon)                 value:icon.
        (aspects at:#iconAndLabel)         value:iconAndLabel.
        (aspects at:#isButton)             value:isButton.
        (aspects at:#auxValue)             value:auxValue.

        (aspects at:#argument)
            value:(argument isSymbol
                        ifTrue: ['#', argument] 
                        ifFalse:[argument]).
    ].
    (aspects at:#isVisible) value:isVisible.
    (aspects at:#hideMenuOnActivated) value:(hideMenuOnActivated ? true).

    "Modified: / 14.8.1998 / 15:37:29 / cg"
! !

!MenuEditor::Item methodsFor:'queries'!

iconFor: aNode
    "get the icon of the menu item for the tree view"

    (aNode hasChildren or: [aNode parent isNil])
    ifTrue:
    [
        ^MenuEditor submenuImage
    ]
    ifFalse:
    [
        submenuChannel notNil 
        ifTrue:
        [
            ^MenuEditor linkSubmenuImage
        ]
        ifFalse:
        [
            self isSeparator 
                ifTrue:  [^MenuEditor menuSeparatorImage]
                ifFalse: [^MenuEditor menuItemImage]
        ]
    ]
!

isSeparator
    "return true if item is a seperator"

    ^self separatorType notNil
!

treeViewLabel
    "get the label of the menu item for the tree view"

    ^label
" asBoldText, 
        (value notNil ifTrue: [': [', 
                value ,
                (argument isString ifTrue: [' ', (Text string: argument emphasis: #italic)] ifFalse: ['']),
                 ']'] ifFalse: [''])


"
! !

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

documentation
"
    This tree view class provides a hierarchical representation
    of the components of a menu.

    [see also:]
        SelectionInTreeView
        SelectionInTree
        TreeItem

    [author:]
        Claus Atzkern
"
! !

!MenuEditor::TreeView methodsFor:'accessing'!

canTab
    ^ true
!

selectorName
    "get the selector of the menu spec"

    ^(listOfNodes first contents label) asSymbol
!

selectorName: aSymbol
    "set the selector for the menu spec"

    listOfNodes first contents label: aSymbol
! !

!MenuEditor::TreeView methodsFor:'building'!

buildFromClass:aClass andSelector:aSelector
    "read a menu spec from aClass and aSelector and put 
     the encoded menu into the tree view"

    |spec cls menu firstNode firstNodeLabel|

    "if opened on a menu"
    (aClass isNil and: [aSelector isNil and: [listOfNodes size > 0]]) ifTrue: [^nil].

    self selection:nil.

    (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.
        ].
        firstNode := self nodeLabel:(aSelector asString).
        self subMenu:menu parent:firstNode.
    ] ifTrue:[
        (aClass notNil and: [aSelector isNil and: [listOfNodes size > 0]])
        ifTrue:
        [
            firstNode := listOfNodes first
        ]
        ifFalse:
        [
            aSelector notNil ifTrue:[firstNodeLabel := aSelector asString]
                        ifFalse:[firstNodeLabel := 'menu'].
            firstNode := self nodeLabel:firstNodeLabel.
        ]
    ].

    firstNode expand.
    model root: firstNode.

    firstNode hasChildren ifFalse:[
        model add:(self nodeLabel:'Item 1') below:firstNode
    ].


!

buildFromMenu:aMenu
    "put aMenu into the tree view"

    |node|

    self selection:nil.

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

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

menuItem:anItem

    |node|

    node := self nodeLabel: anItem label.
    node contents buildFromMenuItem:anItem.
    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'!

redrawLabelAt:x y:yTop index:anIndex
    "draw text label assigned to a node at x y( center)"

    |isSelected y0 x0 x1 w type item|

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

    type isNil ifTrue:[
        ^ super redrawLabelAt:x y:yTop index:anIndex
    ].
    isSelected := self isInSelection:anIndex.
    x0 := x.

    highlightMode == #label ifTrue:[
        x0 := x + 4.

        isSelected ifTrue:[
            w  := 80 + 8.
            self paint:hilightBgColor.
            self fillRectangleX:x y:yTop width:w height:fontHeight.
        ]
    ] ifFalse:[
        w := 0.
    ].
    type == #blank ifFalse:[
        isSelected ifTrue:[self paint:hilightFgColor]
                  ifFalse:[self paint:fgColor].

        x1 := x0 + 80.
        y0 := yTop - 1 + (fontHeight // 2).
        self displayLineFromX:x0 y:y0 toX:x1 y:y0.

        type == #double ifTrue:[
            y0 := y0 + 2.
            self displayLineFromX:x0 y:y0 toX:x1 y:y0.
        ]    
    ].

    (isSelected and:[highlightMode == #label]) ifTrue:[
        self redrawSelFrameAtX:x y:yTop toX:(x + w)
    ].

! !

!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 == #Delete or:[key == #BackSpace]) ifTrue: [^self doDelete].
    key == #Cut   ifTrue:[^self doCut].
    key == #Copy  ifTrue:[^self doCopy].
    key == #Paste ifTrue:[^self doPaste].

    super keyPress:key x:x y:y

! !

!MenuEditor::TreeView methodsFor:'initialization'!

initialize
    "initialize the tree view of the menu components"

    super initialize.

    self multipleSelectOk:true.
    self showDirectoryIndicator: true.
    self showDirectoryIndicatorForRoot: false.
    self selectConditionBlock: [:i|self application askForItemModification]. 
    self validateDoubleClickBlock: [:node| node ~~ listOfNodes first].
    self model iconAction: [:aNode| aNode contents iconFor: aNode].
    self model labelAction: [:aNode| aNode contents treeViewLabel]
! !

!MenuEditor::TreeView methodsFor:'menus'!

XXdoDeleteSelectionBuffered:aBool
    |appl idx|

    appl := self topView application.

    (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
        ^ self
    ].
    aBool ifTrue:[
        self doCopy
    ].

    idx := 10000.
    self selection do:[:aNumber| idx := idx min:aNumber ].

    self selectedNodesRemove.
    self selection:(idx min:(self list size)).
    self setModified.

    aBool ifTrue:[
        "/ must update copy&paste indication
        appl updateAllToolInstances.
    ]
!

doCopy
    |clip|

    self hasSelection ifTrue:[
        self application clipboard:(clip := OrderedCollection new).
        self selectionDo:[:i | clip add:((listOfNodes at:i) copy)].
        self topView application updateAllToolInstances.
    ]
!

doCreateItem

    self addElement: (self nodeLabel:'Item')
!

doCreateLink

    |node item|

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


!

doCreateMenu

    |node|
    node := self nodeLabel:'Submenu'.
    node parent: self selectedNode.        
    node add:(self nodeLabel:'Item 1').
    self addElement:node
!

doCreateSep

    self addElement:(self nodeLabel:nil)
!

doCreateStandardEditMenu

    |node|
    node := self nodeLabel:'Edit'.
    node parent: self selectedNode.        
    node add:(self nodeLabel:'Copy'  selector:#copySelection).
    node add:(self nodeLabel:'Cut'   selector:#cutSelection).
    node add:(self nodeLabel:'Paste' selector:#paste).
    self addElement:node

    "Created: / 23.8.1998 / 15:52:16 / cg"
    "Modified: / 23.8.1998 / 15:59:36 / cg"
!

doCreateStandardFileMenu

    |node|
    node := self nodeLabel:'File'.
    node parent: self selectedNode.        
    node add:(self nodeLabel:'New'        selector:#menuNew).
    node add:(self nodeLabel:'-'          ).
    node add:(self nodeLabel:'Open...'    selector:#menuOpen).
    node add:(self nodeLabel:'-'          ).
    node add:(self nodeLabel:'Save'       selector:#menuSave).
    node add:(self nodeLabel:'Save As...' selector:#menuSaveAs).
    node add:(self nodeLabel:'-'          ).
    node add:(self nodeLabel:'Exit'       selector:#closeRequest).
    self addElement:node

    "Created: / 23.8.1998 / 15:51:55 / cg"
    "Modified: / 23.8.1998 / 16:04:24 / cg"
!

doCreateStandardHelpMenu

    |node|
    node := self nodeLabel:'Help'.
    node parent: self selectedNode.        
    node contents startGroup:#right.
    node add:(self nodeLabel:'Documentation'          selector:#openDocumentation).
    node add:(self nodeLabel:'-').
    node add:(self nodeLabel:'About this Application' selector:#openAboutThisApplication).
    self addElement:node

    "Created: / 23.8.1998 / 15:52:46 / cg"
    "Modified: / 23.8.1998 / 17:30:12 / cg"
!

doCut
    ^ self doDeleteSelectionBuffered:true
!

doDelete
    ^ self doDeleteSelectionBuffered:false
!

doDeleteSelectionBuffered:aBool
    |appl nsel list item prnt|

    appl := self topView application.

    (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
        ^ self
    ].
    aBool ifTrue:[
        self doCopy
    ].
    list := self list.
    nsel := list size.
    self selection do:[:aNumber| nsel := nsel min:aNumber ].

    (     (item := list at:nsel ifAbsent:nil) notNil
     and:[(prnt := item parent) notNil
     and:[prnt children last == item]]
    ) ifTrue:[
        nsel := nsel - 1
    ].

    self selectedNodesRemove.
    self selection:(nsel min:(list size)).
    self setModified.

    aBool ifTrue:[
        "/ must update copy&paste indication
        appl updateAllToolInstances.
    ]
!

doPaste
    |clip|

    clip := self application clipboard.
    (clip notNil and:[self selectedNode notNil]) ifTrue:[
        self addElement:(clip collect:[:el| el copy])
    ].
! !

!MenuEditor::TreeView methodsFor:'private'!

addElement: aNode
    "add something after selection"

    |label sel|     

    self askForItemModification ifTrue:[   
        self selectedNodeAdd:aNode.
        (aNode isCollection not 
        and: [aNode name = 'Item']) 
        ifTrue:[
            sel := self selectedNode.
            label := aNode name , ' ',
                (sel parent notNil 
                ifTrue:
                    [
                        (((sel children size = 0 
                            ifTrue: [sel parent children] 
                            ifFalse: [sel children]) 
                        select:[:node| 
                            |lab| 
                            lab := node contents label. 
                            ((node children size = 0) & 
                            node contents submenuChannel isNil &
                            (lab ~= '-') & (lab ~= '=') & (lab ~= ''))
                        ]) size) printString
                    ] 
                ifFalse: ['1']).  

            aNode name: label string asBoldText.
            aNode contents label: label string.
        ].    
        aNode isCollection ifFalse: [self selectNode: aNode] ifTrue: [self selection: (aNode collect: [:node| self indexOfNode: node])].
        self setModified.
    ]
!

askForItemModification

    ^self topView application askForItemModification
!

nodeLabel:aLabel

    ^TreeItem new contents: ((MenuEditor::Item new label:aLabel) translateLabel:true)

    "Modified: / 6.6.1998 / 17:22:35 / cg"
!

nodeLabel:aLabel selector:aSelector

    ^TreeItem new contents: (((MenuEditor::Item new label:aLabel) value:aSelector) translateLabel:true)

    "Modified: / 6.6.1998 / 17:22:35 / cg"
    "Created: / 23.8.1998 / 15:58:59 / cg"
!

selectedNodeAdd:something

    |node numChildren|

    something notNil ifTrue:[
        (node := self selectedNode) notNil ifTrue:[
            numChildren := node children size.

            node parent notNil ifTrue:[
                node isCollapsable ifTrue:[
                    model add:something afterIndex:numChildren below:node
                ] ifFalse:[
                    model add:something after:node
                ]
            ] ifFalse:[
                model add:something afterIndex:numChildren below:(self root)
            ]
        ]
    ]


!

setModified 
    |app|

    (app := self topView application) modified: true.
    app updateChannels
! !

!MenuEditor class methodsFor:'documentation'!

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