UIPainter.st
author Claus Gittinger <cg@exept.de>
Thu, 17 Feb 2000 16:01:27 +0100
changeset 1361 9020214f03e6
parent 1360 555429506474
child 1391 be99f3e9260e
permissions -rw-r--r--
generate aspect-setters for exported aspects

"
 COPYRIGHT (c) 1995-1998 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:'specClass specSelector specSuperclass aspects treeView
		selectionPanel tabSelection modified specTool layoutTool helpTool'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

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

!UIPainter class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1995-1998 by eXept Software AG
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

!

documentation
"
    The GUI Painter provides the user with a graphical user interface for building own 
    interfaces by interactively assembling widgets and defining the behavior of the widgets.
    The resulting interface specifications can be saved as methods on the application
    classes, typically subclasses of the class ApplicationModel. These specifications
    are used by the UIBuilder to generate the application window and its widgets when 
    opening the application.

    [start with:]
	UIPainter open

    [author:]
	Claus Gittinger, eXept Software AG
	Claus Atzkern, eXept Software AG
	Thomas Zwick, 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
! !

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

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


! !

!UIPainter class methodsFor:'accessing'!

defaultNameOfCanvas
    "returns the default name 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:#(

#align
'Widget alignment functions.'

#alignSelectionBottom
'Aligns the selected widgets bottom edges with the bottom of the dominant widget.'

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

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

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

#alignSelectionLeftAndRight
'Aligns the selected widgets left & right edges with the dominant widget.'

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

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

#alignSelectionTopAndBottom
'Aligns the selected widgets top and bottom edges with the dominant widget.'

#centerSelectionHor
'Centers the selected widgets horizontally within their containing widget.'

#centerSelectionVer
'Centers the selected widgets vertically within their containing widget.'

#changePositionDown
'Moves the selected widget(s) towards the bottom.'

#changePositionLeft
'Moves the selected widget(s) towards the left.'

#changePositionRight
'Moves the selected widget(s) towards the right.'

#changePositionUp
'Moves the selected widget(s) towards the top.'

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

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

#editDimensionDefaultExtent
'Sets the selected widget(s) extent to their default.'

#editDimensionDefaultHeight
'Sets the selected widget(s) height to their default.'

#editDimensionDefaultWidth
'Sets the selected widget(s) width to their default.'

#editDimensionPasteExtent
'Sets the extent of the selected widget(s) to the last copied extent.'

#editDimensionPasteHeight
'Sets the height of the selected widget(s) to the height of the last copied layout/extent.'

#editDimensionPasteLayout
'Sets the layout of the selected widget(s) to the last copied layout.'

#editDimensionPasteWidth
'Sets the width of the selected widget(s) to the width of the last copied layout/extent.'

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

#editInspectView
'Opens an inspector on the view of the selected widget.'

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

#fileBrowseAspectMethods
'Opens a System Browser on the aspect methods.'

#fileLoad
'Opens a dialog to load a window specification from a classes spec method.'

#fileLoadSubspec
'Opens a dialog to load a sub specification from a classes windowSpec method.'

#fileNew
'Creates a new window spec.'

#filePickAnInterface
'Select a view on the screen, generate a window spec for it and edit this spec.'

#fileSave
'Saves the window spec in the current class (as spec method).'

#fileSaveAs
'Opens a dialog to select class and selector for saving the 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:)'

#helpExamples
'Show some examples uses of the GUI Painter.'

#helpFunctions
'Show the documentation on the GUI Painters menu and button functions.'

#helpLayoutTool
'Show the Layout Tools documentation.'

#helpSelectedWidget
'Show the documentation of the selected widget.'

#helpTutorial
'Show the GUI Painters documentation.'

#historyMenuItem
'Edit this windowSpec.'

#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 the 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 toggle grid display or to change the grids spacing.'

#settingsRedefineAspectMethods
'Toggles the permission to overwrite existing aspect methods.'

#settingsAspectsAsInstances
'Generate aspects as instance variables (or bindings, if off).'

#settingsTranscriptHelp
'Toggles display of help texts (after opening a new GUI Painter).'

#settingsUndoManager
'Opens a dialog to undo modifications.'

#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
'Toggles geometry test mode (to define ratios of variable panels and top-window dimension).'

#testStartApplication
'Starts the application with the current window spec.'

)

    "Modified: / 31.7.1998 / 19:29:53 / cg"
! !

!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 291 0 130 0 637 0 289 0)
	      #label: 'GUI Painter'
	      #min: #(#Point 350 160)
	      #max: #(#Point 500 160)
	      #bounds: #(#Rectangle 291 130 638 290)
	      #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 67 0.11 29 0 1 0.5)
			      #label: 'Selector:'
			      #translateLabel: true
			      #adjust: #right
			      #resizeForLabel: true
			  )
			   #(#InputFieldSpec
			      #name: 'methodNameField'
			      #layout: #(#LayoutFrame 70 0.11 18 0 4 1.0 40 0)
			      #tabable: true
			      #model: #methodNameChannel
			      #group: #inputGroup
			  )
			   #(#LabelSpec
			      #name: 'classLabel'
			      #layout: #(#AlignmentOrigin 67 0.11 54 0 1 0.5)
			      #label: 'Class:'
			      #translateLabel: true
			      #adjust: #right
			      #resizeForLabel: true
			  )
			   #(#InputFieldSpec
			      #name: 'classNameField'
			      #layout: #(#LayoutFrame 70 0.11 43 0 4 1.0 65 0)
			      #tabable: true
			      #model: #classNameChannel
			      #group: #inputGroup
			  )
			   #(#LabelSpec
			      #name: 'superClassLabel'
			      #layout: #(#AlignmentOrigin 67 0.11 79 0 1 0.5)
			      #label: 'Superclass:'
			      #translateLabel: true
			      #adjust: #right
			      #resizeForLabel: true
			  )
			   #(#ComboBoxSpec
			      #name: 'superclassNameComboBox'
			      #layout: #(#LayoutFrame 70 0.11 68 0 4 1.0 90 0)
			      #tabable: true
			      #model: #superclassNameChannel
			      #comboList: #superclassNameDefaults
			  )
			)
		    )
		    #label: 'Define Class And Selector'
		    #labelPosition: #topLeft
		    #translateLabel: true
		)
		 #(#UISubSpecification
		    #name: 'subSpec'
		    #layout: #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1)
		    #majorKey: #ToolApplicationModel
		    #minorKey: #windowSpecForCommitWithoutChannels
		)
	      )
	  )
      )

    "Modified: / 13.8.1998 / 19:59:44 / cg"
!

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 291 0 130 0 572 0 327 0)
	      #label: 'GUI Painter'
	      #min: #(#Point 300 200)
	      #max: #(#Point 300 200)
	      #bounds: #(#Rectangle 291 130 573 328)
	      #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 13 14)
			      #model: #showGrid
			      #label: 'Show Grid'
			  )
			   #(#CheckBoxSpec
			      #name: 'AlignCheckBox'
			      #layout: #(#Point 13 42)
			      #model: #alignToGrid
			      #label: 'Align To Grid'
			  )
			   #(#LabelSpec
			      #name: 'HorizontalPixelsLabel'
			      #layout: #(#AlignmentOrigin 138 0 89 0 1 0.5)
			      #label: 'Horizontal Pixels:'
			      #translateLabel: true
			      #adjust: #right
			      #resizeForLabel: true
			  )
			   #(#InputFieldSpec
			      #name: 'HorizontalPixelsField'
			      #layout: #(#LayoutFrame 144 0 77 0 197 0 99 0)
			      #model: #hspace
			      #group: #inputGroup
			      #type: #numberOrNil
			  )
			   #(#LabelSpec
			      #name: 'VerticalPixelsLabel'
			      #layout: #(#AlignmentOrigin 139 0 114 0 1 0.5)
			      #label: 'Vertical Pixels:'
			      #translateLabel: true
			      #adjust: #right
			      #resizeForLabel: true
			  )
			   #(#InputFieldSpec
			      #name: 'VerticalPixelsField'
			      #layout: #(#LayoutFrame 144 0 102 0 197 0 124 0)
			      #model: #vspace
			      #group: #inputGroup
			      #type: #numberOrNil
			  )
			)
		    )
		    #label: 'Grid Parameter'
		    #labelPosition: #topLeft
		    #translateLabel: true
		)
		 #(#UISubSpecification
		    #name: 'subSpec'
		    #layout: #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1)
		    #majorKey: #ToolApplicationModel
		    #minorKey: #windowSpecForCommitWithoutChannels
		)
	      )
	  )
      )

    "Modified: / 13.8.1998 / 20:00:00 / cg"
