UIPainter.st
author tz
Mon, 30 Mar 1998 14:45:46 +0200
changeset 754 04e802a6a920
parent 743 d58a3e7e39d5
child 755 cfbbec0a33c6
permissions -rw-r--r--
color master selection in red + grid background colored

"
 COPYRIGHT (c) 1995 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.
"


ToolApplicationModel subclass:#UIPainter
	instanceVariableNames:'treeView selectionPanel tabSelection specClass specSelector
		specSuperclass aspects layoutCanvas helpCanvas specCanvas
		transcript modified'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

SelectionInTreeView subclass:#TreeView
	instanceVariableNames:'lastDrawnMaster cvsEventsDisabled windowSpec'
	classVariableNames:''
	poolDictionaries:''
	privateIn:UIPainter
!

!UIPainter class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1995 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
"
    GUI-Builder:
    this class allows the user to build its own applications providing a graphical
    user interface to buildin components and to define the behavior of the components
    during runtime. The resulting specifications can be installed as methods on 
    classes, typically subclasses of an ApplicationModel. These specifications
    are used by the UIBuilder to generate the application window and its component
    structues when open the application.

    [start with:]
        UIPainter open

    [author:]
        Claus Gittinger, eXept Software AG
        Claus Atzkern, eXept Software AG

    [see also:]
        UIBuilder
        ApplicationModel
        UISpecification
"

! !

!UIPainter class methodsFor:'instance creation'!

openOnClass:aClass andSelector:aSelector
    "open a GUI Painter on aClass and (windowSpec) aSelector
    "
    ^ self new openOnClass:aClass andSelector:aSelector
!

painter:aBuilderView
    "set the painter
    "
    |application|

    application := self new.
    application painter:aBuilderView.
  ^ application open
! !

!UIPainter class methodsFor:'ST-80 queries'!

preferenceFor:aSymbol
    "ST-80 compatible; always returns false
    "
    ^ false


! !

!UIPainter class methodsFor:'accessing-defaults'!

defaultNameOfCanvas
    "returns the default name (id) of the application
    "
    ^'NewApplication'

! !

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

    <resource: #help>

    ^super helpSpec addPairsFrom:#(

#alignSelectionBottom
'Aligns the selected widgets to the bottom edge of the dominant widget.'

#alignSelectionCenterHor
'Aligns the selected widgets vertically to the center of the dominant widget.'

#alignSelectionCenterVer
'Aligns the selected widgets horizontally to the center of the dominant widget.'

#alignSelectionLeft
'Aligns the selected widgets to the left edge of the dominant widget.'

#alignSelectionLeftAndRight
'Aligns the selected widgets to the right and left edge of the dominant widget.'

#alignSelectionRight
'Aligns the selected widgets to the right edge of the dominant widget.'

#alignSelectionTop
'Aligns the selected widgets to the top edge of the dominant widget.'

#alignSelectionTopAndBottom
'Aligns the selected widgets to the top and bottom edge of the dominant widget.'

#centerSelectionHor
'Centers the selected widgets horizontally to their contained widget.'

#centerSelectionVer
'Centers the selected widgets vertically in their contained widget.'

#changePositionDown
'Changes the position of the widgets to the bottom.'

#changePositionLeft
'Changes the position of the widgets to the left.'

#changePositionRight
'Changes the position of the widgets to the right.'

#changePositionUp
'Changes the position of the widgets to the top.'

#editDimensionCopyExtent
'Copies the extent of the selected widgets.'

#editDimensionCopyLayout
'Copies the layout of the selected widgets.'

#editDimensionDefaultExtent
'Sets the selected widgets to their default extent.'

#editDimensionDefaultHeight
'Sets the selected widgets to their default height.'

#editDimensionDefaultWidth
'Sets the selected widgets to their default width.'

#editDimensionPasteExtent
'Sets the extent of the selected widgets to the last copied extent.'

#editDimensionPasteHeight
'Sets the height of the selected widgets to the height of the last copied layout/extent.'

#editDimensionPasteLayout
'Sets the layout of the selected widgets to the last copied layout.'

#editDimensionPasteWidth
'Sets the width of the selected widgets to the width of the last copied layout/extent.'

#editInspectSpec
'Opens an inspector on the spec of the selected widget.'

#editOpenSpecDocumentation
'Opens the documentation of the selected widget.'

#fileBrowseAspectMethods
'Opens a System Browser to browse the aspect methods.'

#fileLoad
'Opens a dialog to load a window spec from a class.'

#fileLoadSubspec
'Opens a dialog to load an sub spec from a class.'

#fileNew
'Creates a new window spec.'

#filePickAnInterface
'Changes the cursor for moving it over another interface application to load its window spec.'

#fileSave
'Saves current window spec on current class and if modified the help spec.'

#fileSaveAs
'Opens a dialog to select or create a class and selector in order to save current window spec.'

#fileShowWindowSpec
'Opens a Workspace showing the current window spec.'

#generateAspectMethods
'Generates aspect methods for defined aspect selectors of the widgets.'

#generateHookMethods
'Generates startup/release methods. (#closeRequest, #postBuildWith:, #postOpenWith:)'

#moveWidgetDown
'Moves the selected widget one step down.'

#moveWidgetInto
'Moves the selected widget into next widget as child widget.'

#moveWidgetOut
'Moves the selected widget out of its parent widget.'

#moveWidgetUp
'Moves the selected widget one step up.'

#pasteBuffer
'Pastes the widgets of the clipboard at current mouse position.'

#pasteWithLayout
'Pastes the widgets of the clipboard without a changing of their layouts.'

#settingsCanvas
'Shows or hides the canvas window.'

#settingsGallery
'Shows or hides the gallery window.'

#settingsGridManager
'Opens a dialog to show/hide the grid points or to change the distances between them.'

#settingsRedefineAspectMethods
'Turns on/off the permission of redefinition of the aspect methods.'

#settingsTranscriptHelp
'Turns on/off showing help texts in a transcript (after opening of a new GUI Painter).'

#settingsUndoManager
'Opens a dialog to reverse a certain number of last edit action.'

#spreadSelectionHor
'Sets the horizontal spaces between the selected widgets as the same.'

#spreadSelectionVer
'Sets the vertical spaces between the selected widgets as the same.'

#testGeometryTestMode
'Turns on/off the geometry test mode in order to define ratios of variable panels.'

#testStartApplication
'Starts current application on current window spec.'

)
! !

!UIPainter class methodsFor:'helpers'!

convertString:aString maxLineSize:maxCharactersPerLine skipLineFeed:skipLineFeed
    "converts a string to a string collection with maximum characters
     per line
    "
    |stream
        max     "{ Class:SmallInteger }"
        size    "{ Class:SmallInteger }"
        start   "{ Class:SmallInteger }"
        stop    "{ Class:SmallInteger }"
        cpySz   "{ Class:SmallInteger }"
        lnSz    "{ Class:SmallInteger }"
        atBeginOfLine|

    maxCharactersPerLine < 20 ifFalse:[max := maxCharactersPerLine - 1]
                               ifTrue:[max := 20].

    (size := aString size) <= max ifTrue:[
        ^ aString
    ].
    start  := 1.
    lnSz   := 0.
    stream := (String new:size) writeStream.

    atBeginOfLine := true.

    [start <= size] whileTrue:[
        (start := aString indexOfNonSeparatorStartingAt:start) == 0 ifTrue:[
            ^ stream contents
        ].
        (aString at:start) == $\ ifTrue:[
            skipLineFeed ifFalse:[
                stream nextPut:$\
            ].
            start := start + 1.
            stream cr.
            start := start + 1.
            lnSz := 0.
        ] ifFalse:[
            (stop := aString indexOfSeparatorStartingAt:start) == 0 ifTrue:[
                stop := size + 1
            ].
            (aString at:(stop - 1)) == $\ ifTrue:[
                stop := stop - 1
            ].
            cpySz := stop - start.

            lnSz == 0 ifFalse:[
                (lnSz := lnSz + cpySz) >= max ifTrue:[stream cr.    lnSz := cpySz. atBeginOfLine := true. ]
                                             ifFalse:[stream space. lnSz := lnSz + 1]
            ] ifTrue:[
                lnSz := cpySz
            ].
            stream nextPutAll:aString startingAt:start to:(stop - 1).
            start := stop.
        ]
    ].
    ^ stream contents

    "Modified: / 1.2.1998 / 14:42:56 / cg"
! !

!UIPainter class methodsFor:'image specs'!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignB'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@E@@@@@@@G@@@@@@@G@E@@@@@G@G@@@@@G@G@@@@@G@G@@@E@G@G@@@G@G@G@K@G@G@G@@@G@G@G@A@G@G@G@@@G@G@G@K@@@@@@@@B*****(@B*****(@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@G C@G @@G'' @G'' @G'' @G'' G'''' G'''' G'''' G''''!!G'''' G'''' G'''' G'''' O??0O??0@@@@@@@C@@@@') ; yourself); yourself]!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignL'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@(@@@@@@@(@@@@@@@(UUUP@I@(_??0@@@(@@@@@@@(@@@@@@@(@@@@@@@(@@@@@@@(UUUU@@@(_???@@@(@@@@@E@(@@@@@@@(@@@@@@@(@@@@@@@(UU@@@@@(_?@@@@@(@@@@@@@(@@@@@@@@@@@@@E@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@F@@@G?>@G?>@G?>@G?>@F@@@F@@@G?? G?? G?? G?? F@@@F@@@G? @G? @G? @G? @F@@@@@@@@@@@') ; yourself); yourself]!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignLR'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@(@@@B @@(@@@B @@(UUUR I@(_??2 @@(@@@B @@(@@@B @@(@@@B @@(@@@B @@(UUUR @@(_??2 @@(@@@B E@(@@@B @@(@@@B @@(@@@B @@(UUUR @@(_??B @@(@@@B @@(@@@B @@@@@@@@E@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@F@A G?? G?? G?? G?? F@A F@A G?? G?? G?? G?? F@A F@A G?? G?? G?; G?? F@A @@@@@@@@') ; yourself); yourself]!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignR'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@B @@@@@@B @@@UUUR I@@_??2 @@@@@@B @@@@@@B @@@@@@B @@@@@@B @@EUUUR @@G???2 @@@@@@B E@@@@@B @@@@@@B @@@@@@B @@@@EUR @@@@G?2 @@@@@@B @@@@@@B @@@@@@@@E@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@A A?? A?? A?? A?? @@A @@A G?? G?? G?? G?? @@A @@A @G? @G? @G? @G? @@A @@@@@@@@') ; yourself); yourself]!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignT'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@B*****(@B*****(@@@@@@@@@@E@E@E@K@G@G@G@@@G@G@G@A@G@G@G@@@G@G@G@K@G@G@G@@@@@G@G@@@@@G@G@@@@@G@G@@@@@G@G@@@@@G@@@@@@@G@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@C@@@@O??0O??0G'''' G'''' G'''' G'''' G''''!!G'''' G'''' G'''' @G'' @G'' @G'' @G'' @G @@G C@@@@@@@@@@@@') ; yourself); yourself]!

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

    <resource: #image>

    ^Icon
        constantNamed:#'UIPainter iconAlignTB'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@@B*****(@B*****(@@@@@@@@@@E@E@E@G@G@G@G@@@G@G@G@@@G@G@G@@@G@G@G@H@G@G@G@@@G@G@G@A@G@G@G@@@G@G@G@@@G@G@D@@@@@@@@@@B*****(@B*****(@@@@@@@@@@@@@@@@H@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@C@@@@O??0O??0G'''' G''''!!G'''' G'''' G'''' G'''' G'''' G'''' G''''!!G''''!!G''& G'''' O??0O??2@@@@@@@@@@@@') ; yourself); yourself]! !

!UIPainter class methodsFor:'interface specs'!

