MenuEditor.st
author Claus Gittinger <cg@exept.de>
Mon, 24 Aug 1998 21:54:38 +0200
changeset 971 f3b1476f5006
parent 970 23d20044894f
child 981 5b3b9588e57d
permissions -rw-r--r--
find all images in getAllImageSelectorsFrom: (walk superclass chain)

"
 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.
"



ResourceSpecEditor subclass:#MenuEditor
	instanceVariableNames:'specCanvas helpCanvas slices'
	classVariableNames:''
	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'
	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:'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>

    "/ ^ Image fromFile:'brokenImage.xpm'
    ^ Icon constantNamed:'brokenImage.xpm'

    "Modified: / 22.4.1998 / 22:15:11 / ca"
!

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

    ^#menu




! !

!MenuEditor class methodsFor:'aspects'!

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

    ^#(
        label
        accessCharacterPos
        argument
        submenuChannel
        enabled
        value
        nameKey
        indication
        choice
        choiceValue
        translateLabel
        isButton
        shortcutKey
        startGroup
        retriever
        iconAndLabel
        icon
        isVisible
     )

    "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
'Adds a new menu item.'

#addMenuSeparator
'Adds a new menu separator.'

#addSubMenu
'Adds a new sub menu.'

#addSubMenuLink
'Adds a new linked sub menu.'

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

#basicsArgument
'An argument passed to above selector, if it is a 1 or a 2 argument selector.'

#basicsIndication
'A boolean holder, a boolean block, or a boolean method, specifying the indication state.'

#basicsChoice
'A boolean holder, a boolean block, or a boolean method, specifying the choices state.'

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

#basicsIsButton
'Turns on/off a button behavior.'

#basicsLabel
'Label of the item.'

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

#basicsMenu
'A value holder providing the sub menu to be opened if item is selected.'

#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).'

#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).'

#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
'Opens a dialog to select and load a menu spec from a class.'

#fileNew
'Creates a new menu spec.'

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

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

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

#historyMenuItem
'Edit this menu specification.'

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

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

#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).'

#imageImageList
'Currently existing image resources.'

#test
'Displays the current menu (layout test).'
)

    "Modified: / 18.8.1998 / 16:19:13 / cg"
! !