!

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

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

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #windowSpec
        #window: 
       #(#WindowSpec
          #label: 'GUI Painter'
          #name: 'GUI Painter'
          #min: #(#Point 560 460)
          #max: #(#Point 1160 870)
          #bounds: #(#Rectangle 12 22 620 545)
          #menu: #menu
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#MenuPanelSpec
              #attributes: 
             #(#tabable
                true
              )
              #name: 'menuToolbarView'
              #layout: #(#LayoutFrame 0 0.0 0 0 0 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)
              #level: 1
              #component: 
             #(#SpecCollection
                #collection: #(
                 #(#ArbitraryComponentSpec
                    #name: 'treeView'
                    #tabable: true
                    #menu: #menuEdit
                    #hasHorizontalScrollBar: true
                    #hasVerticalScrollBar: true
                    #miniScrollerHorizontal: true
                    #miniScrollerVertical: true
                    #hasBorder: false
                    #component: #treeView
                  )
                 #(#ViewSpec
                    #name: 'specHolderView'
                    #borderWidth: 1
                    #component: 
                   #(#SpecCollection
                      #collection: #(
                       #(#MenuPanelSpec
                          #attributes: 
                         #(#tabable
                            true
                          )
                          #name: 'menuToolbar2View'
                          #layout: #(#LayoutFrame -1 0.0 -2 0 -1 1.0 30 0)
                          #enableChannel: #canMoveOrAlignSelection
                          #tabable: true
                          #menu: #menuToolbar2
                        )
                       #(#HorizontalPanelViewSpec
                          #name: 'horizontalPanelView1'
                          #layout: #(#LayoutFrame -163 1 -1 0 -35 1.0 28 0)
                          #horizontalLayout: #fit
                          #verticalLayout: #fit
                          #horizontalSpace: 0
                          #verticalSpace: 0
                          #component: 
                         #(#SpecCollection
                            #collection: #(
                             #(#ArrowButtonSpec
                                #attributes: 
                               #(#tabable
                                  true
                                )
                                #name: 'MoveLeftButton'
                                #activeHelpKey: #changePositionLeft
                                #tabable: true
                                #model: #moveSelectionLeft
                                #enableChannel: #canMoveOrAlignSelection
                                #isTriggerOnDown: true
                                #direction: #left
                                #useDefaultExtent: true
                              )
                             #(#ArrowButtonSpec
                                #attributes: 
                               #(#tabable
                                  true
                                )
                                #name: 'MoveRightButton'
                                #activeHelpKey: #changePositionRight
                                #tabable: true
                                #model: #moveSelectionRight
                                #enableChannel: #canMoveOrAlignSelection
                                #isTriggerOnDown: true
                                #actionValue: ''
                                #direction: #right
                                #useDefaultExtent: true
                              )
                             #(#ArrowButtonSpec
                                #attributes: 
                               #(#tabable
                                  true
                                )
                                #name: 'MoveDownButton'
                                #activeHelpKey: #changePositionDown
                                #tabable: true
                                #model: #moveSelectionDown
                                #enableChannel: #canMoveOrAlignSelection
                                #isTriggerOnDown: true
                                #actionValue: ''
                                #direction: #down
                                #useDefaultExtent: true
                              )
                             #(#ArrowButtonSpec
                                #attributes: 
                               #(#tabable
                                  true
                                )
                                #name: 'MoveUpButton'
                                #activeHelpKey: #changePositionUp
                                #tabable: true
                                #model: #moveSelectionUp
                                #enableChannel: #canMoveOrAlignSelection
                                #isTriggerOnDown: true
                                #actionValue: ''
                                #direction: #up
                                #useDefaultExtent: true
                              )
                             )
                           
                          )
                        )
                       #(#ActionButtonSpec
                          #attributes: 
                         #(#tabable
                            true
                          )
                          #label: 'helpIcon'
                          #name: 'openWidgetDocumentationButton'
                          #layout: #(#LayoutFrame -28 1 -1 0 0 1 28 0)
                          #activeHelpKey: #editOpenSpecDocumentation
                          #hasCharacterOrientedLabel: false
                          #tabable: true
                          #model: #doOpenWidgetDocumentation
                        )
                       #(#NoteBookViewSpec
                          #attributes: 
                         #(#tabable
                            true
                          )
                          #name: 'noteBook'
                          #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -30 1.0)
                          #enableChannel: #enableChannel
                          #tabable: true
                          #model: #tabModel
                          #menu: #tabList
                          #canvas: #noteBookView
                        )
                       #(#ActionButtonSpec
                          #attributes: 
                         #(#tabable
                            true
                          )
                          #label: 'Cancel'
                          #name: 'cancelButton'
                          #layout: #(#LayoutFrame 2 0 -26 1 -1 0.5 -2 1)
                          #activeHelpKey: #commitCancel
                          #tabable: true
                          #model: #cancel
                          #enableChannel: #modifiedChannel
                        )
                       #(#ActionButtonSpec
                          #attributes: 
                         #(#tabable
                            true
                          )
                          #label: 'OK'
                          #name: 'acceptButton'
                          #layout: #(#LayoutFrame 1 0.5 -26 1 -2 1 -2 1)
                          #activeHelpKey: #commitOK
                          #tabable: true
                          #model: #accept
                          #enableChannel: #modifiedChannel
                        )
                       )
                     
                    )
                  )
                 )
               
              )
              #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
            )
           )
         
        )
      )
! !

!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'
		#translateLabel: true
		#activeHelpKey: #about
		#labelImage: #(#ResourceRetriever nil #menuIcon)
		#submenuChannel: #menuAbout
	    )
	     #(#MenuItem
		#label: 'File'
		#translateLabel: true
		#activeHelpKey: #file
		#enabled: #enableChannel
		#submenu: 
		 #(#Menu
                    
		     #(
		       #(#MenuItem
			  #label: 'New'
			  #translateLabel: true
			  #value: #doNew
			  #activeHelpKey: #fileNew
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Load...'
			  #translateLabel: true
			  #value: #doLoad
			  #activeHelpKey: #fileLoad
		      )
		       #(#MenuItem
			  #label: 'Load Subspec...'
			  #translateLabel: true
			  #value: #doLoadSubspec
			  #activeHelpKey: #fileLoadSubspec
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Save'
			  #translateLabel: true
			  #value: #doSave
			  #activeHelpKey: #fileSave
		      )
		       #(#MenuItem
			  #label: 'Save As...'
			  #translateLabel: true
			  #value: #doSaveAs
			  #activeHelpKey: #fileSaveAs
		      )
		       #(#MenuItem
			  #label: 'Define Class And Selector...'
			  #translateLabel: true
			  #value: #doDefineClassAndSelector
			  #activeHelpKey: #fileSaveAs
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Pick A Window Spec...'
			  #translateLabel: true
			  #value: #doPickAView
			  #activeHelpKey: #filePickAnInterface
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Show Window Spec'
			  #translateLabel: true
			  #value: #doWindowSpec
			  #activeHelpKey: #fileShowWindowSpec
		      )
		       #(#MenuItem
			  #label: 'Browse Class'
			  #translateLabel: true
			  #value: #doBrowseClass
			  #activeHelpKey: #fileBrowseClass
			  #enabled: #hasSpecClass
		      )
		       #(#MenuItem
			  #label: 'Browse Aspect Methods'
			  #translateLabel: true
			  #value: #doBrowseAspectMethods
			  #activeHelpKey: #fileBrowseAspectMethods
			  #enabled: #hasSpecClass
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Exit'
			  #translateLabel: true
			  #value: #closeRequest
			  #activeHelpKey: #fileExit
		      )
		    ) nil
		    nil
		)
	    )
	     #(#MenuItem
		#label: 'Edit'
		#translateLabel: true
		#activeHelpKey: #edit
		#submenuChannel: #menuEdit
	    )
	     #(#MenuItem
		#label: 'Align'
		#translateLabel: true
		#activeHelpKey: #align
		#submenuChannel: #menuAlign
	    )
	     #(#MenuItem
		#label: 'Generate'
		#translateLabel: true
		#activeHelpKey: #generate
		#submenu: 
		 #(#Menu
                    
		     #(
		       #(#MenuItem
			  #label: 'Aspect Methods'
			  #translateLabel: true
			  #value: #doGenerateAspectMethods
			  #activeHelpKey: #generateAspectMethods
			  #enabled: #hasSpecClass
		      )
		       #(#MenuItem
			  #label: 'Menu Stub Methods'
			  #translateLabel: true
			  #value: #doGenerateMenuMethods
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Hook Methods'
			  #translateLabel: true
			  #value: #doGenerateHookMethods
			  #activeHelpKey: #generateHookMethods
			  #enabled: #hasSpecClass
		      )
		    ) nil
		    nil
		)
	    )
	     #(#MenuItem
		#label: 'Test'
		#translateLabel: true
		#activeHelpKey: #test
		#submenu: 
		 #(#Menu
                    
		     #(
		       #(#MenuItem
			  #label: 'Start Application'
			  #translateLabel: true
			  #value: #doStartApplication
			  #activeHelpKey: #testStartApplication
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Geometry Test Mode'
			  #translateLabel: true
			  #activeHelpKey: #testGeometryTestMode
			  #indication: #testMode:
		      )
		    ) nil
		    nil
		)
	    )
	     #(#MenuItem
		#label: 'Settings'
		#translateLabel: true
		#activeHelpKey: #settings
		#submenu: 
		 #(#Menu
                    
		     #(
		       #(#MenuItem
			  #label: 'Canvas'
			  #translateLabel: true
			  #activeHelpKey: #settingsCanvas
			  #indication: #painterShown
		      )
		       #(#MenuItem
			  #label: 'Gallery'
			  #translateLabel: true
			  #activeHelpKey: #settingsGallery
			  #indication: #galleryShown
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Redefine Aspect Methods'
			  #translateLabel: true
			  #activeHelpKey: #settingsRedefineAspectMethods
			  #enabled: #hasSpecClass
			  #indication: #redefineAspectMethods:
		      )
		       #(#MenuItem
			  #label: 'Aspects As Instances'
			  #translateLabel: true
			  #activeHelpKey: #settingsAspectsAsInstances
			  #enabled: #hasSpecClass
			  #indication: #generateAspectsAsInstanceVariables:
		      )
		       #(#MenuItem
			  #label: '-'
		      )