dialogSpecForDefiningClassAndSelector
    "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:UIPainter andSelector:#dialogSpecForDefiningClassAndSelector
     UIPainter new openInterface:#dialogSpecForDefiningClassAndSelector
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #window: 
           #(#WindowSpec
              #name: 'GUI Painter'
              #layout: #(#LayoutFrame 575 0 296 0 921 0 455 0)
              #label: 'GUI Painter'
              #min: #(#Point 10 10)
              #max: #(#Point 1152 900)
              #bounds: #(#Rectangle 575 296 922 456)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#FramedBoxSpec
                    #name: 'FramedBox'
                    #layout: #(#LayoutFrame 0 0.0 3 0.0 0 1.0 -35 1.0)
                    #component: 
                     #(#SpecCollection
                        #collection: 
                         #(
                           #(#LabelSpec
                              #name: 'selectorLabel'
                              #layout: #(#AlignmentOrigin 77 0.11 39 0 1 0.5)
                              #label: 'Selector:'
                              #adjust: #right
                              #resizeForLabel: true
                          )
                           #(#InputFieldSpec
                              #name: 'methodNameField'
                              #layout: #(#LayoutFrame 80 0.11 28 0 14 1.0 50 0)
                              #tabable: true
                              #model: #methodNameChannel
                          )
                           #(#LabelSpec
                              #name: 'classLabel'
                              #layout: #(#AlignmentOrigin 77 0.11 64 0 1 0.5)
                              #label: 'Class:'
                              #adjust: #right
                              #resizeForLabel: true
                          )
                           #(#InputFieldSpec
                              #name: 'classNameField'
                              #layout: #(#LayoutFrame 80 0.11 53 0 14 1.0 75 0)
                              #tabable: true
                              #model: #classNameChannel
                          )
                           #(#LabelSpec
                              #name: 'superClassLabel'
                              #layout: #(#AlignmentOrigin 77 0.11 89 0 1 0.5)
                              #label: 'Superclass:'
                              #adjust: #right
                              #resizeForLabel: true
                          )
                           #(#ComboBoxSpec
                              #name: 'superclassNameComboBox'
                              #layout: #(#LayoutFrame 80 0.11 78 0 14 1.0 100 0)
                              #tabable: true
                              #model: #superclassNameChannel
                              #comboList: #superclassNameDefaults
                          )
                        )
                    )
                    #label: 'Define Class And Selector'
                    #labelPosition: #topLeft
                )
                 #(#UISubSpecification
                    #name: 'subSpec'
                    #layout: #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1)
                    #majorKey: #ToolApplicationModel
                    #minorKey: #windowSpecForCommitWithoutChannels
                )
              )
          )
      )
!

dialogSpecForDefiningGridParameters
    "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:UIPainter andSelector:#dialogSpecForDefiningGridParameters
     UIPainter new openInterface:#dialogSpecForDefiningGridParameters
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #window: 
           #(#WindowSpec
              #name: 'GUI Painter'
              #layout: #(#LayoutFrame 575 0 296 0 856 0 493 0)
              #label: 'GUI Painter'
              #min: #(#Point 10 10)
              #max: #(#Point 1280 1024)
              #bounds: #(#Rectangle 575 296 857 494)
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#FramedBoxSpec
                    #name: 'FramedBox'
                    #layout: #(#LayoutFrame 0 0.0 3 0.0 0 1.0 -35 1.0)
                    #component: 
                     #(#SpecCollection
                        #collection: 
                         #(
                           #(#CheckBoxSpec
                              #name: 'ShowGridCheckBox'
                              #layout: #(#Point 23 24)
                              #model: #showGrid
                              #label: 'Show Grid'
                          )
                           #(#CheckBoxSpec
                              #name: 'AlignCheckBox'
                              #layout: #(#Point 23 52)
                              #model: #alignToGrid
                              #label: 'Align to Grid'
                          )
                           #(#LabelSpec
                              #name: 'HorizontalPixelsLabel'
                              #layout: #(#AlignmentOrigin 148 0 99 0 1 0.5)
                              #label: 'Horizontal Pixels:'
                              #adjust: #right
                              #resizeForLabel: true
                          )
                           #(#InputFieldSpec
                              #name: 'HorizontalPixelsField'
                              #layout: #(#LayoutFrame 154 0 87 0 207 0 109 0)
                              #model: #hspace
                              #type: #numberOrNil
                          )
                           #(#LabelSpec
                              #name: 'VerticalPixelsLabel'
                              #layout: #(#AlignmentOrigin 149 0 124 0 1 0.5)
                              #label: 'Vertical Pixels:'
                              #adjust: #right
                              #resizeForLabel: true
                          )
                           #(#InputFieldSpec
                              #name: 'VerticalPixelsField'
                              #layout: #(#LayoutFrame 154 0 112 0 207 0 134 0)
                              #model: #vspace
                              #type: #numberOrNil
                          )
                        )
                    )
                    #label: 'Grid Parameter'
                    #labelPosition: #topLeft
                )
                 #(#UISubSpecification
                    #name: 'subSpec'
                    #layout: #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1)
                    #majorKey: #ToolApplicationModel
                    #minorKey: #windowSpecForCommitWithoutChannels
                )
              )
          )
      )
!

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:UIPainter andSelector:#windowSpec
     UIPainter new openInterface:#windowSpec
     UIPainter open
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #window: 
           #(#WindowSpec
              #name: 'GUI Painter'
              #layout: #(#LayoutFrame 50 0 310 0 579 0 796 0)
              #label: 'GUI Painter'
              #min: #(#Point 10 10)
              #max: #(#Point 1160 870)
              #bounds: #(#Rectangle 50 310 580 797)
              #menu: #menu
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#MenuPanelSpec
                    #name: 'menuToolbarView'
                    #layout: #(#LayoutFrame -1 0.0 0 0 -1 1.0 32 0)
                    #tabable: true
                    #menu: #menuToolbar
                )
                 #(#VariableHorizontalPanelSpec
                    #name: 'hpanel'
                    #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
                    #component: 
                     #(#SpecCollection
                        #collection: 
                         #(
                           #(#ArbitraryComponentSpec
                              #name: 'treeView'
                              #tabable: true
                              #menu: #menuEdit
                              #hasHorizontalScrollBar: true
                              #hasVerticalScrollBar: true
                              #miniScrollerHorizontal: true
                              #miniScrollerVertical: true
                              #component: #treeView
                              #hasBorder: false
                          )
                           #(#ViewSpec
                              #name: 'specHolderView'
                              #component: 
                               #(#SpecCollection
                                  #collection: 
                                   #(
                                     #(#MenuPanelSpec
                                        #name: 'menuToolbar2View'
                                        #layout: #(#LayoutFrame -1 0.0 -2 0 -1 1.0 30 0)
                                        #enableChannel: #canMoveOrAlignSelection
                                        #tabable: true
                                        #menu: #menuToolbar2
                                    )
                                     #(#NoteBookViewSpec
                                        #name: 'noteBook'
                                        #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -30 1.0)
                                        #enableChannel: #enableChannel
                                        #tabable: true
                                        #model: #tabModel
                                        #menu: #tabList
                                        #style: #(#FontDescription #helvetica #medium #roman 10)
                                        #canvas: #noteBookView
                                    )
                                     #(#HorizontalPanelViewSpec
                                        #name: 'horizontalPanelView1'
                                        #layout: #(#LayoutFrame -163 1 -1 0 -35 1.0 31 0)
                                        #component: 
                                         #(#SpecCollection
                                            #collection: 
                                             #(
                                               #(#ArrowButtonSpec
                                                  #name: 'MoveLeftButton'
                                                  #activeHelpKey: #changePositionLeft
                                                  #tabable: true
                                                  #model: #moveSelectionLeft
                                                  #enableChannel: #canMoveOrAlignSelection
                                                  #isTriggerOnDown: true
                                                  #direction: #left
                                                  #extent: #(#Point 32 32)
                                              )
                                               #(#ArrowButtonSpec
                                                  #name: 'MoveRightButton'
                                                  #activeHelpKey: #changePositionRight
                                                  #model: #moveSelectionRight
                                                  #enableChannel: #canMoveOrAlignSelection
                                                  #isTriggerOnDown: true
                                                  #direction: #right
                                                  #extent: #(#Point 32 32)
                                              )
                                               #(#ArrowButtonSpec
                                                  #name: 'MoveDownButton'
                                                  #activeHelpKey: #changePositionDown
                                                  #model: #moveSelectionDown
                                                  #enableChannel: #canMoveOrAlignSelection
                                                  #isTriggerOnDown: true
                                                  #direction: #down
                                                  #extent: #(#Point 32 32)
                                              )
                                               #(#ArrowButtonSpec
                                                  #name: 'MoveUpButton'
                                                  #activeHelpKey: #changePositionUp
                                                  #model: #moveSelectionUp
                                                  #enableChannel: #canMoveOrAlignSelection
                                                  #isTriggerOnDown: true
                                                  #direction: #up
                                                  #extent: #(#Point 32 32)
                                              )
                                            )
                                        )
                                        #horizontalLayout: #fit
                                        #verticalLayout: #fit
                                        #horizontalSpace: 0
                                        #verticalSpace: 0
                                    )
                                     #(#ActionButtonSpec
                                        #name: 'openSpecDocumentationButton'
                                        #layout: #(#LayoutFrame -32 1 -1 0 0 1 31 0)
                                        #activeHelpKey: #editOpenSpecDocumentation
                                        #hasCharacterOrientedLabel: false
                                        #label: 'helpIcon'
                                        #model: #openSpecDocumentation
                                    )
                                     #(#ActionButtonSpec
                                        #name: 'cancelButton'
                                        #layout: #(#LayoutFrame 2 0 -26 1 -1 0.5 -2 1)
                                        #activeHelpKey: #cancel
                                        #label: 'Cancel'
                                        #tabable: true
                                        #model: #cancel
                                        #enableChannel: #modifiedChannel
                                    )
                                     #(#ActionButtonSpec
                                        #name: 'acceptButton'
                                        #layout: #(#LayoutFrame 1 0.5 -26 1 -2 1 -2 1)
                                        #activeHelpKey: #accept
                                        #label: 'OK'
                                        #tabable: true
                                        #model: #accept
                                        #enableChannel: #modifiedChannel
                                    )
                                  )
                              )
                              #borderWidth: 1
                          )
                        )
                    )
                    #level: 1
                    #handles: #(#Any 0.318868 1.0)
                )
                 #(#UISubSpecification
                    #name: 'infoBarSubSpec'
                    #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
                    #majorKey: #ToolApplicationModel
                    #minorKey: #windowSpecForInfoBar
                )
              )
          )
      )
!