!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
          #window: 
           #(#WindowSpec
              #name: 'Basics Item'
              #layout: #(#LayoutFrame 216 0 173 0 482 0 491 0)
              #label: 'Basics Item'
              #min: #(#Point 10 10)
              #max: #(#Point 1160 870)
              #bounds: #(#Rectangle 216 173 483 492)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'nameKeyLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #activeHelpKey: #basicsKey
                    #label: 'Name Key:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'nameKeyField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #basicsKey
                    #tabable: true
                    #model: #nameKey
                    #group: #inputGroup
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#LabelSpec
                    #name: 'labelLabel'
                    #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #activeHelpKey: #basicsLabel
                    #label: 'Label:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'labelField'
                    #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #activeHelpKey: #basicsLabel
                    #tabable: true
                    #model: #label
                    #group: #inputGroup
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#LabelSpec
                    #name: 'valueLabel'
                    #activeHelpKey: #basicsAction
                    #layout: #(#AlignmentOrigin 107 0 90 0 1 0.5)
                    #label: 'Action:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'valueField'
                    #layout: #(#LayoutFrame 110 0 79 0 -5 1.0 101 0)
                    #activeHelpKey: #basicsAction
                    #tabable: true
                    #model: #value
                    #group: #inputGroup
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#LabelSpec
                    #name: 'argumentLabel'
                    #layout: #(#AlignmentOrigin 107 0 115 0 1 0.5)
                    #activeHelpKey: #basicsArgument
                    #label: 'Argument:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'argumentField'
                    #layout: #(#LayoutFrame 110 0 104 0 -5 1.0 126 0)
                    #activeHelpKey: #basicsArgument
                    #tabable: true
                    #model: #argument
                    #group: #inputGroup
                    #type: #string
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#LabelSpec
                    #name: 'indicationLabel'
                    #layout: #(#AlignmentOrigin 107 0 155 0 1 0.5)
                    #activeHelpKey: #basicsIndication
                    #label: 'Indication:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'indicationField'
                    #layout: #(#LayoutFrame 110 0 144 0 -5 1.0 166 0)
                    #activeHelpKey: #basicsIndication
                    #enableChannel: #indicationEnabled
                    #tabable: true
                    #model: #indication
                    #group: #inputGroup
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#CheckBoxSpec
                    #name: 'translateLabelCheckBox'
                    #layout: #(#Point 20 230)
                    #activeHelpKey: #basicsTranslateLabel
                    #tabable: true
                    #model: #translateLabel
                    #label: 'Translate Label'
                )
                 #(#CheckBoxSpec
                    #name: 'isButtonCheckBox'
                    #layout: #(#Point 20 259)
                    #activeHelpKey: #basicsIsButton
                    #tabable: true
                    #model: #isButton
                    #label: 'Is Button'
                )
                 #(#LabelSpec
                    #name: 'choiceLabel'
                    #layout: #(#AlignmentOrigin 107 0 180 0 1 0.5)
                    #activeHelpKey: #basicsChoice
                    #label: 'Choice:'
                    #translateLabel: true
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'choiceField'
                    #layout: #(#LayoutFrame 110 0 169 0 -5 1.0 191 0)
                    #activeHelpKey: #basicsChoice
                    #enableChannel: #choiceEnabled
                    #tabable: true
                    #model: #choice
                    #group: #inputGroup
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                )
                 #(#LabelSpec
                    #name: 'choiceValueLabel'
                    #activeHelpKey: #basicsChoiceValue
                    #layout: #(#AlignmentOrigin 107 0 205 0 1 0.5)
                    #label: 'Value:'
                    #translateLabel: true
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'choiceValueField'
                    #layout: #(#LayoutFrame 110 0 194 0 -5 1.0 216 0)
                    #activeHelpKey: #basicsChoiceValue
                    #enableChannel: #choiceValueEnabled
                    #tabable: true
                    #model: #choiceValue
                    #group: #inputGroup
                    #type: #smalltalkObject
                    #acceptOnReturn: true
                    #acceptOnTab: true
                    #acceptOnLeave: true
                    #acceptOnLostFocus: true
                    #immediateAccept: false
                )
              )
          )
      )

    "Modified: / 18.8.1998 / 16:20:26 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Basics Link'
              #layout: #(#LayoutFrame 473 0 301 0 739 0 619 0)
              #label: 'Basics Link'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 473 301 740 620)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'nameKeyLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #activeHelpKey: #nameKey
                    #label: 'Name Key:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'nameKeyField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #basicsNameKey
                    #tabable: true
                    #model: #nameKey
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'labelLabel'
                    #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #label: 'Label:'
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'labelField'
                    #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #activeHelpKey: #basicsLabel
                    #tabable: true
                    #model: #label
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'menuLabel'
                    #layout: #(#AlignmentOrigin 107 0 76 0 1 0.5)
                    #label: 'Menu:'
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'menuField'
                    #layout: #(#LayoutFrame 110 0 65 0 -5 1.0 87 0)
                    #activeHelpKey: #basicsMenu
                    #tabable: true
                    #model: #submenuChannel
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'ArgumentLabel'
                    #layout: #(#AlignmentOrigin 107 0 100 0 1 0.5)
                    #label: 'Argument:'
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'argumentField'
                    #layout: #(#LayoutFrame 110 0 90 0 -5 1.0 112 0)
                    #activeHelpKey: #basicsMenuArgument
                    #tabable: true
                    #model: #argument
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#CheckBoxSpec
                    #name: 'translateLabelCheckBox'
                    #layout: #(#Point 20 190)
                    #activeHelpKey: #basicsTranslateLabel
                    #tabable: true
                    #model: #translateLabel
                    #label: 'Translate Label'
                )
              )
          )
      )

    "Modified: / 31.7.1998 / 01:18:16 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Basics Menu'
              #layout: #(#LayoutFrame 473 0 301 0 739 0 619 0)
              #label: 'Basics Menu'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 473 301 740 620)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'nameKeyLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #label: 'Name Key:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'nameKeyField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #basicsNameKey
                    #tabable: true
                    #model: #nameKey
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'labelLabel'
                    #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #label: 'Label:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'labelField'
                    #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #activeHelpKey: #basicsLabel
                    #tabable: true
                    #model: #label
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#CheckBoxSpec
                    #name: 'translateLabelCheckBox'
                    #layout: #(#Point 20 190)
                    #activeHelpKey: #basicsTranslateLabel
                    #tabable: true
                    #model: #translateLabel
                    #label: 'Translate Label'
                )
              )
          )
      )

    "Modified: / 31.7.1998 / 01:18:23 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Basics Root'
              #layout: #(#LayoutFrame 473 0 301 0 739 0 619 0)
              #label: 'Basics Root'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 473 301 740 620)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'selectorLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #label: 'Selector:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'selectorField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #basicsSelector
                    #tabable: true
                    #model: #label
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
              )
          )
      )

    "Modified: / 31.7.1998 / 01:18:28 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Basics Separator'
              #layout: #(#LayoutFrame 473 0 301 0 739 0 619 0)
              #label: 'Basics Separator'
              #min: #(#Point 10 10)
              #max: #(#Point 1160 870)
              #bounds: #(#Rectangle 473 301 740 620)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'separatorLabel'
                    #layout: #(#AlignmentOrigin 127 0 26 0 1 0.5)
                    #label: 'Separator Type:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#ComboListSpec
                    #name: 'seperatorList'
                    #layout: #(#LayoutFrame 132 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #basicsSeparatorType
                    #tabable: true
                    #model: #seperatorSelection
                    #useIndex: true
                )
                 #(#LabelSpec
                    #name: 'visibilityLabel'
                    #layout: #(#AlignmentOrigin 127 0 76 0 1 0.5)
                    #label: 'Visibility:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'visibilityInputField'
                    #layout: #(#LayoutFrame 132 0 65 0 -5 1.0 87 0)
                    #activeHelpKey: #detailsVisibility
                    #tabable: true
                    #model: #isVisible
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
              )
          )
      )

    "Modified: / 31.7.1998 / 01:18:32 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Details Edit'
              #layout: #(#LayoutFrame 332 0 374 0 590 0 661 0)
              #label: 'Details Edit'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 332 374 591 662)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#LabelSpec
                    #name: 'shortcutKeyLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #activeHelpKey: #detailsAccelerator
                    #label: 'Accelerator:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'shortcutKeyField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #detailsAccelerator
                    #tabable: true
                    #model: #shortcutKey
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'enabledLabel'
                    #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #activeHelpKey: #detailsEnabled
                    #label: 'Enabled:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'enabledField'
                    #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #activeHelpKey: #detailsEnabled
                    #tabable: true
                    #model: #enabled
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'visibilityLabel'
                    #layout: #(#AlignmentOrigin 107 0 76 0 1 0.5)
                    #activeHelpKey: #detailsVisibility
                    #label: 'Visibility:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'isVisibleInputField'
                    #layout: #(#LayoutFrame 110 0 65 0 -5 1.0 87 0)
                    #activeHelpKey: #detailsVisibility
                    #tabable: true
                    #model: #isVisible
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'StartGroupLabel'
                    #layout: #(#AlignmentOrigin 107 0 111 0 1 0.5)
                    #activeHelpKey: #detailsStartGroup
                    #label: 'Start Group:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#PopUpListSpec
                    #name: 'StartGroupPopUp'
                    #activeHelpKey: #detailsStartGroup
                    #layout: #(#LayoutFrame 110 0 100 0 -5 1.0 122 0)
                    #label: 'PopUpList'
                    #tabable: true
                    #model: #startGroup
                    #menu: 
                     #(nil
                        #right
                    )
                    #useIndex: false
                )
                 #(#LabelSpec
                    #name: 'accessCharLabel'
                    #layout: #(#AlignmentOrigin 217 0 142 0 1 0.5)
                    #activeHelpKey: #detailsAccessCharaterPosition
                    #label: 'Access Character Position:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'accessCharField'
                    #layout: #(#LayoutFrame 220 0 131 0 -5 1.0 153 0)
                    #activeHelpKey: #detailsAccessCharaterPosition
                    #tabable: true
                    #model: #accessCharacterPos
                    #type: #numberOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
              )
          )
      )

    "Modified: / 18.8.1998 / 16:16:46 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Image Item'
              #layout: #(#LayoutFrame 182 0 348 0 577 0 624 0)
              #label: 'Image Item'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 182 348 578 625)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#CheckBoxSpec
                    #name: 'iconAndLabelCheckBox'
                    #layout: #(#LayoutOrigin 20 0 215 0)
                    #activeHelpKey: #imageImageAndLabel
                    #tabable: true
                    #model: #iconAndLabel
                    #label: 'Image & Label'
                )
                 #(#LabelSpec
                    #name: 'retrieverLabel'
                    #layout: #(#AlignmentOrigin 107 0 26 0 1 0.5)
                    #activeHelpKey: #imageRetriever
                    #label: 'Retriever:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'retrieverField'
                    #layout: #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
                    #activeHelpKey: #imageRetriever
                    #tabable: true
                    #model: #retriever
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#LabelSpec
                    #name: 'iconLabel'
                    #layout: #(#AlignmentOrigin 107 0 51 0 1 0.5)
                    #activeHelpKey: #imageSelector
                    #label: 'Selector:'
                    #adjust: #right
                    #resizeForLabel: true
                )
                 #(#InputFieldSpec
                    #name: 'iconField'
                    #layout: #(#LayoutFrame 110 0 40 0 -5 1.0 62 0)
                    #activeHelpKey: #imageSelector
                    #tabable: true
                    #model: #icon
                    #type: #symbolOrNil
                    #acceptOnReturn: false
                    #acceptOnTab: false
                    #group: #inputGroup
                )
                 #(#ActionButtonSpec
                    #name: 'imageEditorButton'
                    #layout: #(#LayoutFrame 5 0.6 67 0 -5 1 91 0)
                    #activeHelpKey: #imageImageEditor
                    #label: 'Image Editor'
                    #tabable: true
                    #model: #doEditImage
                )
                 #(#SequenceViewSpec
                    #name: 'systemOrUserImagesList'
                    #activeHelpKey: #imageImageList
                    #layout: #(#LayoutFrame 110 0 67 0 0 0.6 200 0)
                    #model: #selectionOfImage
                    #menu: #menuEditImage
                    #hasHorizontalScrollBar: true
                    #hasVerticalScrollBar: true
                    #miniScrollerHorizontal: true
                    #doubleClickSelector: #doEditImage
                    #valueChangeSelector: #imageSelected
                    #useIndex: false
                    #sequenceList: #listOfImages
                )
              )
          )
      )

    "Modified: / 18.8.1998 / 16:17:59 / cg"