"/                       #(#MenuItem
"/                          #label: 'Fonts'
"/                          #submenuChannel: #menuFont
"/                      )
"/                       #(#MenuItem
"/                          #label: '-'
"/                      )
		       #(#MenuItem
			  #label: 'Undo Manager...'
			  #translateLabel: true
			  #value: #openUndoMenu
			  #activeHelpKey: #settingsUndoManager
			  #enabled: #hasUndoHistory
		      )
		       #(#MenuItem
			  #label: 'Grid Manager...'
			  #translateLabel: true
			  #value: #doDefineGrid
			  #activeHelpKey: #settingsGridManager
		      )
		    ) nil
		    nil
		)
	    )
	     #(#MenuItem
		#label: 'History'
		#translateLabel: true
		#activeHelpKey: #history
		#submenuChannel: #menuHistory
	    )
	     #(#MenuItem
		#label: 'Help'
		#translateLabel: true
		#startGroup: #right
		#activeHelpKey: #help
		#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: #helpFunctions
			  #argument: 'tools/uipainter/Functions.html'
		      )
		       #(#MenuItem
			  #label: 'Examples'
			  #translateLabel: true
			  #value: #openHTMLDocument:
			  #activeHelpKey: #helpExamples
			  #argument: 'tools/uipainter/Examples.html'
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Help Tool'
			  #translateLabel: true
			  #value: #openHTMLDocument:
			  #activeHelpKey: #helpHelpTool
			  #argument: 'tools/uipainter/HelpTool.html'
		      )
		       #(#MenuItem
			  #label: 'Layout Tool'
			  #translateLabel: true
			  #value: #openHTMLDocument:
			  #activeHelpKey: #helpLayoutTool
			  #argument: 'tools/uipainter/LayoutTool.html'
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Selected Widget'
			  #translateLabel: true
			  #value: #doOpenWidgetDocumentation
			  #activeHelpKey: #helpSelectedWidget
		      )
		       #(#MenuItem
			  #label: '-'
		      )
		       #(#MenuItem
			  #label: 'Show Help Texts'
			  #translateLabel: true
			  #activeHelpKey: #helpShowHelp
			  #indication: #showingHelp:
		      )
		    ) nil
		    nil
		)
	    )
	  ) nil
	  nil
      )

    "Modified: / 23.8.1998 / 16:09:22 / cg"
!

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

    "Modified: / 20.5.1998 / 01:42:57 / cg"
!

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'
                #translateLabel: true
                #nameKey: #undo
                #value: #undoLast
                #activeHelpKey: #editUndo
                #enabled: #hasUndoHistory
                #shortcutKeyCharacter: #Cmdu
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Cut'
                #translateLabel: true
                #value: #deleteSelection
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
                #shortcutKeyCharacter: #Cut
            )
             #(#MenuItem
                #label: 'Copy'
                #translateLabel: true
                #value: #copySelection
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
                #shortcutKeyCharacter: #Copy
            )
             #(#MenuItem
                #label: 'Paste'
                #translateLabel: true
                #value: #pasteBuffer
                #activeHelpKey: #pasteBuffer
                #enabled: #valueOfCanPaste
                #shortcutKeyCharacter: #Paste
            )
             #(#MenuItem
                #label: 'Delete'
                #translateLabel: true
                #value: #deleteTotalSelection
                #activeHelpKey: #editDelete
                #enabled: #valueOfCanCut
                #shortcutKeyCharacter: #Delete
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Paste With Layout'
                #translateLabel: true
                #value: #pasteWithLayout
                #activeHelpKey: #pasteWithLayout
                #enabled: #valueOfCanPasteWithKeepingLayout
            )
             #(#MenuItem
                #label: 'Paste Keeping Absolute Position'
                #translateLabel: true
                #value: #pasteKeepingPosition
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPasteWithKeepingLayout
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Move'
                #translateLabel: true
                #enabled: #canMoveSelection
                #submenuChannel: #menuMove
            )
             #(#MenuItem
                #label: 'Dimension'
                #translateLabel: true
                #enabled: #hasSelection
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Default Extent'
                          #translateLabel: true
                          #value: #setToDefaultExtent
                          #activeHelpKey: #editDimensionDefaultExtent
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Default Width'
                          #translateLabel: true
                          #value: #setToDefaultWidth
                          #activeHelpKey: #editDimensionDefaultWidth
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Default Height'
                          #translateLabel: true
                          #value: #setToDefaultHeight
                          #activeHelpKey: #editDimensionDefaultHeight
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Copy Layout'
                          #translateLabel: true
                          #value: #copyLayout
                          #activeHelpKey: #editDimensionCopyLayout
                          #enabled: #hasSingleSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Layout'
                          #translateLabel: true
                          #value: #pasteLayout
                          #activeHelpKey: #editDimensionPasteLayout
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Exchange Layouts'
                          #translateLabel: true
                          #value: #exchangeLayouts
                          #activeHelpKey: #editDimensionExchangeLayouts
                          #enabled: #canExchangeSelectionLayouts
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Copy Extent'
                          #translateLabel: true
                          #value: #copyExtent
                          #activeHelpKey: #editDimensionCopyExtent
                          #enabled: #hasSingleSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Extent'
                          #translateLabel: true
                          #value: #pasteExtent
                          #activeHelpKey: #editDimensionPasteExtent
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Width'
                          #translateLabel: true
                          #value: #pasteWidth
                          #activeHelpKey: #editDimensionPasteWidth
                          #enabled: #canMoveOrAlignSelection
                      )
                       #(#MenuItem
                          #label: 'Paste Height'
                          #translateLabel: true
                          #value: #pasteHeight
                          #activeHelpKey: #editDimensionPasteHeight
                          #enabled: #canMoveOrAlignSelection
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Open Widget Documentation'
                #translateLabel: true
                #value: #doOpenWidgetDocumentation
                #activeHelpKey: #editOpenSpecDocumentation
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Inspect View'
                #translateLabel: true
                #value: #doInspectView
                #activeHelpKey: #editInspectView
                #enabled: #hasOneSelectionOtherThanCanvas
            )
             #(#MenuItem
                #label: 'Inspect Spec'
                #translateLabel: true
                #value: #doInspectSpec
                #activeHelpKey: #editInspectSpec
            )
          ) nil
          nil
      )

    "Modified: / 20.5.1998 / 01:46:00 / cg"