windowSpecWithTranscriptHelp
    "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:UIPainter andSelector:#windowSpecWithTranscriptHelp
     UIPainter new openInterface:#windowSpecWithTranscriptHelp
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #window: 
           #(#WindowSpec
              #name: 'GUI Painter'
              #layout: #(#LayoutFrame 575 0 296 0 1127 0 833 0)
              #label: 'GUI Painter'
              #min: #(#Point 10 10)
              #max: #(#Point 1160 870)
              #bounds: #(#Rectangle 575 296 1128 834)
              #menu: #menu
              #usePreferredExtent: false
          )
          #component: 
           #(#SpecCollection
              #collection: 
               #(
                 #(#MenuPanelSpec
                    #name: 'menuToolbarView'
                    #layout: #(#LayoutFrame -1 0.0 0 0 -1 1.0 32 0)
                    #tabable: true
                    #menu: #menuToolbar
                )
                 #(#VariableVerticalPanelSpec
                    #name: 'vpanel'
                    #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
                    #component: 
                     #(#SpecCollection
                        #collection: 
                         #(
                           #(#VariableHorizontalPanelSpec
                              #name: 'hpanel'
                              #component: 
                               #(#SpecCollection
                                  #collection: 
                                   #(
                                     #(#ArbitraryComponentSpec
                                        #name: 'treeView'
                                        #tabable: true
                                        #menu: #menuEdit
                                        #hasHorizontalScrollBar: true
                                        #hasVerticalScrollBar: true
                                        #miniScrollerHorizontal: true
                                        #miniScrollerVertical: true
                                        #component: #treeView
                                        #hasBorder: false
                                    )
                                     #(#ViewSpec
                                        #name: 'specHolderView'
                                        #component: 
                                         #(#SpecCollection
                                            #collection: 
                                             #(
                                               #(#MenuPanelSpec
                                                  #name: 'menuToolbar2View'
                                                  #layout: #(#LayoutFrame -1 0.0 -2 0 -1 1.0 30 0)
                                                  #enableChannel: #canMoveOrAlignSelection
                                                  #tabable: true
                                                  #menu: #menuToolbar2
                                              )
                                               #(#NoteBookViewSpec
                                                  #name: 'noteBook'
                                                  #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -30 1.0)
                                                  #enableChannel: #enableChannel
                                                  #tabable: true
                                                  #model: #tabModel
                                                  #menu: #tabList
                                                  #style: #(#FontDescription #helvetica #medium #roman 10)
                                                  #canvas: #noteBookView
                                              )
                                               #(#HorizontalPanelViewSpec
                                                  #name: 'horizontalPanelView1'
                                                  #layout: #(#LayoutFrame -128 1 -1 0 0 1.0 31 0)
                                                  #component: 
                                                   #(#SpecCollection
                                                      #collection: 
                                                       #(
                                                         #(#ArrowButtonSpec
                                                            #name: 'MoveLeftButton'
                                                            #activeHelpKey: #changePositionLeft
                                                            #tabable: true
                                                            #model: #moveSelectionLeft
                                                            #enableChannel: #canMoveOrAlignSelection
                                                            #isTriggerOnDown: true
                                                            #direction: #left
                                                            #extent: #(#Point 32 32)
                                                        )
                                                         #(#ArrowButtonSpec
                                                            #name: 'MoveRightButton'
                                                            #activeHelpKey: #changePositionRight
                                                            #model: #moveSelectionRight
                                                            #enableChannel: #canMoveOrAlignSelection
                                                            #isTriggerOnDown: true
                                                            #direction: #right
                                                            #extent: #(#Point 32 32)
                                                        )
                                                         #(#ArrowButtonSpec
                                                            #name: 'MoveDownButton'
                                                            #activeHelpKey: #changePositionDown
                                                            #model: #moveSelectionDown
                                                            #enableChannel: #canMoveOrAlignSelection
                                                            #isTriggerOnDown: true
                                                            #direction: #down
                                                            #extent: #(#Point 32 32)
                                                        )
                                                         #(#ArrowButtonSpec
                                                            #name: 'MoveUpButton'
                                                            #activeHelpKey: #changePositionUp
                                                            #model: #moveSelectionUp
                                                            #enableChannel: #canMoveOrAlignSelection
                                                            #isTriggerOnDown: true
                                                            #direction: #up
                                                            #extent: #(#Point 32 32)
                                                        )
                                                      )
                                                  )
                                                  #horizontalLayout: #fit
                                                  #verticalLayout: #fit
                                                  #horizontalSpace: 0
                                                  #verticalSpace: 0
                                              )
                                               #(#HorizontalPanelViewSpec
                                                  #name: 'modifyPanel'
                                                  #layout: #(#LayoutFrame 0 0.0 -30 1.0 0 1.0 0 1.0)
                                                  #component: 
                                                   #(#SpecCollection
                                                      #collection: 
                                                       #(
                                                         #(#ActionButtonSpec
                                                            #name: 'cancelButton'
                                                            #activeHelpKey: #cancel
                                                            #label: 'Cancel'
                                                            #tabable: true
                                                            #model: #cancel
                                                            #enableChannel: #modifiedChannel
                                                            #extent: #(#Point 183 24)
                                                        )
                                                         #(#ActionButtonSpec
                                                            #name: 'acceptButton'
                                                            #activeHelpKey: #accept
                                                            #label: 'OK'
                                                            #tabable: true
                                                            #model: #accept
                                                            #enableChannel: #modifiedChannel
                                                            #extent: #(#Point 183 24)
                                                        )
                                                      )
                                                  )
                                                  #horizontalLayout: #fitSpace
                                                  #verticalLayout: #fitSpace
                                                  #horizontalSpace: 3
                                                  #verticalSpace: 3
                                              )
                                            )
                                        )
                                        #borderWidth: 1
                                    )
                                  )
                              )
                              #level: 1
                              #handles: #(#Any 0.318264 1.0)
                          )
                           #(#TextEditorSpec
                              #name: 'HelpTranscript'
                              #hasHorizontalScrollBar: true
                              #hasVerticalScrollBar: true
                              #miniScrollerHorizontal: true
                              #miniScrollerVertical: true
                              #isReadOnly: true
                          )
                        )
                    )
                    #handles: #(#Any 0.880597 1.0)
                )
                 #(#UISubSpecification
                    #name: 'infoBarSubSpec'
                    #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
                    #majorKey: #ToolApplicationModel
                    #minorKey: #windowSpecForInfoBar
                )
              )
          )
      )
! !

!UIPainter 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:UIPainter andSelector:#menu
     (Menu new fromLiteralArrayEncoding:(UIPainter menu)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'About'
                #labelImage: #(#ResourceRetriever nil #menuIcon)
                #submenuChannel: #menuAbout
            )
             #(#MenuItem
                #label: 'File'
                #enabled: #enableChannel
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'New'
                          #value: #doNew
                          #activeHelpKey: #fileNew
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Load...'
                          #value: #doLoad
                          #activeHelpKey: #fileLoad
                      )
                       #(#MenuItem
                          #label: 'Load Subspec...'
                          #value: #doLoadSubspec
                          #activeHelpKey: #fileLoadSubspec
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Save'
                          #value: #doSave
                          #activeHelpKey: #fileSave
                      )
                       #(#MenuItem
                          #label: 'Save As...'
                          #value: #doSaveAs
                          #activeHelpKey: #fileSaveAs
                      )
                       #(#MenuItem
                          #label: 'Define Class And Selector...'
                          #value: #defineClassAndSelector
                          #activeHelpKey: #fileSaveAs
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Pick A Window Spec...'
                          #value: #doPickAView
                          #activeHelpKey: #filePickAnInterface
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Show Window Spec'
                          #value: #doWindowSpec
                          #activeHelpKey: #fileShowWindowSpec
                      )
                       #(#MenuItem
                          #label: 'Browse Class'
                          #value: #doBrowseClass
                          #activeHelpKey: #fileBrowseClass
                          #enabled: #hasSpecClass
                      )
                       #(#MenuItem
                          #label: 'Browse Aspect Methods'
                          #value: #doBrowseAspectMethods
                          #activeHelpKey: #fileBrowseAspectMethods
                          #enabled: #hasSpecClass
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Exit'
                          #value: #closeRequest
                          #activeHelpKey: #fileExit
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Edit'
                #submenuChannel: #menuEdit
            )
             #(#MenuItem
                #label: 'Align'
                #submenuChannel: #menuAlign
            )
             #(#MenuItem
                #label: 'Generate'
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Aspect Methods'
                          #value: #doGenerateAspectMethods
                          #activeHelpKey: #generateAspectMethods
                          #enabled: #hasSpecClass
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Hook Methods'
                          #value: #doGenerateHookMethods
                          #activeHelpKey: #generateHookMethods
                          #enabled: #hasSpecClass
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Test'
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Start Application'
                          #value: #doStartApplication
                          #activeHelpKey: #testStartApplication
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Geometry Test Mode'
                          #activeHelpKey: #testGeometryTestMode
                          #indication: #testMode:
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Settings'
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Canvas'
                          #activeHelpKey: #settingsCanvas
                          #indication: #painterShown
                      )
                       #(#MenuItem
                          #label: 'Gallery'
                          #activeHelpKey: #settingsGallery
                          #indication: #galleryShown
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Redefine Aspect Methods'
                          #activeHelpKey: #settingsRedefineAspectMethods
                          #enabled: #hasSpecClass
                          #indication: #redefineAspectMethods:
                      )
                       #(#MenuItem
                          #label: 'Transcript Help'
                          #activeHelpKey: #settingsTranscriptHelp
                          #indication: #transcriptHelp:
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Fonts'
                          #submenuChannel: #menuFont
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Undo Manager...'
                          #value: #openUndoMenu
                          #activeHelpKey: #settingsUndoManager
                      )
                       #(#MenuItem
                          #label: 'Grid Manager...'
                          #value: #gridMenu
                          #activeHelpKey: #settingsGridManager
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'History'
                #submenuChannel: #menuHistory
            )
             #(#MenuItem
                #label: 'Help'
                #startGroup: #right
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Tutorial'
                          #translateLabel: true
                          #value: #openHTMLDocument:
                          #activeHelpKey: #helpTutorial
                          #argument: 'tools/uipainter/TOP.html'
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Functions'
                          #translateLabel: true
                          #value: #openHTMLDocument:
                          #activeHelpKey: #helpTutorial
                          #argument: 'tools/uipainter/Functions.html'
                      )
                       #(#MenuItem
                          #label: 'Examples'
                          #translateLabel: true
                          #value: #openHTMLDocument:
                          #activeHelpKey: #helpTutorial
                          #argument: 'tools/uipainter/Examples.html'
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Show Help Texts'
                          #translateLabel: true
                          #activeHelpKey: #helpShowHelp
                          #indication: #showHelp:
                      )
                    ) nil
                    nil
                )
            )
          ) nil
          nil
      )
!

menuAlign
    "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:UIPainter andSelector:#menuAlign
     (Menu new fromLiteralArrayEncoding:(UIPainter menuAlign)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Left'
                #value: #alignSelectionLeft
                #activeHelpKey: #alignSelectionLeft
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignL 'Left')
            )
             #(#MenuItem
                #label: 'Right'
                #value: #alignSelectionRight
                #activeHelpKey: #alignSelectionRight
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignR 'Right')
            )
             #(#MenuItem
                #label: 'Left & Right'
                #value: #alignSelectionLeftAndRight
                #activeHelpKey: #alignSelectionLeftAndRight
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignLR 'Left & Right')
            )
             #(#MenuItem
                #label: 'Top'
                #value: #alignSelectionTop
                #activeHelpKey: #alignSelectionTop
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignT 'Top')
            )
             #(#MenuItem
                #label: 'Bottom'
                #value: #alignSelectionBottom
                #activeHelpKey: #alignSelectionBottom
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignB 'Bottom')
            )
             #(#MenuItem
                #label: 'Top & Bottom'
                #value: #alignSelectionTopAndBottom
                #activeHelpKey: #alignSelectionTopAndBottom
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #UIPainter #iconAlignTB 'Top & Bottom')
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Centered Horizontal'
                #value: #alignSelectionCenterHor
                #activeHelpKey: #alignSelectionCenterHor
                #enabled: #canMoveOrAlignSelection
            )
             #(#MenuItem
                #label: 'Centered Vertical'
                #value: #alignSelectionCenterVer
                #activeHelpKey: #alignSelectionCenterVer
                #enabled: #canMoveOrAlignSelection
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Center Horizontal In Frame'
                #value: #centerSelectionHor
                #activeHelpKey: #centerSelectionHor
                #enabled: #canMoveOrAlignSelection
            )
             #(#MenuItem
                #label: 'Center Vertical In Frame'
                #value: #centerSelectionVer
                #activeHelpKey: #centerSelectionVer
                #enabled: #canMoveOrAlignSelection
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Spread Horizontal'
                #value: #spreadSelectionHor
                #activeHelpKey: #spreadSelectionHor
                #enabled: #canMoveOrAlignSelection
            )
             #(#MenuItem
                #label: 'Spread Vertical'
                #value: #spreadSelectionVer
                #activeHelpKey: #spreadSelectionVer
                #enabled: #canMoveOrAlignSelection
            )
          ) 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:UIPainter andSelector:#menuEdit
     (Menu new fromLiteralArrayEncoding:(UIPainter menuEdit)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Undo'
                #nameKey: #undo
                #value: #undoLast
                #activeHelpKey: #editUndo
                #enabled: #hasUndoHistory
                #shortcutKeyCharacter: #Cmdu
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Cut'
                #value: #deleteSelection
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
                #shortcutKeyCharacter: #Cut
            )
             #(#MenuItem
                #label: 'Copy'
                #value: #copySelection
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
                #shortcutKeyCharacter: #Copy
            )
             #(#MenuItem
                #label: 'Paste'
                #value: #pasteBuffer
                #activeHelpKey: #pasteBuffer
                #enabled: #valueOfCanPaste
                #shortcutKeyCharacter: #Paste
            )
             #(#MenuItem
                #label: 'Delete'
                #value: #deleteTotalSelection
                #activeHelpKey: #editDelete
                #enabled: #valueOfCanCut
                #shortcutKeyCharacter: #Delete
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Paste With Layout'
                #value: #pasteWithLayout
                #activeHelpKey: #pasteWithLayout
                #enabled: #valueOfCanPasteWithKeepingLayout
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Move'
                #submenuChannel: #menuMove
            )
             #(#MenuItem
                #label: 'Dimension'
                #enabled: #hasSelection
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Default Extent'
                          #value: #setToDefaultExtent
                          #activeHelpKey: #editDimensionDefaultExtent
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Default Width'
                          #value: #setToDefaultWidth
                          #activeHelpKey: #editDimensionDefaultWidth
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Default Height'
                          #value: #setToDefaultHeight
                          #activeHelpKey: #editDimensionDefaultHeight
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Copy Layout'
                          #value: #copyLayout
                          #activeHelpKey: #editDimensionCopyLayout
                          #enabled: #hasSingleSelection
                      )
                       #(#MenuItem
                          #label: 'Copy Extent'
                          #value: #copyExtent
                          #activeHelpKey: #editDimensionCopyExtent
                          #enabled: #hasSingleSelection
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Paste Layout'
                          #value: #pasteLayout
                          #activeHelpKey: #editDimensionPasteLayout
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Extent'
                          #value: #pasteExtent
                          #activeHelpKey: #editDimensionPasteExtent
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Width'
                          #value: #pasteWidth
                          #activeHelpKey: #editDimensionPasteWidth
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Height'
                          #value: #pasteHeight
                          #activeHelpKey: #editDimensionPasteHeight
                          #enabled: #canMoveOrAlignSelection
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Open Spec Documentation'
                #value: #openSpecDocumentation
                #activeHelpKey: #editOpenSpecDocumentation
            )
             #(#MenuItem
                #label: 'Inspect Spec'
                #value: #inspectSpec
                #activeHelpKey: #editInspectSpec
            )
          ) nil
          nil
      )