!

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
          #window: 
           #(#WindowSpec
              #name: 'Menu Editor'
              #layout: #(#LayoutFrame 53 0 403 0 609 0 810 0)
              #label: 'Menu Editor'
              #min: #(#Point 510 390)
              #max: #(#Point 1152 900)
              #bounds: #(#Rectangle 53 403 610 811)
              #menu: #menu
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#MenuPanelSpec
                    #name: 'menuToolbarView'
                    #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
                    #menu: #menuToolbar
                    #showSeparatingLines: true
                )
                 #(#VariableHorizontalPanelSpec
                    #name: '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
                              #component: #treeView
                              #hasBorder: false
                          )
                           #(#ViewSpec
                              #name: 'Box'
                              #component: 
                               #(#SpecCollection
                                  #collection: 
                                   #(
                                     #(#NoteBookViewSpec
                                        #name: 'NoteBook'
                                        #layout: #(#LayoutFrame 1 0.0 0 0.0 1 1.0 -30 1.0)
                                        #tabable: true
                                        #model: #tabModel
                                        #menu: #tabList
                                        #useIndex: true
                                        #canvas: #noteBookView
                                    )
                                     #(#UISubSpecification
                                        #name: 'SubSpecification'
                                        #layout: #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
                                        #majorKey: #ToolApplicationModel
                                        #minorKey: #windowSpecForCommit
                                    )
                                  )
                              )
                              #level: -1
                          )
                        )
                    )
                    #handles: #(#Any 0.30117 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: 'About'
                #translateLabel: true
                #accessCharacterPosition: 1
                #labelImage: #(#ResourceRetriever nil #menuIcon)
                #submenuChannel: #menuAbout
            )
             #(#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:
                      )
                    ) 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 File Menu'
                          #translateLabel: true
                          #value: #doCreateStandardFileMenu
                      )
                       #(#MenuItem
                          #label: 'Standard Edit Menu'
                          #translateLabel: true
                          #value: #doCreateStandardEditMenu
                      )
                       #(#MenuItem
                          #label: 'Standard Help Menu'
                          #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
                #shortcutKeyCharacter: #Cut
            )
             #(#MenuItem
                #label: 'Copy'
                #translateLabel: true
                #value: #doCopy
                #activeHelpKey: #editCopy
                #enabled: #hasValidSelection
                #shortcutKeyCharacter: #Copy
            )
             #(#MenuItem
                #label: 'Paste'
                #translateLabel: true
                #value: #doPaste
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPaste
                #shortcutKeyCharacter: #Paste
            )
             #(#MenuItem
                #label: 'Delete'
                #translateLabel: true
                #value: #doDelete
                #activeHelpKey: #editDelete
                #enabled: #hasValidSelection
                #shortcutKeyCharacter: #Delete
            )
             #(#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
                #shortcutKeyCharacter: #Cut
            )
             #(#MenuItem
                #label: 'Remove'
                #translateLabel: true
                #value: #doRemoveImage
                #activeHelpKey: #editCopy
                #enabled: #hasValidSelection
                #shortcutKeyCharacter: #Copy
            )
          ) 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 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].

     imageMethodSelectors := OrderedCollection new.

     iconClass withAllSuperclasses do:[:cls |
        cls class methodDictionary keysAndValuesDo: [:sel :m | 
            (r := m resourceType == #image
            or:[r == #programImage]) ifTrue:[
                imageMethodSelectors add:sel
            ]
        ]
     ].

     ^ imageMethodSelectors asSortedCollection asOrderedCollection

    "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 := self 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 noteBookView.

    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
!

hasValidSingleSelection

    ^builder booleanValueAspectFor: #hasValidSingleSelection
!

listOfImages
    "get a list of the images"

    |holder|
    (holder := builder bindingAt:#listOfImages) isNil ifTrue:[
        builder aspectAt:#listOfImages put: (holder := List new).
        self updateListOfImages    
    ].
    ^ holder


!

noteBookView
    "create the note book view containing the attibute sections and the help tool"

    |noteBook helpTool|

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

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

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

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

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


!

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 := #(Basics Details Image Help) asValue).
    ].
    ^ holder