!

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'
		#translateLabel: true
		#value: #doStepUp
		#activeHelpKey: #moveWidgetUp
		#enabled: #canChangeOrderInContainer
		#labelImage: #(#ResourceRetriever #Icon #upIcon 'Up')
	    )
	     #(#MenuItem
		#label: 'Down'
		#translateLabel: true
		#value: #doStepDown
		#activeHelpKey: #moveWidgetDown
		#enabled: #canChangeOrderInContainer
		#labelImage: #(#ResourceRetriever #Icon #downIcon 'Down')
	    )
	     #(#MenuItem
		#label: 'Into'
		#translateLabel: true
		#value: #doStepIn
		#activeHelpKey: #moveWidgetInto
		#enabled: #canMoveSelectionIntoContainer
		#labelImage: #(#ResourceRetriever #Icon #downRightIcon 'Into')
	    )
	     #(#MenuItem
		#label: 'Out'
		#translateLabel: true
		#value: #doStepOut
		#activeHelpKey: #moveWidgetOut
		#enabled: #canMoveSelectionOutOfContainer
		#labelImage: #(#ResourceRetriever #Icon #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 #Icon #startIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'New'
                #isButton: true
                #value: #doNew
                #activeHelpKey: #fileNew
                #labelImage: #(#ResourceRetriever #Icon #newIcon)
            )
             #(#MenuItem
                #label: 'Load'
                #isButton: true
                #value: #doLoad
                #activeHelpKey: #fileLoad
                #labelImage: #(#ResourceRetriever #Icon #loadIcon)
            )
             #(#MenuItem
                #label: 'Save'
                #isButton: true
                #value: #doSave
                #activeHelpKey: #fileSave
                #labelImage: #(#ResourceRetriever #Icon #saveIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Cut'
                #isButton: true
                #value: #deleteSelection
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever #Icon #cutIcon)
            )
             #(#MenuItem
                #label: 'Copy'
                #isButton: true
                #value: #copySelection
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
                #labelImage: #(#ResourceRetriever #Icon #copyIcon)
            )
             #(#MenuItem
                #label: 'Paste With Layout'
                #isButton: true
                #value: #pasteWithLayout
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPasteWithKeepingLayout
                #labelImage: #(#ResourceRetriever #Icon #pasteIcon)
            )
             #(#MenuItem
                #label: 'Delete'
                #isButton: true
                #value: #deleteTotalSelection
                #activeHelpKey: #editDelete
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever #Icon #deleteIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Move Up'
                #isButton: true
                #value: #doStepUp
                #activeHelpKey: #moveWidgetUp
                #enabled: #canChangeOrderInContainer
                #labelImage: #(#ResourceRetriever #Icon #upIcon)
            )
             #(#MenuItem
                #label: 'Move Down'
                #isButton: true
                #value: #doStepDown
                #activeHelpKey: #moveWidgetDown
                #enabled: #canChangeOrderInContainer
                #labelImage: #(#ResourceRetriever #Icon #downIcon)
            )
             #(#MenuItem
                #label: 'Move Into'
                #isButton: true
                #value: #doStepIn
                #activeHelpKey: #moveWidgetInto
                #enabled: #canMoveSelectionIntoContainer
                #labelImage: #(#ResourceRetriever #Icon #downRightIcon)
            )
             #(#MenuItem
                #label: 'Move Out'
                #isButton: true
                #value: #doStepOut
                #activeHelpKey: #moveWidgetOut
                #enabled: #canMoveSelectionOutOfContainer
                #labelImage: #(#ResourceRetriever #Icon #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:'aspects'!

aspectFor:aKey
    "returns the aspect for aKey"

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

canChangeOrderInContainer
    "returns a boolean value holder which is true if the widget order can be changed 
     within their container"

    ^ builder booleanValueAspectFor:#canChangeOrderInContainer
!

canExchangeSelectionLayouts
    "returns a boolean value holder which is true in case that the selection 
     consists of exactly 2 components
     and all widgets in the selection can change its layout through to a move or
     align operation"

    ^ builder booleanValueAspectFor:#canExchangeSelectionLayouts
!

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
!

canMoveSelection

    ^self canChangeOrderInContainer value or: [ 
     self canMoveSelectionOutOfContainer value or: [
     self canMoveSelectionOutOfContainer value]]
!

canMoveSelectionIntoContainer
    "returns a boolean value holder which is true in case that one widget 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 widget 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 widget is selected
     other than the root"

    ^ builder booleanValueAspectFor:#hasOneSelectionOtherThanCanvas
!

helpIcon

    ^Icon helpIcon
!

noteBookView
    "returns the notebook view; initialize the tools embedded in the notebook"

    |noteBook modifiedChannel applBuilder applWindow|

    (noteBook := builder bindingAt:#noteBookView) isNil ifTrue:[
        modifiedChannel := self modifiedChannel.
        noteBook := View new.
        builder aspectAt:#noteBookView put:noteBook.

        layoutTool := UILayoutTool new.
        layoutTool createBuilder.
        applBuilder := layoutTool builder.
        applWindow  := ApplicationSubView origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        applWindow level:0.
        layoutTool masterApplication:self.
        applBuilder window:applWindow.
        applWindow client:layoutTool spec:#windowSpec builder:applBuilder.
        applBuilder window:applWindow.
        layoutTool modifiedHolder:modifiedChannel.

        helpTool := UIHelpTool new.
        helpTool createBuilder.
        applBuilder := helpTool builder.
        applWindow  := ApplicationSubView origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        applWindow level:0.
        helpTool buildFromClass:specClass.
        helpTool masterApplication:self.
        applBuilder window:applWindow.
        applWindow client:helpTool spec:#windowSpec builder:applBuilder.
        applBuilder window:applWindow.
        helpTool modifiedHolder:modifiedChannel.

        specTool := UISpecificationTool new.
        specTool createBuilder.
        applBuilder := specTool builder.
        applWindow  := ApplicationSubView origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        specTool masterApplication:self.
        applWindow level:0.

        applBuilder window:applWindow.
        applWindow client:specTool spec:#windowSpec builder:applBuilder.
        applBuilder window:applWindow.

        specTool modifiedHolder:modifiedChannel.
    ].
    ^ 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 the section labels in the notebook"

    |holder|

    (holder := builder bindingAt:#tabList) isNil ifTrue:[
	builder aspectAt:#tabList put:(holder :=  #(Basics Details Layout) asValue).
    ].
    ^ holder
!

tabModel
    "returns a value holder which keeps the label of the current section in the notebook"

    |holder|

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

treeView
    "returns the tree view which holds all widget"

    ^ treeView
!

valueOfCanPasteWithKeepingLayout

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



! !

!UIPainter methodsFor:'building editors'!

openDataSetColumnEditor
    "opens a Table Column Editor on current widget"

    |cls loadedFromClass loadedFromSpec editor tableColumnsOrSelector|

    (cls := self resolveName:specClass) isNil ifTrue:[
	self askForSaving ifFalse: [^self].
	cls := self resolveName:specClass.
    ].
    self modifiedChannel value ifTrue:[
	(self confirm:'Accept changes made to spec ?') ifTrue:[
	    self accept
	]
    ].

    loadedFromSpec := loadedFromClass := false.
    editor := DataSetBuilder new.
    editor masterApplication:self.
    editor specClass: cls.
    editor rowClassName:(self specTool specification rowClassName).
    ((tableColumnsOrSelector := self specTool specification columnHolder) notNil and: 
    [cls class implements: tableColumnsOrSelector]) ifTrue: [
	editor openModalOnClass: cls andSelector: tableColumnsOrSelector.
	loadedFromClass := true.
    ] ifFalse: [       
	(tableColumnsOrSelector := self specTool specification columns) isNil ifTrue: [
	    editor openModal
	] ifFalse: [         
	    editor openModalOnResourceSpec:tableColumnsOrSelector.
	    loadedFromSpec := true
	].
    ].

    loadedFromClass ifTrue: [
	self specTool specification columns:nil.
	self specTool specification rowClassName:nil.
	self modifiedChannel value:true.
	self accept.
    ].

    (loadedFromSpec not and: [editor hasSaved and:[editor specSelector ~= tableColumnsOrSelector]]) ifTrue:[
	self specTool specification columnHolder:editor specSelector.
	self modifiedChannel value:true.
	self accept.
	^self
    ].
    loadedFromClass ifFalse: [
	self specTool specification columns:(editor columns).
	self specTool specification rowClassName:(editor rowClassName).
	self modifiedChannel value: editor modified.
    ].