!

menuMove
    "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:UIPainter andSelector:#menuMove
     (Menu new fromLiteralArrayEncoding:(UIPainter menuMove)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Up'
                #value: #doStepUp
                #activeHelpKey: #moveWidgetUp
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #ToolApplicationModel #upIcon 'Up')
            )
             #(#MenuItem
                #label: 'Down'
                #value: #doStepDown
                #activeHelpKey: #moveWidgetDown
                #enabled: #canMoveOrAlignSelection
                #labelImage: #(#ResourceRetriever #ToolApplicationModel #downIcon 'Down')
            )
             #(#MenuItem
                #label: 'Into'
                #value: #doStepIn
                #activeHelpKey: #moveWidgetInto
                #enabled: #canMoveSelectionIntoContainer
                #labelImage: #(#ResourceRetriever #ToolApplicationModel #downRightIcon 'Into')
            )
             #(#MenuItem
                #label: 'Out'
                #value: #doStepOut
                #activeHelpKey: #moveWidgetOut
                #enabled: #canMoveSelectionOutOfContainer
                #labelImage: #(#ResourceRetriever #ToolApplicationModel #leftDownIcon 'Out')
            )
          ) 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:UIPainter andSelector:#menuToolbar
     (Menu new fromLiteralArrayEncoding:(UIPainter menuToolbar)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Start'
                #isButton: true
                #value: #doStartApplication
                #activeHelpKey: #testStartApplication
                #labelImage: #(#ResourceRetriever nil #startIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'New'
                #isButton: true
                #value: #doNew
                #activeHelpKey: #fileNew
                #labelImage: #(#ResourceRetriever nil #newIcon)
            )
             #(#MenuItem
                #label: 'Load'
                #isButton: true
                #value: #doLoad
                #activeHelpKey: #fileLoad
                #labelImage: #(#ResourceRetriever nil #loadIcon)
            )
             #(#MenuItem
                #label: 'Save'
                #isButton: true
                #value: #doSave
                #activeHelpKey: #fileSave
                #labelImage: #(#ResourceRetriever nil #saveIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Cut'
                #isButton: true
                #value: #deleteSelection
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever nil #cutIcon)
            )
             #(#MenuItem
                #label: 'Copy'
                #isButton: true
                #value: #copySelection
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
                #labelImage: #(#ResourceRetriever nil #copyIcon)
            )
             #(#MenuItem
                #label: 'Paste With Layout'
                #isButton: true
                #value: #pasteWithLayout
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPasteWithKeepingLayout
                #labelImage: #(#ResourceRetriever nil #pasteIcon)
            )
             #(#MenuItem
                #label: 'Delete'
                #isButton: true
                #value: #deleteTotalSelection
                #activeHelpKey: #editDelete
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever nil #deleteIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Move Up'
                #isButton: true
                #value: #doStepUp
                #activeHelpKey: #moveWidgetUp
                #enabled: #canChangeOrderInContainer
                #labelImage: #(#ResourceRetriever nil #upIcon)
            )
             #(#MenuItem
                #label: 'Move Down'
                #isButton: true
                #value: #doStepDown
                #activeHelpKey: #moveWidgetDown
                #enabled: #canChangeOrderInContainer
                #labelImage: #(#ResourceRetriever nil #downIcon)
            )
             #(#MenuItem
                #label: 'Move Into'
                #isButton: true
                #value: #doStepIn
                #activeHelpKey: #moveWidgetInto
                #enabled: #canMoveSelectionIntoContainer
                #labelImage: #(#ResourceRetriever nil #downRightIcon)
            )
             #(#MenuItem
                #label: 'Move Out'
                #isButton: true
                #value: #doStepOut
                #activeHelpKey: #moveWidgetOut
                #enabled: #canMoveSelectionOutOfContainer
                #labelImage: #(#ResourceRetriever nil #leftDownIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Canvas'
                #activeHelpKey: #settingsCanvas
                #indication: #painterShown
            )
             #(#MenuItem
                #label: 'Gallery'
                #activeHelpKey: #settingsGallery
                #indication: #galleryShown
            )
          ) nil
          nil
      )
!

menuToolbar2
    "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:UIPainter andSelector:#menuToolbar2
     (Menu new fromLiteralArrayEncoding:(UIPainter menuToolbar2)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Align Left'
                #isButton: true
                #value: #alignSelectionLeft
                #activeHelpKey: #alignSelectionLeft
                #labelImage: #(#ResourceRetriever nil #iconAlignL)
            )
             #(#MenuItem
                #label: 'Align Right'
                #isButton: true
                #value: #alignSelectionRight
                #activeHelpKey: #alignSelectionRight
                #labelImage: #(#ResourceRetriever nil #iconAlignR)
            )
             #(#MenuItem
                #label: 'Align Left & Right'
                #isButton: true
                #value: #alignSelectionLeftAndRight
                #activeHelpKey: #alignSelectionLeftAndRight
                #labelImage: #(#ResourceRetriever nil #iconAlignLR)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Align Top'
                #isButton: true
                #value: #alignSelectionTop
                #activeHelpKey: #alignSelectionTop
                #labelImage: #(#ResourceRetriever nil #iconAlignT)
            )
             #(#MenuItem
                #label: 'Align Bottom'
                #isButton: true
                #value: #alignSelectionBottom
                #activeHelpKey: #alignSelectionBottom
                #labelImage: #(#ResourceRetriever nil #iconAlignB)
            )
             #(#MenuItem
                #label: 'Align Top & Bottom'
                #isButton: true
                #value: #alignSelectionTopAndBottom
                #activeHelpKey: #alignSelectionTopAndBottom
                #labelImage: #(#ResourceRetriever nil #iconAlignTB)
            )
          ) nil
          nil
      )
! !

!UIPainter methodsFor:'accessing'!

redefineAspectMethods
    "redefine methods yes or no. If a method is defined in super class
     should the message be reinstalled ?
    "
    ^ UIPainterView redefineAspectMethods


!

redefineAspectMethods:aBoolean
    "redefine methods yes or no. If a method is defined in super class
     should the message be reinstalled ?
    "
    UIPainterView redefineAspectMethods:aBoolean


!

transcriptHelp
    "get whether the help transcript is turned on/off
    "
    ^self class settings at: #transcriptHelp 
        ifAbsent: [self class settings at: #transcriptHelp put: false]
!

transcriptHelp:aBoolean
    "turn on/off the help transcript
    "
    self class settings at: #transcriptHelp put: aBoolean

! !

!UIPainter methodsFor:'actions'!

accept
    "accept changes done to the specification. The component assigned to the
     specification will change immediately dependant on the attributes derived
     from the specification.
    "
    |layout spec prop key layoutTool|

    self isLayoutToolSelected ifTrue:[
        layoutTool := self layoutTool.

        (layout := layoutTool layout) notNil ifTrue:[
            layoutTool layoutType == #Extent ifTrue:[
                layoutTool layoutView == self painter topView ifTrue:[
                    layoutTool layoutView extent:layout
                ] ifFalse:[
                    self painter setExtent:layout
                ]
            ] ifFalse:[
                self painter setLayout:layout
            ]
        ]
    ] ifFalse:[
        spec := self specTool specification.

        self isHelpToolSelected ifTrue:[
            self helpTool accept.
            key  := self helpTool helpKey.
            prop := treeView propertySelected.

            prop notNil ifTrue:[
                prop spec activeHelpKey:key
            ].
            spec activeHelpKey:key.
        ] ifFalse:[
            self painter updateFromSpec:spec.
        ]
    ].             
    self modifiedChannel value:false.
    modified := true.
!

addWidget: aSpecClass

    self addWidgetOfSpec: (Array with: (Smalltalk at: aSpecClass) new)

!

addWidgetOfSpec: aSpec

    |newSel|  
    (newSel := self pasteSpecifications:aSpec keepLayout:false at:0@0) notNil
    ifTrue:
    [
        self select: newSel
    ]
    ifFalse:
    [   
        ((treeView selection size = 0) or: [treeView selectedNode isNil])
        ifTrue:
        [                          
            treeView selection: #(1).
        ]
        ifFalse:
        [  
            treeView selectNode: (treeView detectNode: [:n| n = treeView selectedNode parent])
        ].
        self addWidgetOfSpec: aSpec
    ]

!

cancel
    "cancel all changes done to the specification; reread attributes from the
     assigned component
    "
    |spec key view|

    self isModified ifTrue:[
        (spec := self painter specForSelection) notNil ifTrue:[
            key := spec activeHelpKey.
        ].
        self helpTool helpKey:key.
        self specTool specification:spec.
        view := self layoutTool layoutView.

        self setViewInLayoutTool:view.
        spec class == DataSetSpec ifTrue:[
            view columnDescriptors:(spec columns)
        ].        
        self modifiedChannel value:false.
        modified := false
    ]
!

inspectSpec
    "inspect the selected specification"

    |spec|

    (spec := self painter specForSelection) isNil ifTrue:[
        treeView isCanvasSelected ifTrue:[
            spec := treeView canvasSpec.
        ]
    ].
    spec notNil ifTrue:[
        spec inspect
    ]

    "Created: / 10.3.1998 / 18:11:42 / stefan"
    "Modified: / 10.3.1998 / 18:19:55 / stefan"
!

moveSelectionDown
    "move selected components down
    "
    self painter moveSelectionDown
!

moveSelectionLeft
    "move selected components left
    "
    self painter moveSelectionLeft

!

moveSelectionRight
    "move selected components right
    "
    self painter moveSelectionRight

!

moveSelectionUp
    "move selected components up
    "
    self painter moveSelectionUp

!

openSpecDocumentation
    "open documentation for the selected specification"

    |spec|

    (spec := self painter specForSelection) isNil ifTrue:[
        treeView isCanvasSelected ifTrue:[
            spec := treeView canvasSpec.
        ]
    ].
    spec notNil ifTrue:[
        HTMLDocumentView openFullOnDocumentationFile: 'tools/uipainter/', spec userFriendlyName,'.html'
    ]
! !

!UIPainter methodsFor:'aspects'!

aspectFor:aKey
    "aspect for a key
    "
  ^ aspects at:aKey ifAbsent:[ super aspectFor:aKey ]
!

canChangeOrderInContainer
    "returns a boolean value holder which is true if the component order can be changed within their container.
    "
    ^ builder booleanValueAspectFor:#canChangeOrderInContainer
!

canMoveOrAlignSelection
    "returns a boolean value holder which is true in case that any selection exists
     and all widgets in the selection can change its layout through to a move or
     align operation
    "
    ^ builder booleanValueAspectFor:#canMoveOrAlignSelection
!

canMoveSelectionIntoContainer
    "returns a boolean value holder which is true in case that one component is selected
     and can change its container widget to the next element in the list which will have
     the same container.
    "
    ^ builder booleanValueAspectFor:#canMoveSelectionIntoContainer
!

canMoveSelectionOutOfContainer
    "returns a boolean value holder which is true in case that one component is selected
     which is contained within another component
    "
    ^ builder booleanValueAspectFor:#canMoveSelectionOutOfContainer
!

enableChannel
    "true if modifications are allowed otherwise running test
    "
  ^ self painter enableChannel
!

galleryShown
    "returns a boolean value holder which is set to true if the gallery is shown
    "
    |holder|

    (holder := builder bindingAt:#galleryShown) isNil ifTrue:[
        builder aspectAt:#galleryShown put:(holder :=  true asValue).
        holder addDependent:self
    ].
    ^ holder

!

hasOneSelectionOtherThanCanvas
    "returns a value holder which is true in case that one component is selected
     other than the canvas.
    "               
    ^ builder booleanValueAspectFor:#hasOneSelectionOtherThanCanvas
!

modifiedChannel
    "returns a boolean value holder which is set to true if something is modified
     and not accepted
    "
    ^ builder booleanValueAspectFor:#modifiedChannel
!