!

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

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

!MenuEditor methodsFor:'building'!

buildFromClass:aClass andSelector:aSelector

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

    self updateHistory.
    self updateInfoLabel.
    self treeView selection: 2.
    self menuChanged

!

buildFromResourceSpec: aResourceSpec

    self buildFromMenu:  
        (aResourceSpec class == Menu ifTrue: [aResourceSpec] ifFalse: [aResourceSpec decodeAsLiteralArray])
! !

!MenuEditor methodsFor:'change & update'!

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

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

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

updateChannels
    "update channels"

    |node parent next state|

    state := false.   
    self updateSelectionOfImage.

    (node  := self treeView selectedNode) notNil
    ifTrue:
    [
        self hasAnySingleSelection value:true.
        (parent := node parent) notNil
        ifTrue:
        [
            next := parent childAt:((parent indexOfChild:node) + 1).
            self valueOfEnableMovingIn       value:(next notNil and:[next hasChildren]).
            self valueOfEnableMovingUpOrDown value:(parent children size > 1).
            self valueOfEnableMovingOut      value:parent parent notNil.
            self hasValidSingleSelection     value:true.
            self hasValidSelection           value:true.  
            self valueOfCanPaste             value:true & self valueOfCanPaste value. 
            ^self
        ]
    ]
    ifFalse:
    [
        self hasAnySingleSelection value:false.
        self treeView numberOfSelections ~~ 0 ifTrue:[
            state := (self treeView isInSelection:1) not
        ]
    ].          
    self valueOfEnableMovingUpOrDown value:false.
    self valueOfEnableMovingIn       value:false.
    self valueOfEnableMovingOut      value:false.
    self hasValidSingleSelection     value:false.
    self hasValidSelection           value:state.     
    self valueOfCanPaste             value:(self hasValidSingleSelection value or: [node == self treeView root]) & self valueOfCanPaste value. 