!

openEditMenu
    "opens a Menu Editor on current widget"

    |cls selectorOrMenu editor selectedSpec spec|

    (cls := self resolveName:specClass) isNil ifTrue:[
	self askForSaving ifFalse: [^self].
	cls := self resolveName:specClass.
    ].

    cls notNil ifTrue:[
	spec := self specTool specification.

	self modifiedChannel value ifTrue:[
	    (self confirm:'Accept changes made to spec ?') ifTrue:[
		self accept
	    ]
	].

	(selectorOrMenu := spec 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:[
		spec menuSelector:editor specSelector.
		self modifiedChannel value:true.
		self accept
"/            ]
	].
    ]

    "Modified: / 16.7.1998 / 18:16:42 / cg"
!

openHierarchicalListEditor
    "opens a Hierarchical List Editor on current widget"

    |selector editor spec|

    (self resolveName:specClass) isNil ifTrue:[
	self askForSaving ifFalse: [^self]
    ].

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

    editor := HierarchicalListEditor new.
    editor masterApplication:self.
    editor openModalOnClass:specClass andSelector:selector.

    editor specSelector ~= selector ifTrue:[
	editor hasSaved ifTrue:[
	    spec hierarchicalList:editor specSelector.
	    self modifiedChannel value:true.
	    self accept
	]
    ]

    "Modified: / 16.7.1998 / 18:15:46 / cg"
!

openSubSpecGUIPainter
    "opens a GUI Painter on the current subspecification"

    |spec cls meta sel|

    (self resolveName:specClass) isNil ifTrue:[
	self askForSaving ifFalse: [^self]
    ]. 

    spec := self specTool specification.
    cls := spec majorKey.
    cls isNil ifTrue:[
	cls := specClass.
    ].
    (cls := self resolveName:cls inClass:(Smalltalk at: specClass asSymbol)) 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.

!

openTabListEditor
    "opens a Tab List Editor on current widget"

    |selector editor spec|

    (self resolveName:specClass) isNil ifTrue:[
	self askForSaving ifFalse: [^self]
    ].

    spec := self specTool specification.
    (selector := spec listSelector) isArray 
	ifTrue: [^self warn: 'Cannot open the Tab List Editor on an array!!'].

    editor := TabListEditor new.
    editor masterApplication:self.
    editor openModalOnClass:specClass andSelector:selector.

    editor specSelector ~= selector ifTrue:[
	editor hasSaved ifTrue:[
	    spec listSelector:editor specSelector.
	    self modifiedChannel value:true.
	    self accept.
	]
    ]

    "Modified: / 16.7.1998 / 18:15:14 / cg"
! !

!UIPainter methodsFor:'change & update'!

layoutChanged
    "called by the painter/canvas whenever the layout of the current selected
     widget has changed"

    self isModified ifFalse:[
        self layoutTool update.
        self clearModifiedFlag
    ]
!

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

    |property spec|

    (property := treeView propertySelected) notNil ifTrue:[
        spec := property spec copy.
        self specTool specification:spec.
        self setViewInLayoutTool:(property view) spec:spec.
        self clearModifiedFlag
    ] ifFalse:[
        self layoutTool layoutView notNil ifTrue:[
            self clearModifiedFlag.
            self treeSelection
        ]
    ]
!

update:something with:aParameter from:someObject
    "catches change notifications"

    |window|

    someObject == treeView model ifTrue:[
	(something == #selection
	or:[something == #selectionIndex]) ifTrue:[self treeSelection].
      ^ self
    ].

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

    someObject == self painterShown ifTrue:[
	"/ canvasShown toggle changed
	window := self painter topView.
	(someObject value) ifTrue:[
	    self raiseUIView:window
	] ifFalse:[
	    self hideUIView:window
	].
      ^ self
    ].

    "Modified: / 16.7.1998 / 19:09:57 / cg"
!

updateChannels
    "updates the channels"

    |canCutOrCopy canPaste clipboard sel treeSelection|

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

    treeView notNil
    ifTrue:
    [
        treeSelection := treeView selection.
        "/ the top-node cannot be cut, copied or pasted.
        canCutOrCopy := treeSelection size >= 1 and:[treeSelection first ~~ 1].
        clipboard := self getSelection.

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

        canPaste := (sel isKindOf:UISpecification) and: 
                    [treeSelection size  = 1 
                    and:[treeSelection 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").

"/    self modifiedChannel value: false.

    "Modified: / 16.7.1998 / 19:13:30 / cg"
! !

!UIPainter methodsFor:'defaults'!

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

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

    "Created: / 13.8.1998 / 20:33:05 / cg"
! !

!UIPainter methodsFor:'event handling'!

doesNotUnderstand:aMessage
    "if does not understand incoming messages, detour them to painter"

    |painter|

    painter := self painter.

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

! !

!UIPainter methodsFor:'help'!

defaultInfoLabel
    "returns the default info label"

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

    "Modified: / 20.6.1998 / 16:49:16 / cg"
! !

!UIPainter methodsFor:'private'!

askForModification
    "asks for window spec modification"

    |painter|

    painter := self painter.

    self askForSectionModification.    


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

    "Modified: / 20.5.1998 / 02:03:16 / cg"
!

askForSaving
    "asks for defining an application class"

    self askForSectionModification.    

    ((YesNoBox title:'No application class defined yet!!')        
	noText:'Cancel';
	yesText:'Define';
	showAtPointer;
	accepted) ifFalse: [^false].

    self doSave.

    ^true
!

askForSectionModification
    "asks for section modification in the notebook"

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

checkClassAndSelector
    "checks 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:[
	    cls := superclass 
			subclass:(specClass asSymbol)
			instanceVariableNames:''
			classVariableNames:''
			poolDictionaries:''
			category:'Applications'.

	    cls name ~= specClass ifTrue:[
		self information:'Created new class is ' , cls name.
		specClass := cls name
	    ].
	    ^ 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"
!

hideUIView:aView
    "hides the view which is an application or top view"

    aView beIndependent.
    aView unmap.
!

raiseTabView
    |appl|

    self isLayoutToolSelected ifTrue:[
        helpTool   window unmap.
        specTool   window unmap.
        layoutTool window realize.
    ] ifFalse:[
        self isHelpToolSelected ifTrue:[
            layoutTool window unmap.
            specTool   window unmap.
            helpTool   window realize.
        ] ifFalse:[
            specTool selection:tabSelection.
            helpTool   window unmap.
            layoutTool window unmap.
            specTool   window realize.

"/            specTool selection:tabSelection.
        ]
    ]

!

raiseUIView:aView
    "raise the view which is an application or top view"

    aView remap.
    aView bePartner.
!

resourceMessage: aString
    "reads the specClass and the specSelector by evaluating 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:
	[
	    self specClass:cls.
	    specSuperclass := cls superclass name.
	    specSelector := (msg at: 2) asSymbol.
	    ^true
	]
    ].
    ^false
!

setClass:cls selector:selector
    "sets the specClass and the specSelector under which the window spec should be saved"

    |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 spec:aSpec
    "sets view for layout tool"

    |type|

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

!

specClass:aClass
    "sets the specClass and updates the Help Tool"

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

    self helpTool buildFromClass:specClass.    
    self helpTool updateList.
    self clearModifiedFlag. 

! !

!UIPainter methodsFor:'private tools'!

helpTool
    "returns the help tool"

    helpTool isNil ifTrue:[self noteBookView].
  ^ helpTool
!

layoutTool
    "returns the layout tool"

    layoutTool isNil ifTrue:[self noteBookView].
  ^ layoutTool
!

painter
    "returns the canvas view"

    ^ treeView canvas
!

specTool
    "returns the spec tool"

    specTool isNil ifTrue:[self noteBookView].
  ^ specTool
! !

!UIPainter methodsFor:'queries'!

hasSpecClass
    "answers whether an application class is defined"

    ^ (self resolveName:specClass) notNil
!

hasSpecClassAndSelector
    "answers whether an application class and a selector under which
     the window spec is stored is defined"

    specSelector size > 1 ifTrue:[
	^ self hasSpecClass
    ].
    ^ false
!

isHelpToolSelected
    "answers whether the current selected section in the noteBook is the Help Tool"

    ^ tabSelection = UIHelpTool label
!

isLayoutToolSelected
    "answers whether the current selected section in the noteBook is the Layout Tool"

    ^ tabSelection = UILayoutTool label
!

isModified
    "answers whether the current window spec or a layout is modified"

    ^ self modifiedChannel value
!

isPainterEnabled
    "answers whether I am running in test mode"

    ^ self painter enabled
! !

!UIPainter methodsFor:'selection'!

tabSelection
    "returns the label of the current section in the notebook"

    ^ tabSelection
!

tabSelection:something
    "called whenever the section of the notebook has changed"

    |whatToDo|

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

    self isModified ifTrue:[
	whatToDo := DialogBox 
			confirmWithCancel:'Accept modifications in section ' , tabSelection printString asBoldText, '?'
			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 has changed"

    |view list spec slices size property tabComponent|

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

    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 spec:spec.
    self specTool specification:spec.

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

        view notNil ifTrue:[
            self treeView isCanvasSelected 
            ifFalse:
            [
                list := Array new:(size + 2).
                list at:(size + 2) put:(UILayoutTool label).
            ]
            ifTrue:
            [
                list := Array new:(size + 1).
                list at:(size + 1) put:(UILayoutTool label).
            ].
        ] ifFalse:[
            list := Array new:(size + 1).
        ].

        1 to:size do:[:i| list at:i put:((slices at:i) first asString)].
        self treeView isCanvasSelected ifFalse: [list at:(size + 1) put:(UIHelpTool label)].

        self tabList value:list.
        self showHelp:spec class name for:self.
        tabComponent enabled:true.

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

    self updateChannels
! !

!UIPainter methodsFor:'settings'!

generateAspectsAsInstanceVariables
    "if on, aspects are held as instance variables;
     if off (the default), they are kept in the bindings dictionary.
    "
    ^ UIPainterView generateAspectsAsInstanceVariables

    "Created: / 29.7.1998 / 11:17:59 / cg"
!

generateAspectsAsInstanceVariables:aBoolean
    "if on, aspects are held as instance variables;
     if off (the default), they are kept in the bindings dictionary.
    "
    ^ UIPainterView generateAspectsAsInstanceVariables:aBoolean

    "Created: / 29.7.1998 / 11:18:20 / cg"
!

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


! !

!UIPainter methodsFor:'startup / release'!

closeRequest
    "close request"

    self askForModification ifFalse:[^self].

    treeView model removeDependent:self.
    self painter release.

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

    super closeRequest.

!

closeRequestFor:aTopView
    "handles a close request for a specific view"

    |topView|

    (topView := self window) == 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: aMessageString
    "loads a window spec by evaluating aMessageString
     (which is something like 'fooClass windowSpec')"

    |readStream aClass aSelector|

    ((aMessageString size > 0) and: [self askForModification])
    ifTrue:[
        readStream := aMessageString 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)
            ]
        ]
    ]
!

openInterface:aSymbol
    "opens the interface on the selector aSymbol"

    |cls painterView painter topView galleryWindow icon|

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

    "/ the canvas ...

    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.

    super openInterface:aSymbol.

    topView := self window.
    topView label:'GUI Painter'.

    painterView openInGroup:(topView windowGroup).
    painterView application:self.

    "/ the selectionPanel ...

    selectionPanel := UISelectionPanel new.
    selectionPanel allButOpenInterface:#windowSpec.
    (galleryWindow := selectionPanel window) openInGroup:(topView windowGroup).
    selectionPanel openWindow.
    selectionPanel masterApplication:self.

    icon := Smalltalk imageFromFileNamed:'UIPainter.xbm' forClass:self class.
    topView iconLabel:'GUI Painter'.
    topView icon:icon.

    painterView iconLabel:'GUI Canvas'.
    painterView icon:icon.

    topView bePartner.
    painterView bePartner.
    galleryWindow bePartner.

    galleryWindow iconLabel:'GUI Gallery'.
    galleryWindow icon:icon.

    painterView topView raise.

!

openOnClass:aClass
    "opens the GUI Painter on aClass and #windowSpec"

    self openOnClass:aClass andSelector:#windowSpec
!

openOnClass:aClass andSelector:aSelector
    "opens the GUI Painter on aClass and aSelector
    "
    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].
    ].

    specSelector := aSelector.
    specClass := aClass.

    self openInterface.

"/    specSelector := aSelector.
"/    specClass := aClass.

    "Modified: / 21.8.1998 / 20:59:15 / cg"
!

postBuildWith: aBuilder
    "sets the root of the tree view as first selection;
     sets the grid parameters, if defined"

    |painter settings gridPara hspace vspace cls sel|

    super postBuildWith:aBuilder.

    cls := specClass.
    cls isString ifTrue:[
        cls := Smalltalk at:(cls string asSymbol)
    ].
    sel := specSelector.
    specSelector := nil.
    specClass    := nil.

    painter  := self painter.
    settings := self class settings.
    gridPara := painter gridParameters copy.
    hspace   := settings at: #HGridSpace ifAbsent:10.
    vspace   := settings at: #VGridSpace ifAbsent:10.
    gridPara at:1 put:hspace; at:2 put:vspace; at:5 put:hspace; at:6 put:vspace.
    painter gridParameters:gridPara.
    painter gridShown: (settings at: #GridShown ifAbsent:false).
    painter gridAlign: (settings at: #GridAlign ifAbsent:false).
    painter shown ifTrue:[painter clear].

    cls notNil ifTrue:[
        self setClass:cls selector:sel.

        (cls respondsTo:sel) ifTrue:[  
            painter setupFromSpec:(cls perform:sel).
        ]
    ].

    "Modified: / 22.8.1998 / 17:41:34 / cg"
!

postOpenWith: aBuilder
    "sets the initial selection"

    |myWindow canvasWindow canvasOrg galleryWindow 
     galleryOrg myOrg myCorner|

    super postOpenWith: aBuilder.
    treeView selection: #(1).
    aBuilder keyboardProcessor menuBar:nil.

    myWindow := self window.
    canvasWindow := self painter topView.
    galleryWindow := selectionPanel window.

    myOrg := myWindow origin.
    myCorner := myWindow corner.

    "/ try to lay out things non-overlapping
    "/ but only, if the window manager placed all windows
    "/ on top of each other
    myOrg = canvasWindow origin ifTrue:[

        canvasOrg := 10@20.
"/        myOrg := (device width - myWindow width - 20) @ 20.
        galleryOrg := (device width - galleryWindow width - 20) 
                      @ 
                      ((myWindow height + 20) min:(device height - galleryWindow height - 20)).
        myWindow origin:myOrg.

        canvasWindow origin:canvasOrg.
        galleryWindow origin:galleryOrg.

        galleryWindow raise.
        canvasWindow raise.
    ].

    "Modified: / 13.7.1999 / 21:26:52 / cg"
! !

!UIPainter methodsFor:'user actions'!

accept
    "accepts all modifications done to the attributes of the current section"

    |painter layout spec layoutTool layoutView t|

    self acceptChannel value:true; value:false.  "/ force editFields to accept
    self clearModifiedFlag.

    painter := self painter.
    spec := self specTool specification.

    self isLayoutToolSelected ifTrue:[
        layoutTool := self layoutTool.

        (layout := layoutTool layout) notNil ifTrue:[
            layoutTool layoutType == #Extent ifTrue:[
                layoutView := layoutTool layoutView.

                layoutView == painter topView ifTrue:[
                    layoutView extent:layout
                ] ifFalse:[
                    spec useDefaultExtent:(layoutTool aspectFor:#useDefaultExtent) value.
                    spec useDefaultExtent ifTrue:[
                        "/ temporarily unfreeze the widgets size
                        "/ (but remember, the old setting, which is actually
                        "/ controlled by the resizeForLabel attribute)
                        t := layoutView sizeFixed.
                        layoutView sizeFixed:false.
                        layout := layoutView preferredExtent.    
                        layoutView sizeFixed:t.
                    ].
                    painter setExtent:layout.
                    painter updateFromSpec:spec.
                ]
            ] ifFalse:[
                painter setLayout:layout
            ]
        ]
    ] ifFalse:[
        self isHelpToolSelected ifTrue:[
            self helpTool accept.      
            spec activeHelpKey:self helpTool helpKey.
        ].      
        painter updateFromSpec:spec
    ].

    modified := false.
!

addWidget: aSpecClass
    "adds a widget from aSpecClass to the current widget"

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

!

addWidgetOfSpec: aSpec
    "adds a widget from aSpec to the current widget"

    |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
    "cancels all modifications done to the attributes of the current section; 
     reread the old attributes"

    |spec key view|

    self isModified ifTrue:[
        (spec := self painter specForSelection) notNil ifTrue:[
            key := spec activeHelpKey.
        ].
        self helpTool helpKey:key.

        treeView isCanvasSelected ifTrue: [
            spec := treeView canvasSpec.
        ].
        self specTool specification:spec.
        view := self layoutTool layoutView.

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

doBrowseAspectMethods
    "opens a browser on the aspect methods"

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

    (methods := self painter aspectMethods) isEmpty ifTrue:[
	self warn:'No aspect methods found!!'.
	^ self.
    ].
    SystemBrowser browseMethods:methods title:'Aspect methods'.

!

doBrowseClass
    "opens a System Browser on the specClass"

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

    SystemBrowser openInClass:(self resolveName:specClass)
    
!

doDefineClassAndSelector
    "launches a dialog for defining class, superclass, and selector of the application"

    |again tmp helpDict helpKey helpTool|

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

    specClass := specClass isBehavior ifTrue:[specClass name]
                                      ifFalse:[specClass].

    helpTool := self helpTool.
    helpDict := helpTool dictionary.
    helpKey  := helpTool helpKey.
    helpTool buildFromClass:specClass.    
    helpTool dictionary declareAllFrom: helpDict.
    helpTool updateList.
    helpTool helpKey: helpKey.
    self clearModifiedFlag.
    helpTool modified: true.

    self updateInfoLabel

    "Modified: / 16.7.1998 / 18:26:33 / cg"
!

doDefineGrid
    "opens a dialog for the grid parameters"

    |hspace vspace bindings painter gridPara settings|

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

    bindings at:#showGrid    put:((settings at: #GridShown ifAbsent: [painter gridShown]) asValue).
    bindings at:#alignToGrid put:((settings at: #GridAlign ifAbsent: [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.

    settings at: #GridShown  put: (bindings at:#showGrid) value.
    settings at: #GridAlign  put: (bindings at:#alignToGrid) value.
    settings at: #HGridSpace put: hspace.
    settings at: #VGridSpace put: vspace.
    painter clear.

    "Modified: / 4.2.1999 / 15:36:34 / cg"
!

doGenerateAspectMethods
    "generates aspect and action methods for the application class"

    self askForSectionModification.

    (ReadStream on:self painter generateAspectMethods) fileIn.

!

doGenerateAspectSelectorsMethod
    "generates aspectSelectors method for the exported aspects"


    self askForSectionModification.

    (ReadStream on:self painter generateAspectSelectorsMethod) fileIn.

!

doGenerateHookMethods
    "generates hook methods for the application class"

    self askForSectionModification.

    (ReadStream on:self painter generateHookMethods) fileIn.

!

doGenerateMenuMethods
    "generates menu stub methods for the application class"

    self askForSectionModification.

    (ReadStream on:self painter generateMenuMethods) fileIn.

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

doInspectSpec
    "opens an inspector on the spec of the selected widget"

    |spec|

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


!

doInspectView
    "opens an inspector on the view of the selected widget"

    |selection|

    ((selection := self painter selection) isCollection and: [selection size >= 1]) ifTrue:[
	selection first inspect
    ] ifFalse: [
	selection inspect
    ]

!

doLoad
    "opens a ResourceSelectionBrowser for loading a window spec from a class"

    self askForModification ifFalse: [^nil].

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

doLoadSubspec
    "opens a ResourceSelectionBrowser for loading a sub spec from a class"

    |subSpecMessage|

    self askForSectionModification.

    (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
    "removes all widgets, specClass, and specSelector"

    self askForModification ifFalse: [^nil].
    specClass := specSelector := nil.
    self painter removeAll.
    treeView canvas topView name:  UIPainter defaultNameOfCanvas.
    treeView canvas topView label: UIPainter defaultNameOfCanvas.
    self helpTool doNew.
    self treeSelection.
    treeView selectedNode changed.
    self tabModel value: self tabList value first.
    self updateInfoLabel.
!

doOpenWidgetDocumentation
    "opens documentation for the selected widget"

    |spec document|

    (spec := self specForSelection) isNil ifTrue:[
        treeView isCanvasSelected ifTrue:[
            spec := nil
        ]
    ].
    spec notNil ifTrue:[
        document := 'tools/uipainter/', spec documentFileName,'.html'
    ] ifFalse: [
        document := 'tools/uipainter/WindowSpec.html'
    ].
    HTMLDocumentView openFullOnDocumentationFile: document 


!

doPickAView
    "changes the cursor for picking a view and builds a window spec from it"

    |view|

    self askForModification ifFalse: [^nil].

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

    self updateInfoLabel

!

doSave
    "saves the window spec"

    |code painter cls ns|

    self askForSectionModification.

    self hasSpecClassAndSelector ifFalse:[
        self doDefineClassAndSelector isNil ifTrue: [^nil]
    ].

    (specClass notNil and: [(cls := Smalltalk at: specClass asSymbol) isClass]) ifFalse:[   
        self warn:('Oops - cannot save - class not found: ' , specClass).
        ^nil
    ].

"/    specClass notNil ifTrue:[
"/        (specClass includes:$:) ifFalse:[
"/            (ns := Smalltalk defaultNameSpace) notNil ifTrue:[
"/                cls := ns at:specClass asSymbol
"/            ].
"/        ].
"/        cls isNil ifTrue:[
"/            (specClass startsWith:'Smalltalk::') ifTrue:[
"/                cls := Smalltalk at: (specClass copyFrom:12) asSymbol.
"/            ] ifFalse:[
"/                cls := Smalltalk at: specClass asSymbol.
"/            ]
"/        ].
"/        ns := cls nameSpace.
"/    ].
"/    cls isClass ifFalse:[   
"/        self warn:('Oops - cannot save - class not found: ' , specClass).
"/        ^nil
"/    ].
"/
"/    ns ~~ Smalltalk defaultNameSpace ifTrue:[
"/        specClass := ns name , '::' , cls nameWithoutNameSpacePrefix.
"/    ] ifFalse:[
"/        specClass := cls name.
"/    ].

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

    Transcript showCR:'generating windowSpec code...'.

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

    self doGenerateAspectSelectorsMethod.

    self helpTool installHelpSpecsOnClass:specClass.

    self updateInfoLabel.
    modified := false.
    painter resetModification.
    (cls class implements: specSelector) ifTrue:[
        self addToHistory: (specClass, ' ', specSelector) -> #loadFromMessage:.
    ].

!

doSaveAs
    "opens a ResourceSelectionBrowser for saving the window spec on a class"

    |resourceMessage|

    self askForSectionModification.

    (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
    "starts the application on the editing window spec"

    |cls application|

    self hasSpecClassAndSelector ifFalse:[
	self doSave isNil ifTrue: [^nil].
    ] ifTrue: [
	self askForSectionModification.    
	(modified or: [self painter isModified or: [self helpTool modified]])
	ifTrue:
	[
	    ((YesNoBox title:'Window Spec was modified!!')        
		noText:'Cancel';
		yesText:'Save it and start';
		showAtPointer;
		accepted) ifFalse: [^nil].
	    self doSave isNil ifTrue: [^nil]
	]
    ].

    cls := self resolveName:specClass.
    cls isNil ifTrue:[
	self warn:'Oops cannot start application - no class:' , specClass.
	^ nil
    ].
    ((application := cls new) respondsTo:#openInterface:) ifFalse:[
        ^ self warn:('The application does not respond to the ''openInterface:'' message.\\(maybe the spec is supposed to be used as subApplication/subCanvas)') withCRs.
    ].        
    application openInterface:specSelector
!

doStepDown
    "moves the selected widget one step down in the hierarchy"

    treeView doStepOver:1
!

doStepIn
    "moves the selected widget into the next widget as child"

    treeView doStepIn
!

doStepOut
    "moves the selected widget out of the parent widget"

    treeView doStepOut
!

doStepUp
    "moves the selected widget one step up in the hierarchy"

    treeView doStepOver:-1
!

doWindowSpec
    "opens a code view with the contents of the window spec"

    self askForSectionModification.

    CodeView 
	openWith: self painter generateWindowSpecMethodSource 
	title: 'Window Spec'

! !

!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 (UIPainterView)"

    ^ model root contents view


!

canvas:aCanvas
    "install canvas (UIPainterView)"

    |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 list key block cls canvas modelBlock|

    spec := WindowSpec new.
    canvas := self canvas.

    spec fromView:(canvas topView) callBack:nil.

    windowSpec notNil ifTrue:[
        spec copyValuesFromSpec:windowSpec.
    ].

    spec exportedAspects isNil ifTrue:[
        (     (cls  := canvas className) notNil
         and:[(cls  := canvas resolveName:cls) notNil]
        ) ifTrue:[
            list := cls perform:#aspectSelectors ifNotUnderstood:nil.
        ].
        spec setExportedAspectsFrom:list.
        windowSpec notNil ifTrue:[
            windowSpec exportedAspects:(spec exportedAspects).
        ]
    ].

    self propertiesDo:[:aProp| |aspect entry|
        spec exportedAspectsAddKey:(aProp model) type:nil.
        aProp spec aspectSelectors do:[:aKey|spec exportedAspectsAddKey:aKey type:nil].
        aProp spec actionSelectors do:[:aKey|spec exportedAspectsAddKey:aKey type:#action].
    ].
  ^ spec
!

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

exportedAspects
    "returns spec assigned to canvas"

    windowSpec isNil ifTrue:[^ #()].
    ^ windowSpec exportedAspects ? #()

!

itemOfView:aView
    "returns item assigned to view or nil"

    aView notNil ifTrue:[
	self allItemsDo:[:anItem|
	    (anItem contents view == aView) ifTrue:[^ anItem]
	]
    ].
    ^ nil


!

lastDrawnMaster
    "returns the lastDrawnMaster"

    ^ lastDrawnMaster


! !

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

propertiesDo:aOneArgBlock
    "evaluates the argument a block on each property"

    self allItemsDo:[:anItem| aOneArgBlock value:(anItem contents)]


!

propertyDetect:aOneArgBlock
    "evaluates 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
    "adds a new item"

    |parent| 

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

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

!

removeAll
    "removes all items other than canvas"

    lastDrawnMaster := nil.
    windowSpec := nil.

    self canvas subViews copy do:[:aView|
	"/ care to not destroy the transparent input view
	(aView isInputOnly) ifFalse:[aView destroy]
    ].
    model root name: UIPainter defaultNameOfCanvas asBoldText.
    model removeAllOtherThanRoot.

!

removeView:aView
    "removes 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 named:specNameSymbol
    "generates a full spec from aSpecArray"

    |fullSpec winSpec|

    fullSpec := FullSpec new.
    fullSpec name:specNameSymbol.

    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.

!

setAttributesFromWindowSpec:aWindowSpec
    "sets a window spec from aWindowSpec and applies some attributes
     to the canvas."

    |nm canvasView builder|

    windowSpec := WindowSpec new copyValuesFromSpec:aWindowSpec.
    canvasView := self canvas.

    builder := UIBuilder new isEditing:true.
    aWindowSpec setAttributesIn:canvasView with:builder.

    nm := aWindowSpec name.
    canvasView topView name:nm.
    self canvasNameChanged:nm.
    self application treeSelection.
! !

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

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

    ((sel := aSelection) isNil or:[sel isCollection]) ifFalse:[
	sel := Array with:sel
    ].

    (size := sel size) ~~ 0 ifTrue:[
	list := OrderedCollection new:size.

	sel do:[:aView||item|
	    (item := self itemOfView:aView) notNil ifTrue:[
		list add:item.
		model doMakeVisible:item.
	    ]
	].
	sel := list collect:[:anItem| self indexOfNode:anItem ].
    ].
    self cvsEventsDisabledDo:[ self selection:sel ].            




!

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

    item := self itemOfView:aView.

    item notNil ifTrue:[
	model doMakeVisible:item.

	(index := self indexOfNode:item) ~~ 0 ifTrue:[
	    oldSel := selection copy.
	    self addToSelection:index.
	    self selectionChangedFrom:oldSel
	]        
    ]            



!

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

    (     (item := self itemOfView:aView) notNil
     and:[(index := self indexOfNode:item) ~~ 0
     and:[self isInSelection:index]]
    ) ifTrue:[
	oldSel := selection copy.
	self removeFromSelection:index.
	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
    "evaluates the argument a block on each item other than the canvas"

    model root allChildrenDo:aOneArgBlock


! !

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

cvsEventsDisabledDo:aBlock
    "evaluates the block without raising selection changed notifications
     to canvas"

    |restoreCvsEvents|

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


!

doubleClicked
    "disables collapsing of the root item"

    self selectedNode == model root ifFalse:[
	super doubleClicked
    ]


!

redrawLabelAt:x y:yTop index:anIndex
    "draws a tiny rectangle for indicating the master node (first selected node)"

    |dX|

    super redrawLabelAt:x y:yTop index:anIndex.

    ((selection size > 1) and: [selection first == anIndex]) ifTrue:[
	dX := textInset - 1.
	self paint:(Color red). "/ self application painter handleMasterColor.
	self fillRectangleX:(x - dX - 2)
			  y:yTop + ((fontHeight - dX) // 2)
		      width:dX
		     height:dX
    ]
! !

!UIPainter::TreeView methodsFor:'initialization'!

initialize
    "initialize the tree view; multiple select and tree item actions"

    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:[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
    "returns the tree item label for 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 > 1 ifTrue: [
	    (listOfNodes at:lastDrawnMaster) retrieveLabel.
	    self redrawLine: lastDrawnMaster. 
	    lastDrawnMaster := selection first
	]
    ].
    size > 1 ifTrue:[
	selection first ~~ lastDrawnMaster ifTrue: [
	    (listOfNodes at:selection first) retrieveLabel.
	    lastDrawnMaster notNil ifTrue: [(listOfNodes at:lastDrawnMaster) retrieveLabel].
	    self redrawLine: lastDrawnMaster. 
	    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"

    ^(selection size == 1)  and: 
    [(selection at: 1) ~~ 1 and:   
    [self selectedNode parent children size > 1]] 


!

canExchangeSelectionLayouts 
    "returns true if the selections size is exactly 2
     and all widgets in the selection
     can change their layout through to a move or align operation"

    selection size == 2 ifFalse:[
        ^ false
    ].
    ^ self canMoveOrAlignSelection
!

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

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

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

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

canMoveSelectionIntoContainer
    "returns true in case that one widget 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 widget is selected which is contained within
     another widget"

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

    |selectedNode|

    (selectedNode := self selectedNode) notNil ifTrue:[
	(selectedNode := selectedNode parent) notNil ifTrue:[
	    ^ (selectedNode parent isNil or:[selectedNode 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:'searching'!

detectItemRespondsToView:aView
    "detects 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'!

doChangeHierarchyOf:anItem

    |canvas|

    anItem isNil ifTrue:[
	^ self
    ].
    self setSelection:nil.

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

doStepIn
    |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]]]
    ) ifFalse:[
	self doChangeHierarchyOf:prnt
    ]
!

doStepOut
    |item|

    ((item := self selectedNode) notNil and:[(item := item parent) notNil]) ifTrue:[
	self doChangeHierarchyOf:(item parent)
    ].
!

doStepOver:anIndex
    "moves 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
    ].
    idx := idx + anIndex.

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

    self setSelection:nil.
    model remove:item.
    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$'
! !