noteBookView
    "returns the notebook view; initialize components within the notebook
    "
    |noteBook channel helpTool layoutTool specTool|

    (noteBook := builder bindingAt:#noteBookView) isNil ifTrue:[
        noteBook   := View new.
        layoutTool := UILayoutTool new.
        helpTool   := UIHelpTool   new.
        helpTool helpSpecFrom:specClass.
        specTool   := UISpecificationTool new.
        channel    := self modifiedChannel.

        layoutTool masterApplication:self.
        specTool   masterApplication:self.
        helpTool   masterApplication:self.

        layoutCanvas := SubCanvas origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        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.

        layoutCanvas client:layoutTool.
        helpCanvas   client:helpTool.
        specTool builder:(specCanvas client:specTool).

        layoutTool masterApplication:self.
        specTool   masterApplication:self.
        helpTool   masterApplication:self.

        layoutTool modifiedHolder:channel.
        helpTool   modifiedHolder:channel.
        specTool   modifiedHolder:channel.

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

painterShown
    "returns a boolean value holder which is set to true if the painter is shown
    "
    |holder|

    (holder := builder bindingAt:#painterShown) isNil ifTrue:[
        builder aspectAt:#painterShown put:(holder :=  true asValue).
        holder addDependent:self
    ].
    ^ holder

!

tabList
    "returns a value holder which keeps a list of labels assigned to the tabs
    "
    |holder|

    (holder := builder bindingAt:#tabList) isNil ifTrue:[
        builder aspectAt:#tabList put:(holder :=  ValueHolder new).
        holder value:#( 'Properties' ).
    ].
    ^ holder
!

tabModel
    "returns a value holder which keeps the current name of the tab selected
    "
    |holder|

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

treeView
    "returns the selection tree view which holds all widget identifiers
    "
    ^ treeView
!

valueOfCanPasteWithKeepingLayout

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



! !

!UIPainter methodsFor:'building editors'!

openDataSetColumnEditor
    "opens a column editor
    "
    |cls aspect editor columns|

    cls := self resolveName:specClass.

    cls isNil ifTrue:[
        ^ self information:'No application class defined yet!!'
    ].
    aspect := self specTool specification columns.

    editor := DataSetBuilder new.
    editor masterApplication:self.
    editor columns:aspect fromView:(self layoutTool layoutView).
    editor rowClassName:(self specTool specification rowClassName).
    editor openModal.

    editor hasChanged ifTrue:[
        self specTool specification columns:(editor columns).
        self specTool specification rowClassName:(editor rowClassName).
        self modifiedChannel value:true.
    ].
!

openEditMenu
    "opens a menu editor on current widget
    "
    |cls selectorOrMenu editor selectedSpec|

    cls := self resolveName:specClass.

    cls isNil ifTrue:[
        ^ self warn:'No application class defined yet!!'
    ].

    cls notNil ifTrue:[
        (selectorOrMenu := self specTool specification menuSelector) notNil ifTrue:[
            selectorOrMenu := selectorOrMenu asSymbol
        ] ifFalse:[
            "/ cg: q&d hack ...

            (selectedSpec := treeView propertySelected) notNil ifTrue:[
                Object errorSignal handle:[:ex |
                    selectorOrMenu := nil.
                ] do:[
                    selectorOrMenu := selectedSpec view asMenu.
                ]
            ].
        ].

        editor := MenuEditor new.
        editor masterApplication:self.
        editor specClass: cls.
        editor useHelpTool: self helpTool. 
        selectorOrMenu class ~~ Menu
            ifTrue:  [editor openModalOnClass:cls andSelector:selectorOrMenu]
            ifFalse: [editor openModalOnMenu:selectorOrMenu].
        self helpTool updateList.

        editor specSelector ~= selectorOrMenu ifTrue:[
            editor hasSaved ifTrue:[
                self specTool specification menuSelector:editor specSelector.
                self modifiedChannel value:true.
                self accept
            ]
        ].
    ]

    "Modified: 31.7.1997 / 14:26:13 / cg"
!

openHierarchicalListEditor
    "opens a hierarchical list editor editor on current widget
    "
    |cls aspect editor|

    cls := self resolveName:specClass.

    cls isNil ifTrue:[
        ^ self information:'No application class defined yet!!'
    ].

    (aspect := self specTool specification hierarchicalList) notNil ifTrue:[
        aspect := aspect asSymbol
    ].

    editor := HierarchicalListEditor new.
    editor masterApplication:self.
    editor openModalOnClass:cls andSelector:aspect.

    editor specSelector ~= aspect ifTrue:[
        editor hasSaved ifTrue:[
            self specTool specification hierarchicalList:editor specSelector.
            self modifiedChannel value:true.
            self accept
        ]
    ]
!

openSubSpecGUIPainter
    "opens a GUI Painter on the current subspecification"

    |spec cls meta sel|

    spec := self specTool specification.
    cls := spec majorKey.
    cls isNil ifTrue:[
        cls := specClass.
    ].
    (cls isNil or:[(cls := self resolveName:cls) isNil]) ifTrue:[
        spec majorKey isNil ifTrue:[
            ^ self warn:'Cannot find class (no majorKey specified)'.
        ].
        ^ self warn:'Cannot find class ', spec majorKey asBoldText, '!!'.
    ].
    sel := spec minorKey.
    meta := cls class whichClassIncludesSelector:sel.
    meta isNil ifTrue:[
        ^ self warn:'Cannot find selector #', (sel ? '') asBoldText, ' in class ', cls name asBoldText, '!!'
    ].

    self class openOnClass:meta soleInstance andSelector:spec minorKey.

    "Created: / 6.2.1998 / 13:03:59 / stefan"
    "Modified: / 6.2.1998 / 13:59:30 / stefan"
!

openTabListEditor
    "open a TabListEditor
    "
    |cls aspect editor columns|

    cls := self resolveName:specClass.

    cls isNil ifTrue:[
        ^ self information:'No application class defined yet!!'
    ].
    aspect := self specTool specification listSelector.

    editor := TabListEditor new.
    editor masterApplication:self.
    editor openModalOnClass:cls andSelector:aspect.

    editor specSelector ~= aspect ifTrue:[
        editor hasSaved ifTrue:[
            self specTool specification listSelector:(editor specSelector).
            self modifiedChannel value:true.
            self accept.
        ]
    ]
! !

!UIPainter methodsFor:'change & update'!

layoutChanged
    "called by the painter/canvas whenever the layout of the current selected
     widget changed
    "
    self isModified ifFalse:[
        self layoutTool update.
        self modifiedChannel value:false
    ]
!

propertyChanged
    "called by the painter/canvas whenever the property of the current selected
     widget changed
    "
    |p|

    (p := treeView propertySelected) notNil ifTrue:[
        self specTool specification:(p spec copy).
        self setViewInLayoutTool:(p view).
        self modifiedChannel value:false
    ] ifFalse:[
        self layoutTool layoutView notNil ifTrue:[
            self modifiedChannel value:false.
            self treeSelection
        ]
    ]
!

update:something with:aParameter from:someObject
    "catch change notifications
    "
    someObject == treeView model ifTrue:[
        (something == #selection
        or:[something == #selectionIndex]) ifTrue:[self treeSelection].
      ^ self
    ].

    self galleryShown == someObject ifTrue:[
        (self galleryShown value) ifTrue:[
            self raiseUIView:(selectionPanel window)
        ] ifFalse:[
            self hideUIView:(selectionPanel window)
        ].
      ^ self
    ].

    self painterShown == someObject ifTrue:[
        (self painterShown value) ifTrue:[
            self raiseUIView:(self painter topView)
        ] ifFalse:[
            self hideUIView:(self painter topView)
        ].
      ^ self
    ].

    "Modified: / 29.10.1997 / 17:48:19 / cg"
! !

!UIPainter methodsFor:'event handling'!

doesNotUnderstand:aMessage

    |painter|

    painter := self painter.

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

! !

!UIPainter methodsFor:'help'!

defaultInfoLabel

    specClass isNil ifTrue: [^'No class and selector defined.'].
    ^specClass printString, ' >> ', specSelector
!

show:aHelpText

    (self transcriptHelp and: [transcript notNil])
    ifFalse:
    [
        super showHelp:aHelpText for:self
    ]
    ifTrue:
    [
        transcript hideCursor; contents:aHelpText
    ]    
!

showHelp:aHelpText for:view
    "display active help texts in my own info area."

    (self transcriptHelp and: [transcript notNil])
    ifFalse:
    [
        ^super showHelp:aHelpText for:view.
    ]
    ifTrue:
    [
        |txt|
        aHelpText isNil ifTrue:[
            txt := nil
        ] ifFalse:[
            txt := self class 
                    convertString:(aHelpText asString)
                    maxLineSize:(transcript width // transcript font width)
                    skipLineFeed:true
        ].
        transcript hideCursor; contents:txt.
        ^true
    ]
! !

!UIPainter methodsFor:'private'!

askForModification
    "check interface modification
    " 

    self treeSelection. "accept modifications"    

    (modified or: [self painter isModified or: [self helpTool modified]])
    ifTrue:
    [
        ((YesNoBox title:'Window Spec was modified!!')        
            noText:'Cancel';
            yesText:'Waste it and proceed';
            showAtPointer;
            accepted) ifFalse: [^false].
        modified := false.
        self painter resetModification
    ].
    ^true
!

checkClassAndSelector
    "check for class & superclass"

    |superclass cls|

    specClass isNil ifTrue:[^ false].

    cls := self resolveName:specClass.

    cls isNil ifTrue:[
        superclass := self resolveName:specSuperclass.

        superclass isNil ifTrue:[
            self warn:'No class named ' , specSuperclass , ' exists!!'.
            ^ false.
        ].
        (self confirm:'Create class ' , specClass asBoldText, '?') ifTrue:[
            superclass subclass:(specClass asSymbol)
                       instanceVariableNames:''
                       classVariableNames:''
                       poolDictionaries:''
                       category:'Applications'.
            ^ true.
        ].
        ^ false.
    ].
    cls isBehavior ifFalse:[
        self warn:'A global named ' , specClass , ' exists, but it is no class.'.
        ^ false.
    ].

    specSuperclass isBehavior ifFalse:[
        specSuperclass isEmpty ifFalse:[
            superclass := self resolveName:specSuperclass
        ] ifTrue:[
            specSuperclass := nil.
        ]
    ] ifTrue:[
        superclass := specSuperclass
    ].

    specSuperclass notNil ifTrue:[
        superclass isNil ifTrue:[
            self warn:'No class named ' , specSuperclass , ' exists!!'.
            ^ false.
        ].

        (cls isSubclassOf:superclass) ifFalse:[
            self information:('A global named ' , specClass , ' exists,\' ,
                              'but is not a subclass of ' , superclass name , '.\\' ,
                              'Check and try again if that is not what you want.') withCRs.
        ]
    ].

    superclass isNil ifTrue:[
        cls notNil ifTrue:[
            specSuperclass := cls superclass name
        ]
    ].

    ^ true

    "Modified: 12.8.1997 / 23:39:10 / cg"
!

checkModified
    "check interface modification
    "               
    (self isModified and: [self isModified or: [self helpTool modified]])
    ifTrue:
    [
        ((YesNoBox title:'Window Spec was modified!!')        
            noText:'Cancel';
            yesText:'Waste it and proceed';
            showAtPointer;
            accepted) ifFalse: [^false].
        self painter resetModification
    ].
    ^true
!

defineClassAndSelector
    "launch a dialog to define class, superclass and method"

    |again tmp|

    [
        again := false.

        (tmp := specClass) isNil ifTrue:[tmp := 'NewApplication'].
        aspects at:#classNameChannel put:tmp asValue.

        (tmp := specSelector) isNil ifTrue:[tmp := 'windowSpec'].
        aspects at:#methodNameChannel put:tmp asValue.

        (tmp := specSuperclass) isNil ifTrue:[tmp := 'ApplicationModel'].
        aspects at:#superclassNameChannel put:tmp asValue.

        (self openDialogInterface:#dialogSpecForDefiningClassAndSelector) ifTrue:[

            specClass    := (self aspectFor:#classNameChannel) value.
            specSelector := (self aspectFor:#methodNameChannel) value.
            specSelector notNil ifTrue:[specSelector := specSelector asSymbol].
            specSuperclass := (self aspectFor:#superclassNameChannel) value.

            (again := self checkClassAndSelector not) ifFalse:[
                self painter className:specClass
                        superclassName:specSuperclass
                              selector:specSelector.
            ]
        ]
        ifFalse:
        [
            ^nil
        ]

    ] doWhile:[again].

    self specClass:specClass.
    self helpTool modified: true
!

gridMenu
    "open a dialog for grip parameters configuration
    "
    |hspace vspace bindings painter gridPara|

    painter  := self painter.
    bindings := IdentityDictionary new.
    gridPara := painter gridParameters copy.

    bindings at:#showGrid    put:(painter gridShown asValue).
    bindings at:#alignToGrid put:(painter gridAlign asValue).
    bindings at:#hspace      put:((gridPara at:1) asValue).
    bindings at:#vspace      put:((gridPara at:2) asValue).

    (self openDialogInterface:#dialogSpecForDefiningGridParameters withBindings:bindings) ifFalse:[
        ^ self
    ].

    hspace := (bindings at:#hspace) value ? 5.
    vspace := (bindings at:#vspace) value ? 5.

    gridPara at:1 put:hspace.
    gridPara at:2 put:vspace.
    gridPara at:5 put:hspace.
    gridPara at:6 put:vspace.

    painter gridShown:false.
    painter gridAlign:false.
    painter gridParameters:gridPara.
    painter gridAlign:(bindings at:#alignToGrid) value.
    painter gridShown:(bindings at:#showGrid) value.
    painter clear.
    painter clear.

!

hideUIView:aView
    "hide the view which is an application or top view
    "
    aView beIndependent.
    aView unmap.
!

raiseTabView

    self isLayoutToolSelected ifTrue:[
        layoutCanvas raise
    ] ifFalse:[
        self isHelpToolSelected ifTrue:[
            helpCanvas raise
        ] ifFalse:[
            self specTool selection:tabSelection.
            specCanvas raise
        ]
    ]
!

raiseUIView:aView
    "raise the view which is an application or top view
    "
    aView map.
    aView bePartner.
!

resourceMessage: aString

    (aString notNil and: [self askForModification]) 
    ifTrue:
    [            
        |msg cls sel|
        msg := aString asCollectionOfWords.
        (msg size == 2 and:
        [(cls := self resolveName:(msg at:1)) notNil])
        ifTrue:
        [
            specClass := cls name.
            specSuperclass := cls superclass name.
            specSelector := (msg at: 2) asSymbol.
            ^true
        ]
    ].
    ^false
!

setClass:cls selector:selector
    "set the application class and the selector under which the
     window specification should be stored
    "
    |clsName superClassName|

    clsName := cls name.
    superClassName := cls superclass name.

    (self aspectFor:#classNameChannel) value:clsName.
    (self aspectFor:#methodNameChannel) value:(selector ? '').
    (self aspectFor:#superclassNameChannel) value:superClassName.

    self painter 
            className:clsName 
            superclassName:superClassName
            selector:(selector ? '').

    self specClass:clsName.
    specSelector := (selector ? '').
    specSuperclass := superClassName.

    specClass notNil & selector notNil ifTrue:[
        self addToHistory: (specClass, ' ', specSelector) -> #loadFromMessage:.
        self updateInfoLabel
    ].

    "Modified: / 5.2.1998 / 09:44:58 / stefan"
!

setViewInLayoutTool:aView
    "set view for layout tool
    "
    |type|

    self painter topView == aView ifTrue:[
        type := #Extent
    ].
    self layoutTool layoutView:aView type:type

!

specClass:aClass

    specClass := aClass isBehavior ifTrue:[aClass name]
                                   ifFalse:[aClass].
    self helpTool helpSpecFrom:specClass.

    "Modified: / 5.2.1998 / 09:42:57 / stefan"
! !

!UIPainter methodsFor:'private tools'!

helpTool
    "returns the help tool
    "
    helpCanvas isNil ifTrue:[
        self noteBookView
    ].
    ^ helpCanvas application
!

layoutTool
    "returns the layout tool
    "
    layoutCanvas isNil ifTrue:[
        self noteBookView
    ].
    ^ layoutCanvas application
!

painter
    "returns the painter/canvas view
    "
    ^ treeView canvas
!

specTool
    "returns the spec tool
    "
    specCanvas isNil ifTrue:[
        self noteBookView
    ].
    ^ specCanvas application
! !

!UIPainter methodsFor:'queries'!

hasSpecClass
    "checks whether an application class is defined
    "
    ^ (self resolveName:specClass) notNil
!

hasSpecClassAndSelector
    "checks whether an application class and a selector under which
     the window specification is stored is defined.
    "
    specSelector size > 1 ifTrue:[
        ^ self hasSpecClass
    ].
  ^ false
!

isHelpToolSelected
    "returns true if current selected tab in the noteBook is assigned
     to the 'Help' tool
    "
    ^ tabSelection = UIHelpTool label

!

isLayoutToolSelected
    "returns true if current selected tab in the noteBook is assigned
     to the 'Layout' tool
    "
    ^ tabSelection = UILayoutTool label
!

isModified
    "return true if current specification or layout is modified
    "
    ^ self modifiedChannel value
!

isPainterEnabled
    "returns true if not running in test mode
    "
    ^ self painter enabled
! !

!UIPainter methodsFor:'selection'!

tabSelection
    "returns name of current selected tab in the notebook.
    "
    ^ tabSelection
!

tabSelection:something
    "the tab selection of the notebook changed
    "

    |whatToDo|

    (something isNil or:[tabSelection = something]) ifTrue:[
        ^ self
    ].

    self isModified ifTrue:[
        whatToDo := DialogBox 
                        confirmWithCancel:'Accept modifications in section ' , tabSelection printString , '?'
                        labels:#('Cancel' 'Ignore' 'Accept')
                        default:3.
        whatToDo isNil ifTrue:[^self].
        whatToDo == true ifTrue:[
            self accept
        ] ifFalse:[
            self cancel
        ]
    ].

    tabSelection := something.
    self raiseTabView.
    self cancel.

!

treeSelection
    "called whenever the selection of the treeview changed
    "
    |view list spec slices size property tabComponent canCutOrCopy canPaste clipboard sel|

    self isModified ifTrue:[
        (self confirm:'Accept modifications in section ' , tabSelection printString asBoldText, '?') ifTrue:[
            self accept
        ]
    ].

    self canMoveOrAlignSelection        value:(treeView canMoveOrAlignSelection).
    self canChangeOrderInContainer      value:(treeView canChangeOrderInContainer).
    self canMoveSelectionIntoContainer  value:(treeView canMoveSelectionIntoContainer).
    self canMoveSelectionOutOfContainer value:(treeView canMoveSelectionOutOfContainer).
    self hasOneSelectionOtherThanCanvas value:(treeView hasOneSelectionOtherThanCanvas).

    treeView isCanvasSelected ifTrue:[
        spec := treeView canvasSpec.
        view := self painter topView.
    ] ifFalse:[
        (property := treeView propertySelected) notNil ifTrue:[
            treeView canResizeSelectedWidget ifTrue:[
                view := property view.
            ].
            spec := property spec copy.
        ]
    ].
    tabComponent := builder componentAt:#noteBook.
    self setViewInLayoutTool:view.
    self specTool specification:spec.

    spec notNil ifTrue:[
        self helpTool helpKey:(spec activeHelpKey).
        slices := spec class slices.
        size   := slices size.

        view notNil ifTrue:[
            list := Array new:(size + 2).
            list at:(size + 2) put:(UILayoutTool label).
        ] ifFalse:[
            list := Array new:(size + 1).
        ].
        1 to:size do:[:i| list at:i put:((slices at:i) first asString)].
        list at:(size + 1) put:(UIHelpTool   label).

        self tabList value:list.
        self show:(spec class name).
        tabComponent enabled:true.

        (tabSelection := tabComponent selection) isNil ifTrue:[
            tabComponent setSelection:(tabSelection := list first)
        ].
        self raiseTabView
    ] ifFalse:[
        self helpTool helpKey:nil.
        tabComponent enabled:false.
        self show:nil.
    ].
    self modifiedChannel value:false.

    treeView notNil
    ifTrue:
    [
        canCutOrCopy := treeView selection size >= 1 and:[treeView selection first ~~ 1].
        clipboard := self getSelection.

        clipboard isCollection ifTrue:[clipboard notEmpty ifTrue:[sel := clipboard first]]
                              ifFalse:[sel := clipboard].

        canPaste := (sel isKindOf:UISpecification) and:
                    [treeView selection size  = 1 
                    and:[treeView selection first == 1 
                    or: [self canPasteInto: treeView selectedNode contents view]]]
    ].

    self valueOfCanCut value: canCutOrCopy.
    self valueOfCanCopy value: canCutOrCopy.
    self valueOfCanPaste value: canPaste.             
    self valueOfCanPasteWithKeepingLayout value: (canPaste &  self canKeepLayoutInSelection).


! !

!UIPainter methodsFor:'startup / release'!

closeRequest
    "close all windows open by builder
    "

    self askForModification ifFalse:[^self].

    treeView model removeDependent:self.
    self painter release.
    ColorMenu releaseResources.

    selectionPanel notNil ifTrue:[
        selectionPanel masterApplication:nil.
        selectionPanel closeRequest
    ].
    selectionPanel := nil.
    treeView       := nil.

    ActiveHelp stopFor:self.

    super closeRequest.

    "Modified: / 27.10.1997 / 00:01:30 / cg"
!

closeRequestFor:aTopView
    "handle a close request for a specific view
    "
    |topView|

    topView := self window.

    topView == aTopView ifTrue:[
        super closeRequestFor:aTopView
    ] ifFalse:[
        aTopView = selectionPanel window ifTrue:[
            self galleryShown value:false
        ] ifFalse:[
            aTopView == (self painter topView) ifTrue:[
                self painterShown value:false
            ] ifFalse:[
                aTopView closeRequest
            ]
        ].
        topView raise.
    ].
!

loadFromMessage: aMessage

    ((aMessage size > 0) and: [self askForModification])
    ifTrue:
    [
        |readStream aClass aSelector|
        readStream := aMessage readStream.
        (aClass := Smalltalk at: (readStream upTo: $ ) asSymbol) notNil
        ifTrue:
        [
            aSelector :=  readStream upToEnd asSymbol.
            self setClass: aClass selector: aSelector.
            (aClass respondsTo:aSelector) 
            ifTrue:
            [
                self painter setupFromSpec:(aClass perform:aSelector).
                treeView selection: #(1). 
            ]
        ]
    ]
!

openInterface:aSymbol
    "open interfaces
    "
    |painterView painter cls topView|

    modified := false.

    aspects := IdentityDictionary new.

    aspects at:#classNameChannel put:(
        (specClass notNil ifTrue:[specClass]
                         ifFalse:['NewApplication']) asValue
    ).
    specSuperclass isNil ifTrue:[
        specClass notNil ifTrue:[
            (cls := self resolveName:specClass) notNil ifTrue:[
                specSuperclass := cls superclass name.
            ]
        ]
    ].
    aspects at:#superclassNameChannel put:(
        (specSuperclass notNil ifTrue:[specSuperclass]
                         ifFalse:['ApplicationModel']) asValue
    ).
    aspects at:#superclassNameDefaults put:#('ApplicationModel' 'SimpleDialog') asValue.
    aspects at:#methodNameChannel put:(
        (specSelector notNil ifTrue:[specSelector asValue]
                            ifFalse:[#windowSpec]) asValue
    ).

    treeView    := TreeView new.
    painterView := StandardSystemView new.
    painterView name: self class defaultNameOfCanvas.
    painterView label: self class defaultNameOfCanvas.
    painterView extent:300@300.

    painter := UIPainterView in:painterView.
    painter layout:(0.0 @ 0.0 corner:1.0 @ 1.0) asLayout.

    treeView := treeView canvas:painter.
    painter treeView:treeView.
    treeView model addDependent:self.

    self transcriptHelp
    ifFalse:
    [
        super openInterface:aSymbol.
    ]
    ifTrue:
    [
        super openInterface:#windowSpecWithTranscriptHelp.
        transcript := (self builder componentAt:#HelpTranscript) scrolledView.
    ].

    topView := self window.

    topView label:'GUI Painter'.

    painterView openInGroup:(topView windowGroup).

    painterView application:self.
    painterView open.

    painterView application:self.
    selectionPanel := UISelectionPanel new.
    selectionPanel allButOpenInterface:#windowSpec.
    selectionPanel window openInGroup:(topView windowGroup).

    selectionPanel openWindow.
    selectionPanel masterApplication:self.

    topView iconLabel:'GUI Painter'.
    topView icon:(Image fromFile:'bitmaps/UIPainter.xbm' resolution:100).

    painterView iconLabel:'GUI Painter'.
    painterView icon:(Image fromFile:'bitmaps/UIPainter.xbm' resolution:100).

    topView bePartner.
    painterView bePartner.
    selectionPanel window bePartner.

    selectionPanel window iconLabel:'GUI Painter'.
    selectionPanel window icon:(Image fromFile:'bitmaps/UIPainter.xbm' resolution:100).

    ActiveHelp startFor:self.
!

openOnClass:aClass
    "open up an interface builder
    "
    self openOnClass:aClass andSelector:#windowSpec
!

openOnClass:aClass andSelector:aSelector
    "open up an interface builder, fetching a spec from someClass
     via some selector
    "
    |painter|

    aClass isNil ifTrue:[
        (self confirm:'No class given to the GUI Painter (class was probably renamed?)\\Open anyway (to create a new window spec) ?' withCRs)
        ifFalse:[^ nil].
    ].

    self openInterface.

    aClass notNil ifTrue:[
        painter := self painter.
        self setClass:aClass selector:aSelector.
        (aClass respondsTo:aSelector) ifTrue:[
            "take care for those who do close very quickly"
            Object errorSignal handle: [:ex|] do: 
            [
                painter setupFromSpec:(aClass perform:aSelector).
                treeView selection: #(1)
            ].
        ]
    ]

    "Modified: / 25.10.1997 / 19:11:51 / cg"
    "Modified: / 5.2.1998 / 09:48:15 / stefan"
!

postOpenWith: aBuilder

    super postOpenWith: aBuilder.

    treeView selection: (Array with: 1).
    self treeSelection.
    self tabSelection: 'Basics'


! !

!UIPainter methodsFor:'user actions'!

doBrowseAspectMethods
    "open a browser on the aspect methods"

    |cls methods|

    self painter isModified ifTrue:[
        self warn:'The current window spec has not yet been saved!!\\The System Browser may show the code of the old aspect methods.' withCRs.
    ].
    cls := self resolveName:specClass.

    cls notNil ifTrue:[
        methods := self painter aspectMethods.
        methods isEmpty ifTrue:[
            self warn:'No aspect methods have been saved yet!!'.
            ^ self.
        ].
        SystemBrowser browseMethods:methods title:'Aspect methods'.
    ] ifFalse:[
        self information:'No class defined!!'.
    ].

    "Created: / 25.10.1997 / 19:07:55 / cg"
!

doBrowseClass
    "open a System Browser on the class"

    |cls|

    self painter isModified ifTrue:[
        self warn:'The current window spec has not yet been saved!!\\The System Browser will show the code of the old window spec.' withCRs.
    ].
    cls := self resolveName:specClass.

    cls notNil ifTrue:[
        SystemBrowser openInClass:cls
    ] ifFalse:[
        self information:'No class defined!!'.
    ].

!

doChooseTreeViewFont

    |font|
    (font := FontPanel 
        fontFromUserInitial: treeView class defaultFont
        title: 'Choose Tree View Font') notNil
    ifTrue:
    [
        treeView class defaultFont: (font on: device).
        treeView font: treeView class defaultFont
    ]
!

doGenerateAspectMethods
    "generate aspect and action methods
    "
    |code|

    self treeSelection. "accept modifications"

    self hasSpecClassAndSelector ifFalse:[
        self defineClassAndSelector
    ].

    self checkClassAndSelector ifFalse:[
        ^ self
    ].

    self painter className:specClass
        superclassName:specSuperclass
              selector:specSelector.

    code := self painter generateAspectMethods.
    (ReadStream on:code) fileIn.

!

doGenerateHookMethods
    "generate hook methods for the application class
    "
    |code|

    self treeSelection. "accept modifications"

    self hasSpecClassAndSelector ifFalse:[
        self defineClassAndSelector
    ].

    self checkClassAndSelector ifFalse:[
        ^ self
    ].

    self painter className:specClass
        superclassName:specSuperclass
              selector:specSelector.

    code := self painter generateHookMethods.
    (ReadStream on:code) fileIn.

    "Created: / 31.10.1997 / 17:37:54 / cg"
!

doLoad

    self askForModification ifFalse: [^nil].

    self loadFromMessage: 
        (ResourceSelectionBrowser
            request: 'Load Window Spec From Class'
            onSuperclass: nil
            andClass: specClass
            andSelector: specSelector ? #windowSpec
            withResourceTypes: #(canvas))
!

doLoadSubspec

    |subSpecMessage|

    self treeSelection. "ask for modification"

    (subSpecMessage := ResourceSelectionBrowser
            request: 'Load Subspec From Class'
            onSuperclass: nil
            andClass: specClass
            andSelector: specSelector
            withResourceTypes: #(canvas)) notNil
    ifTrue:
    [
        |readStream aClass aSelector|
        readStream := subSpecMessage readStream.
        (aClass := Smalltalk at: (readStream upTo: $ ) asSymbol) notNil
        ifTrue:
        [
            aSelector :=  readStream upToEnd asSymbol.
            (aClass name == specClass and: [aSelector == specSelector]) ifTrue: [^self warn: 'Current interface as subspec not allowed!!'].
            (aClass respondsTo:aSelector) 
            ifTrue:
            [
                self addWidgetOfSpec: (Array with: (UISubSpecification new majorKey: aClass name; minorKey: aSelector))
            ]
        ]
    ]
!

doNew
    "remove all components and associated resources
    "

    self askForModification ifFalse: [^nil].
    specClass := specSelector := nil.
    self painter removeAll.
    treeView canvas topView name:  UIPainter defaultNameOfCanvas.
    treeView canvas topView label: UIPainter defaultNameOfCanvas.
    self helpTool reset.
    treeView selection:#(1).
    self treeSelection.
    self updateInfoLabel.
!

doPickAView
    "pick a view and setup specifications
    "
    |painter view cls spec app|

    self askForModification ifFalse: [^nil].

    (view := Screen current viewFromUser) notNil ifTrue:[
        view == Screen current rootView ifFalse:[
            painter := self painter.
            spec    := UISpecification fromView:view topView.

         "/ ok, got it

         "   (app := view application) notNil ifTrue:[
                cls := app class
            ] ifFalse:[
                cls := view class
            ].            
            self setClass:cls selector:nil.
         "
            painter setupFromSpec:spec.
        ]
    ].

    self updateInfoLabel

!

doSave
    "install window spec
    "
    |code painter|

    self treeSelection. "ask for modification"

    self hasSpecClassAndSelector ifFalse:[
         (self defineClassAndSelector) isNil ifTrue: [^nil]
    ].

    (specClass notNil and: [(Smalltalk at: specClass asSymbol) isClass])
    ifFalse: 
    [   
        ^nil
    ].

    self isModified ifTrue:[
        (self confirm:'Accept modifications in section ' , tabSelection printString , '?') ifTrue:[
            self accept
        ] ifFalse:[
            (self confirm:'Load old window spec?') ifFalse:[
                ^ self
            ]
        ]
    ].

    painter := self painter.

    painter className:specClass
       superclassName:specSuperclass
             selector:specSelector.

    code := painter generateWindowSpecMethodSource withCRs.
    painter resetModification.
    (ReadStream on:code) fileIn.

    self helpTool installHelpSpecsOnClass:specClass.

    self updateInfoLabel.
    modified := false.
    self painter resetModification.

    ((Smalltalk at: specClass asSymbol) class implements: specSelector) 
    ifTrue: 
    [
        self addToHistory: (specClass, ' ', specSelector) -> #loadFromMessage:.
    ].


!

doSaveAs
    "launch a dialog to define class, superclass and method"

    |resourceMessage|

    self treeSelection. "ask for modification"

    (resourceMessage := ResourceSelectionBrowser
            request: 'Save Window Spec In Class'
            onSuperclass: #Object
            andClass: (specClass ? #ApplicationModel) asSymbol
            andSelector: specSelector ? #windowSpec
            withResourceTypes: #(canvas)) notNil
    ifTrue:
    [
        modified := false.
        self painter resetModification.
        (self resourceMessage: resourceMessage)
        ifTrue:
        [
            self doSave.
            ^true
        ]
    ]

!

doStartApplication
    "start current edited application
    "
    |cls app infoMessage|

    self treeSelection. "accept modifications"

    (specClass isNil or:[specSelector size < 2]) ifTrue:[
        self painter isModified ifTrue:[
            infoMessage := 'Class and selector must be defined,\and the window spec must be saved first!!' withCRs.
        ] ifFalse:[
            infoMessage := 'No class and selector defined!!'.
        ]
    ] ifFalse:[
        cls := self resolveName:specClass.

        cls isNil ifTrue:[
            infoMessage := 'Class does not exist!!'.
        ] ifFalse:[
            (cls respondsTo:specSelector) ifFalse:[
                infoMessage := ('No method for: #' 
                                , specSelector , ' in ' , cls name
                                , '\\(did you save the window spec?)') withCRs.
            ]
        ]
    ].

    infoMessage notNil ifTrue:[
        ^ self information:infoMessage
    ].

    self isModified ifTrue:[
        (self confirm:'Accept modifications in section ' , tabSelection printString asBoldText, '?') ifTrue:[
            self accept.
            "/  "XXX must be fixed - canvas changes are not recorded in the history
            "/  so isModified returns false here
            "/
            "/ self painter isModified ifTrue:[
            "/
            (self confirm:'Save the new window spec?' withCRs) ifTrue:[
                self doSave
            ]
        ]
    ].

    self painter isModified ifTrue:[
        (self confirm:'The current window spec has not yet been saved!!\\Start anyway (based upon the previous window spec)?' withCRs) ifFalse:[
                ^ self
        ]
    ].

    ((app := cls new) respondsTo:#openInterface:) ifFalse:[
        ^ self warn:('The application does not respond to the ''openInterface:'' message.\\(maybe its supposed to be used as subApplication/subCanvas)') withCRs.
    ].        
    app openInterface:specSelector
!

doStepDown
    "move selected component after the next component in the hierarchy of
     its container widget
    "
    treeView doStepOver:1
!

doStepIn
    "change the container of the selected widget
    "
    treeView doStepIn
!

doStepOut
    "change the container of the selected widget
    "
    treeView doStepOut
!

doStepUp
    "move selected component before the previous component in the hierarchy of
     its container widget
    "
    treeView doStepOver:-1
!

doWindowSpec
   "create the window specification but do not write to application; instead
    open a view
   "
   |code v|

   self treeSelection. "accept modifications"

   code := self painter generateWindowSpecMethodSource.

   v := CodeView open.
   v contents:code.
   v label:'windowSpec'.

! !

!UIPainter::TreeView class methodsFor:'documentation'!

documentation
"
    selection in tree view; only used by the UIPainter

    [see also:]
        SelectionInTreeView
        SelectionInTree
        TreeItem
        UIPainter

    [author:]
        Claus Atzkern
"


! !

!UIPainter::TreeView methodsFor:'accessing'!

canvas
    "returns the canvas( UIPainter )
    "
  ^ model root contents view


!

canvas:aCanvas
    "install canvas( UIPainter )
    "
    |props|

    props := UIPainterView::ViewProperty new.
    props view:aCanvas.
    model root:(TreeItem name: UIPainter defaultNameOfCanvas asBoldText contents:props).
    model root expand.
    self enableChannel:(aCanvas enableChannel).

!

canvasSpec
    "returns spec assigned to canvas
    "
    |spec|

    spec := WindowSpec new.

    spec fromView:(self canvas topView) callBack:nil.
    windowSpec notNil ifTrue:[
        spec copyValuesFromSpec:windowSpec
    ].
    ^ spec

    "Modified: / 29.10.1997 / 18:06:44 / cg"
!

canvasSpec:aSpec
    "update canvas from spec
    "
    |spec|

    self setAttributesFromWindowSpec:aSpec.
    spec := aSpec copy.
    spec  menu:nil.
    spec flags:nil.

    spec setAttributesIn:(self canvas topView) with:(UIBuilder new isEditing:true).
!

itemOfView:aView
    "returns item assigned to view or nil
    "
    aView notNil ifTrue:[
        self allItemsDo:[:anItem|
            (anItem contents view == aView) ifTrue:[^ anItem]
        ]
    ].
  ^ nil


! !

!UIPainter::TreeView methodsFor:'accessing property'!

propertiesDo:aOneArgBlock
    "evaluate the argument a block on each property
    "
    self allItemsDo:[:anItem| aOneArgBlock value:(anItem contents)]


!

propertyDetect:aOneArgBlock
    "evaluate the block on each property
    "
    self allItemsDo:[:anItem|
        (aOneArgBlock value:(anItem contents)) ifTrue:[^ anItem contents]
    ].
  ^ nil

!

propertySelected
    "returns current selected property or nil in case of multi selection
     or empty selection
    "
    |idx|

    selection size == 1 ifTrue:[
        (idx := selection first) ~~ 1 ifTrue:[          "canvas: not yet supported"
            ^ (listOfNodes at:idx) contents
        ]
    ].
  ^ nil

! !

!UIPainter::TreeView methodsFor:'adding & removing'!

addProperty:aProperty
    "add a new item
    "
    |parent| 

    parent := self detectItemRespondsToView:(aProperty view superView).

    parent notNil ifTrue:[
        model add:(TreeItem new contents:aProperty) below:parent
    ]

!

removeAll
    "remove all items other than canvas
    "
    lastDrawnMaster := nil.
    windowSpec := nil.

    self canvas subViews copy do:[:aView|
        (aView isKindOf:InputView) ifFalse:[aView destroy]
    ].
    model root name: UIPainter defaultNameOfCanvas asBoldText.
    model root children:(OrderedCollection new).
    model recomputeList.                

!

removeView:aView
    "remove a view
    "
    |item prnt|

    ((item := self itemOfView:aView) notNil and:[(prnt := item parent) notNil]) ifTrue:[
        aView destroy.
        prnt contents view sizeChanged:nil.
        model remove:item
    ]


! !

!UIPainter::TreeView methodsFor:'building'!

generateFullSpecForComponents:aSpecArray
    "generates a full spec for components
    "
    |fullSpec winSpec|

    fullSpec := FullSpec new.

    fullSpec fromBuilder:(self canvas topView)
              components:(SpecCollection new collection:aSpecArray).

    windowSpec notNil ifTrue:[
        winSpec := fullSpec window.
        winSpec copyValuesFromSpec:windowSpec.
        winSpec name: winSpec label.
    ].    
    ^ fullSpec literalArrayEncoding.

    "Modified: / 29.10.1997 / 18:05:58 / cg"
!

setAttributesFromWindowSpec:aWindowSpec
    "set windowSpec from argument a WindowSpec
    "                           
    windowSpec := WindowSpec new copyValuesFromSpec:aWindowSpec.
    self canvasNameChanged:aWindowSpec name.

    "Modified: / 29.10.1997 / 18:06:56 / cg"
! !

!UIPainter::TreeView methodsFor:'canvas selection'!

cvsSelection:aSelection
    "canvas changed its selection
    "
    |sel list rcLt|

    list := OrderedCollection new.

    aSelection isNil ifFalse:[
        aSelection isCollection ifTrue:[
            aSelection notNil ifTrue:[sel := aSelection]
        ] ifFalse:[
            sel := Array with:aSelection
        ]
    ].

    sel notNil ifTrue:[
        rcLt := false.

        sel do:[:aView||item|
            (item := self itemOfView:aView) notNil ifTrue:[
                list add:item.

                [(item := item parent) notNil] whileTrue:[
                    item hidden ifTrue:[
                        rcLt := true.
                        item expand.
                    ]
                ]
            ]
        ].
        rcLt ifTrue:[model recomputeList].
        sel := list collect:[:anItem| listOfNodes findFirst:[:el| el == anItem]]
    ] ifFalse:[
        sel := list
    ].
    self cvsEventsDisabledDo:[ self selection:sel ].            




!

cvsSelectionAdd:aView
    "canvas adds a view to current selection
    "
    |parent item rcLt oldSel|

    item := self itemOfView:aView.

    item notNil ifTrue:[
        parent := item.

        [ (parent := parent parent) notNil ] whileTrue:[
            parent hidden ifTrue:[
                rcLt := true.
                parent expand.
            ]
        ].
        rcLt == true ifTrue:[model recomputeList].

        oldSel := selection copy.
        self addToSelection:(listOfNodes findFirst:[:el| el == item]).
        self selectionChangedFrom:oldSel
    ].            



!

cvsSelectionRemove:aView
    "canvas removes a view from current selection
    "
    |parent item rcLt oldSel|

    item := self itemOfView:aView.

    item notNil ifTrue:[
        parent := item.

        [ (parent := parent parent) notNil ] whileTrue:[
            parent hidden ifTrue:[
                rcLt := true.
                parent expand.
            ]
        ].
        rcLt == true ifTrue:[model recomputeList].

        oldSel := selection copy.
        self removeFromSelection:(listOfNodes findFirst:[:el| el == item]).
        self selectionChangedFrom:oldSel
    ].            



! !

!UIPainter::TreeView methodsFor:'change & update'!

canvasNameChanged:aName
    "called if identification name assigned to window (canvas) changed
    "
    |name node|

    node := listOfNodes at:1.

    (    aName size ~~ 0
     and:[(name := aName string withoutSeparators) size ~~ 0
     and:[(self propertyDetect:[:p| p name = name]) isNil
     and:[node name ~= name]]]
    ) ifTrue:[
        node name: name asBoldText.
        node changed.
    ].
!

layoutChanged
    "layout of any component changed; in case of single selection, the
     application will be informed to update its layout
    "
    selection size == 1 ifTrue:[
        self application layoutChanged
    ]


!

propertyChanged:aProperty
    "property of view derived from argument a property changed
    "
    |item idx end|

    item := self itemOfView:(aProperty view).

    item notNil ifTrue:[
        item contents:aProperty.

        item name = aProperty name ifFalse:[
            idx := self firstLineShown.

            (end := self lastLineShown) > listOfNodes size ifTrue:[
                end := listOfNodes size
            ].                          
            item changed.

            [idx <= end] whileTrue:[
                (listOfNodes at:idx) == item ifTrue:[
                    self redrawLine:idx.                "/ is visible; redraw line
                    end := 0
                ] ifFalse:[
                    idx := idx + 1
                ]
            ]
        ].

        self selectedNode == item ifTrue:[              "/ inform application
            self application propertyChanged
        ]
    ].


! !

!UIPainter::TreeView methodsFor:'drag & drop'!

canDrop:anObjectOrCollection
    "can drop ? delegate to canvas
    "
  ^ self canvas canDrop:anObjectOrCollection
!

drop:anObjectOrCollection at:aPoint
    "drop objects ? delegate to canvas
    "
    self canvas drop:anObjectOrCollection at:aPoint
! !

!UIPainter::TreeView methodsFor:'enumerating'!

allItemsDo:aOneArgBlock
    "evaluate the argument a block on each item other than the canvas
    "
    model root allChildrenDo:aOneArgBlock


! !

!UIPainter::TreeView methodsFor:'event processing'!

cvsEventsDisabledDo:aBlock
    "evaluate the block without raising selection changed notifications
     to canvas
    "
    |restoreCvsEvents|

    restoreCvsEvents  := cvsEventsDisabled.
    cvsEventsDisabled := true.
    aBlock value.
    cvsEventsDisabled := restoreCvsEvents.


!

cvsSetupListDo:aBlock
    "evaluate block without handling notifications from model; after evaluation
     the new list will be recomputed
    "
    model removeDependent:self.

    self cvsEventsDisabledDo:[
        self selection:nil.
        aBlock value
    ].
    model addDependent:self.
    model recomputeList.

!

doubleClicked
    "disable collapse of canvas item
    "
    self selectedNode == model root ifFalse:[
        super doubleClicked
    ]


! !

!UIPainter::TreeView methodsFor:'initialization'!

initialize
    "initialization; set multiple select and model
    "
    super initialize.

    self multipleSelectOk:true.
    cvsEventsDisabled := false.
    self showDirectoryIndicator: true.
    self showDirectoryIndicatorForRoot: false.

    self model iconAction: 
    [:aNode|
        |specClass|
        (specClass := aNode contents spec) isNil 
        ifTrue:  
        [
            WindowSpec icon
        ]
        ifFalse:
        [
            ((selection size > 1) and: [(listOfNodes at:selection first) == aNode])
            ifTrue: 
            [
                specClass class icon copyWithColorMapProcessing:[:clr | clr blendWith:Color red]
            ] 
            ifFalse:
            [
                specClass class icon
            ]
        ]
    ].

    self model labelAction: 
    [:aNode|
        |spec|
        (spec := aNode contents spec) notNil
            ifTrue:  [self nameForSpecInList:spec] 
            ifFalse: [aNode name]
    ]
! !

!UIPainter::TreeView methodsFor:'private'!

nameForSpecInList:aSpec
     ^ aSpec name asBoldText, ': [', aSpec viewClass name , ']' 
!

selectionChangedFrom:oldSelection
    "selection has changed. update master selection and raise notification
     to canvas in case of enabled cvs events
    "
    |sel size|

    super selectionChangedFrom:oldSelection.
    size := selection size.

    cvsEventsDisabled ifFalse:[
        (size ~~ 0 and:[size ~~ 1 or:[selection first ~~ 1]]) ifTrue:[
            sel := OrderedCollection new.

            selection do:[:i|
                i ~~ 1 ifTrue:[sel add:(listOfNodes at:i) contents view]
            ]
        ].
        self canvas updateSelectionFromModel:sel
    ].
    size = 1 ifTrue:[
        oldSelection size = 2 ifTrue: [
        self redrawLine: (lastDrawnMaster := selection first)]
    ].
    size > 1 ifTrue:[
        selection first ~~ lastDrawnMaster ifTrue: [
        self redrawLine: (lastDrawnMaster := selection first)]
    ]
    ifFalse: [
        lastDrawnMaster := nil
    ]
! !

!UIPainter::TreeView methodsFor:'queries'!

canChangeOrderInContainer
    "returns true if any selection exists and all widgets in the selection
     can change their layout through to a move or align operation.
    "
    |canvas|

    ((selection size ~~ 1) or: [(selection at: 1) == 1]) ifTrue:[
        ^ false
    ].
    ^ true
!

canMoveOrAlignSelection
    "returns true if any selection exists and all widgets in the selection
     can change their layout through to a move or align operation.
    "
    |canvas|

    selection size == 0 ifTrue:[
        ^ false
    ].
    canvas := self canvas.

    selection do:[:i|
        i == 1 ifTrue:[^ false].

        (canvas canChangeLayoutOfView:((listOfNodes at:i) contents view)) ifFalse:[
            ^ false
        ]
    ].
    ^ true
!

canMoveSelectionIntoContainer
    "returns true in case that one component is selected and can change its container
     widget to the next element in the list which will have the same container.
    "
    |item prnt|

    (     (item := self selectedNode) isNil
      or:[(prnt := item parent) isNil
      or:[(prnt := prnt childAt:((prnt indexOfChild:item) + 1)) isNil
      or:[prnt contents spec class supportsSubComponents not]]]
    ) ifTrue:[
        ^ false
    ].
  ^ true
!

canMoveSelectionOutOfContainer
    "returns true in case that one component is selected which is contained within
     another component.
    "
    |item prnt|

    (     (item := self selectedNode) isNil
      or:[(prnt := item parent) isNil
      or:[prnt parent isNil]]
    ) ifTrue:[
        ^ false
    ].
  ^ true
!

canResizeSelectedWidget
    "returns true in case of one widget selected and is contained
     within a widget which allows to resize sub components
    "
    |n|

    (n := self selectedNode) notNil ifTrue:[
        (n := n parent) notNil ifTrue:[
            ^ (n parent isNil or:[n contents spec class canResizeSubComponents])
        ]
    ].
    ^ false
!

hasOneSelectionOtherThanCanvas
    "returns true in case that one selection exists other than the canvas
    "
    ^ (selection size == 1 and:[selection first ~~ 1])
!

isCanvasSelected
    "returns true in case of a single selection and the
     selection is the canvas (index 1)
    "
    ^ (selection size == 1 and:[self isInSelection:1])
! !

!UIPainter::TreeView methodsFor:'seraching'!

detectItemRespondsToView:aView
    "detect the item responding to the view. The item of the view or the first
     subview providing the item is returned. If no property is detected nil is
     returned
    "
    |view item|

    (view := aView) notNil ifTrue:[
        [(item := self itemOfView:view) isNil] whileTrue:[
            (view := view superView) isNil ifTrue:[^ listOfNodes at:1]
        ].
    ].
    ^ item

! !

!UIPainter::TreeView methodsFor:'user interactions'!

doStepIn
    |item prnt canvas|

    (     (item := self selectedNode) isNil
      or:[(prnt := item parent) isNil
      or:[(prnt := prnt childAt:((prnt indexOfChild:item) + 1)) isNil
      or:[prnt contents spec class supportsSubComponents not]]]
    ) ifFalse:[
        canvas := self canvas.
        canvas deleteSelection.
        canvas setSelection:(prnt contents view) withRedraw:false.
        canvas pasteWithLayout.
    ]
!

doStepOut
    |item next prnt canvas|

    (     (item := self selectedNode) isNil
      or:[(prnt := item parent) isNil
      or:[(next := prnt parent) isNil]]
    ) ifTrue:[
        ^ self
    ].
    model removeDependent:self.

    canvas := self canvas.
    canvas deleteSelection.
    canvas setSelection:(next contents view) withRedraw:false.
    canvas pasteWithLayout.

!

doStepOver:anIndex
    "move child 'anOffset' forward or backward in list of children
    "
    |item idx size prnt spVw view canvas|

    (    (item := self selectedNode) isNil
     or:[(prnt := item parent) isNil
     or:[(size := prnt children size) < 2
     or:[(idx  := prnt indexOfChild:item) == 0]]]
    ) ifTrue:[
        ^ self
    ].
    model removeDependent:self.
    model removeSelection.
    selection := nil.
    model addDependent:self.
    idx := idx + anIndex.

    idx < 1 ifTrue:[idx := size]
           ifFalse:[idx > size ifTrue:[idx := 1]].

    model add:item beforeIndex:idx below:prnt.
    idx    := prnt indexOfChild:item.
    view   := item contents view.
    spVw   := prnt contents view.
    canvas := self canvas.

    canvas hideSelection.

 "/ input view might by contained in sequence
    ((size := canvas findInputViewIn:spVw) ~~ 0 and:[idx >= size]) ifTrue:[
        idx := idx + 1
    ].
    spVw changeSequenceOrderFor:view to:idx.

    spVw specClass isLayoutContainer ifFalse:[
        spVw subViews do:[:v| v raise ].
        canvas inputView raise
    ].
    canvas showSelection.
    self selectNode:item.
! !

!UIPainter class methodsFor:'documentation'!

version
    ^ '$Header$'
! !