!

updateListAndSelectionOfImage
    "updates the list and selection of image"

    self updateListOfImages.
    self updateSelectionOfImage
!

updateListOfImages
    "updates the list of images"

    |iconClass|      

    (iconClass := (aspects at: #retriever) value ? specClass) notNil ifTrue: 
    [
        iconClass := Smalltalk at: iconClass
    ].

    self listOfImages contents:
        ((self class getAllImageSelectorsFrom: iconClass)
            collect: [:sel| |image| image := iconClass perform: sel. LabelAndIcon icon:(image magnifiedBy: 22/image extent y ) string: sel]).

    "Modified: / 24.8.1998 / 21:29:24 / cg"
!

updateSelectionOfImage
    "updates the selection of image"

    self selectionOfImage value: nil.
    self updateListOfImages.
    self selectionOfImage value: (self listOfImages detect: [:im| im string == (aspects at: #icon) value] ifNone: nil).

! !

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

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


! !

!MenuEditor methodsFor:'private'!

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

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

helpTool
    "get the help tool"

    ^helpCanvas application
! !

!MenuEditor methodsFor:'queries'!

isHelpToolSelected
    "return true if current selection is help tool"

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

preferredExtent

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


! !

!MenuEditor methodsFor:'selection'!

imageSelected

    (aspects at: #icon) value: self selectionOfImage value string

!

menuChanged

    |node item slc sel old|

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

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

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

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

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

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

    "Modified: / 14.8.1998 / 14:52:32 / cg"
!

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

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

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

    "Modified: / 14.8.1998 / 15:07:06 / cg"
! !

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

    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)).

    "Modified: / 14.8.1998 / 15:07:58 / cg"
!

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

    super openModalOnResourceSpec: aMenu
!

postOpenWith:aBuilder

    super postOpenWith:aBuilder.

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

! !

!MenuEditor methodsFor:'user actions'!

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

    |node|

    super accept.

    (node := self treeView selectedNode) notNil
    ifTrue:
    [
        self isHelpToolSelected
        ifTrue:
        [
            self helpTool accept.
            node contents activeHelpKey: self helpTool helpKey.
            self valueOfEnablingCommitButtons value: false.
        ]
        ifFalse:
        [
            node contents buildFromAspects: aspects.
            node changed.
            specSelector := self treeView selectorName.
        ]
    ].   
    self updateInfoLabel.
    self updateListAndSelectionOfImage
!

cancel
    "invoked by button 'Cancel'"

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

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.

    self updateListAndSelectionOfImage
!

doNew

    super doNew ifTrue: [self helpTool doNew]
!

doPickAMenu

    |view|

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

doRemoveImage
    "removes the image of the selected line"

    self selectionOfImage value notNil
    ifTrue:
    [
        (Smalltalk at: (aspects at: #retriever) value ? specClass) class removeSelector:
            self selectionOfImage value string.

        self updateListAndSelectionOfImage.
        (aspects at:#icon) value: nil
    ] 
!

doSave
    |cls treeView menu spec mthd category code excla|

    super doSave ifFalse: [^nil].

    cls := self resolveName: specClass.
    treeView := self treeView.
    menu     := treeView asMenu.
    menu := menu literalArrayEncoding.
    spec := WriteStream on:String new.
    UISpecification prettyPrintSpecArray:menu on:spec indent:5.
    spec := spec contents.

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

    category := '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: [self treeView selectorName: specSelector]
!

doStepDown
    "shift selected menu item one step down"

    self treeView selectedNodeChangeSequenceOrder:1.
    modified := true.




!

doStepIn
    "move selected menu item into next submenu"

    self treeView selectedNodeBecomeChildOfNext.
    modified := true.





!

doStepOut
    "move selected menu item out from parent submenu"

    self treeView selectedNodeBecomeSisterOfParent.
    modified := true.
!

doStepUp
    "shift selected menu item one step up"

    self 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.
        argument           := (aspects at:#argument) value.
        translateLabel     := (aspects at:#translateLabel) value.
        isButton           := (aspects at:#isButton) value.

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

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

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

    |rtv|

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

    (enabled := anItem enabled) isSymbol ifFalse:[
        enabled := nil
    ].
    (value := anItem value) isSymbol ifFalse:[
        value := nil.
    ].
    (indication := anItem indication) isSymbol ifFalse:[
        indication := nil
    ].
    (choice := anItem choice) isSymbol ifFalse:[
        choice := nil
    ].
    choiceValue := anItem choiceValue.

    nameKey            := anItem nameKey.
    shortcutKey        := anItem shortcutKeyCharacter.
    startGroup         := anItem startGroup.
    accessCharacterPos := anItem accessCharacterPosition.
    argument           := anItem argument.

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

    (((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: / 14.8.1998 / 15:37:20 / cg"
! !

!MenuEditor::Item methodsFor:'conversion'!

asMenuItem
    "converts self to a menu item"

    |item rcv|

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

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

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

    "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:#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.

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

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

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

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

    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 maxX w label 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'!

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
    |app|

    app := self topView application.
    (app hasValidSelection value and: [self askForItemModification])
    ifTrue:
    [
        |selectedNodes|
        self doCopy.
        selectedNodes := self selection asSortedCollection.
        self selectedNodesRemove.
        self selection: selectedNodes first - 1.
        self setModified.
        app updateAllToolInstances.
    ]

!

doDelete

    (self topView application hasValidSelection value and: [self askForItemModification])
    ifTrue:
    [
        |selectedNodes|
        selectedNodes := self selection asSortedCollection.
        self selectedNodesRemove.
        self selection: selectedNodes first - 1.
        self setModified.
    ]

!

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"

    self askForItemModification
    ifTrue:
    [   
        self selectedNodeAdd: aNode.
        (aNode isCollection not and: [aNode name = 'Item']) 
        ifTrue: 
        [
            |label|     
            label := aNode name, ' ',
                (self selectedNode parent notNil 
                ifTrue:
                [
                    (((self selectedNode children size = 0 
                        ifTrue: [self selectedNode parent children] 
                        ifFalse: [self selectedNode 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|

    something notNil ifTrue:[
        (node := self selectedNode) notNil ifTrue:[
            node parent notNil ifTrue:[
                node isCollapsable ifTrue:[
                    model add:something afterIndex:node children size below:node
                ] ifFalse:[
                    model add:something after:node
                ]
            ] ifFalse:[
                model add:something afterIndex:node children size below:(self root)
            ]
        ]
    ]


!

setModified 
    |app|

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

!MenuEditor class methodsFor:'documentation'!

version
    ^ '$Header$'
! !