UIPainter.st
author Claus Gittinger <cg@exept.de>
Sat, 05 Jul 1997 16:15:12 +0200
changeset 214 e5aaf5e3bbf9
parent 206 1c3fb15ffd62
child 217 354ba46948b4
permissions -rw-r--r--
also install libtool2 & libui

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

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


ApplicationModel subclass:#UIPainter
	instanceVariableNames:'activeHelpTool layoutTool specTool objectList selectionPanel
		tabSelection specClass specSelector specSuperclass aspects'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

!UIPainter class methodsFor:'documentation'!

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

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

!

documentation
"
    GUI-Builder:
    this class allows the user to build its own applications providing a graphical
    user interface to buildin components and to define the behavior of the components
    during runtime. The resulting specifications can be installed as methods on 
    classes, typically subclasses of an ApplicationModel. These specifications
    are used by the UIBuilder to generate the application window and its component
    structues when open the application.

    [start with:]
        UIPainter open

    [author:]
        Claus Gittinger
        Claus Atzkern

    [see also:]
        UIBuilder
        ApplicationModel
        UISpecification
"

! !

!UIPainter class methodsFor:'instance creation'!

listHolder:aListHolder
    |application|

    application := self new.
    application objectList:aListHolder.
  ^ application open
!

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

    "Created: 1.7.1997 / 19:16:59 / cg"
!

painter:aBuilderView
    |application|

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

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

preferenceFor:aSymbol
    ^ false


! !

!UIPainter class methodsFor:'help specs'!

helpSpec
    "return a dictionary filled with helpKey -> helptext associations.
     These are used by the activeHelp tool.
    "
  ^ super helpSpec addPairsFrom:#(

#alignSelectionCenterVer
'align selection vertical'

#alignSelectionLeft
'align selected components to the left edge of the
dominant component ( underlined )'

#alignSelectionRight
'align selected components to the right edge of the
dominant component ( underlined )'

#alignSelectionLeftAndRight
'align selected components to the right and left edge
of the dominant component ( underlined )'

#alignSelectionTop
'align selected components to the top edge of the
dominant component ( underlined )'

#alignSelectionBottom
'align selected components to the bottom edge of the
dominant component ( underlined )'

#alignSelectionTopAndBottom
'align selected components to the top and bottom edge
of the dominant component ( underlined )'

#alignSelectionCenterVer
'align selected components horizontal to the center of
the dominant component ( underlined )'

#alignSelectionCenterHor
'align selected components vertical to the center of
the dominant component ( underlined )'

#spreadSelectionVer
'vertical spacing between selected components is made the same'

#spreadSelectionHor
'horizontal spacing between selected components is made the same'

#centerSelectionHor
'center components horizontal in contained view'

#centerSelectionVer
'center vertical horizontal in contained view'

#setToDefaultExtent
'set selected components to their default extent'

#setToDefaultWidth
'set selected components to their default width'

#setToDefaultHeight
'set selected components to their default height'

#copyExtent
'copy extent of the selected component'

#pasteExtent
'change extent of all selected components to the
last copied extent'

#pasteWidth
'change width of all selected components to the
last copied extent width'

#pasteHeight
'change height of all selected components to the
last copied extent height'

#copyLayout
'copy layout of the selected component'

#pasteLayout
'change layout of all selected components to the
last copied layout'

#pasteBuffer
'paste components at current mouse position'

#pasteWithLayout
'paste components without changing their layouts'

)




! !

!UIPainter class methodsFor:'icons'!

iconAlignB
    ^ Image fromFile:'b_alignB.xbm'

!

iconAlignCenterH
    ^ Image fromFile:'b_alignCH.xbm'

!

iconAlignCenterV
    ^ Image fromFile:'b_alignCV.xbm'

!

iconAlignL
    ^ Image fromFile:'b_alignL.xbm'
!

iconAlignLR
    ^ Image fromFile:'b_alignLR.xbm'

!

iconAlignR
    ^ Image fromFile:'b_alignR.xbm'

!

iconAlignT
    ^ Image fromFile:'b_alignT.xbm'

!

iconAlignTB
    ^ Image fromFile:'b_alignTB.xbm'

! !

!UIPainter class methodsFor:'interface specs'!

menuAlignment
    ^ #(#Menu #(
                #(#MenuItem
                        #'label:' 'align left'
                        #'value:' #alignSelectionLeft
                        #'labelImage:' #( ResourceRetriever nil iconAlignL )
                        #'activeHelpKey:' #alignSelectionLeft
                 )
                #(#MenuItem
                        #'label:' 'align right'
                        #'value:' #alignSelectionRight
                        #'labelImage:' #( ResourceRetriever nil iconAlignR )
                        #'activeHelpKey:' #alignSelectionRight
                 )
                #(#MenuItem
                        #'label:' 'align left & right'
                        #'value:' #alignSelectionLeftAndRight
                        #'labelImage:' #( ResourceRetriever nil iconAlignLR )
                        #'activeHelpKey:' #alignSelectionLeftAndRight
                 )
                #(#MenuItem
                        #'label:' 'align top'
                        #'value:' #alignSelectionTop
                        #'labelImage:' #( ResourceRetriever nil iconAlignT )
                        #'activeHelpKey:' #alignSelectionTop
                 )
                #(#MenuItem
                        #'label:' 'align bottom'
                        #'value:' #alignSelectionBottom
                        #'labelImage:' #( ResourceRetriever nil iconAlignB )
                        #'activeHelpKey:' #alignSelectionBottom
                 )
                #(#MenuItem
                        #'label:' 'align top & bottom'
                        #'value:' #alignSelectionTopAndBottom
                        #'labelImage:' #( ResourceRetriever nil iconAlignTB )
                        #'activeHelpKey:' #alignSelectionTopAndBottom
                 )
                #(#MenuItem
                        #'label:' 'align centered horizontal'
                        #'value:' #alignSelectionCenterHor
                        #'labelImage:' #( ResourceRetriever nil iconAlignCenterH )
                        #'activeHelpKey:' #alignSelectionCenterHor
                 )
                #(#MenuItem
                        #'label:' 'align centered vertical'
                        #'value:' #alignSelectionCenterVer
                        #'labelImage:' #( ResourceRetriever nil iconAlignCenterV )
                        #'activeHelpKey:' #alignSelectionCenterVer
                 )
                )
               #( 3 3 )
               nil
        )

!

menuPullDown
    ^ #(#Menu #(
        #(#MenuItem
                #'label:' 'file'
                #'value:' #file
                #'submenu:'
                        #(#Menu #(
                                 #(#MenuItem
                                        #'label:' 'new'
                                        #'value:' #doNew
                                  )
                                 #(#MenuItem
                                        #'label:' 'from class ...'
                                        #'value:' #doFromClass
                                  )
                                 #(#MenuItem
                                        #'label:' 'pick a view '
                                        #'value:' #doPickAView
                                  )
                                 #(#MenuItem
                                        #'label:' 'raise'
                                        #'value:' #doRaise
                                  )
                                 #(#MenuItem
                                        #'label:' '='
                                  )
                                 #(#MenuItem
                                        #'label:' 'quit'
                                        #'value:' #closeRequest
                                  )
                                 )
                                #( 3 )
                                nil
                       )
         )
        #(#MenuItem
                #'label:' 'misc'
                #'value:' #misc
                #'submenu:'
                        #(#Menu #(
                                #(#MenuItem
                                        #'label:' 'grid'
                                        #'value:' #grid
                                        #'submenu:'
                                                #(#Menu #(
                                                        #(#MenuItem
                                                                #'label:' 'show'
                                                                #'indication:' #gridShown:
                                                         )
                                                        #(#MenuItem
                                                                #'label:' 'align'
                                                                #'indication:' #gridAlign:
                                                         )
                                                        )
                                                        nil
                                                        nil
                                                 )
                                 )
                                #(#MenuItem
                                        #'label:' 'undo'
                                        #'value:' #undo
                                        #'submenu:'
                                                #(#Menu #(
                                                        #(#MenuItem
                                                                #'label:' 'last'
                                                                #'value:' #undoLast
                                                         )
                                                        #(#MenuItem
                                                                #'label:' 'menu'
                                                                #'value:' #openUndoMenu
                                                         )
                                                        #(#MenuItem
                                                                #'label:' 'delete'
                                                                #'value:' #removeUndoHistory
                                                         )
                                                        )
                                                        #(2)
                                                        nil
                                                 )
                                  )
                                )
                                nil
                                nil
                               )
         )
        #(#MenuItem
                #'label:' 'code'
                #'value:' #code
                #'submenu:'
                        #(#Menu #(
                                #(#MenuItem
                                        #'label:' 'class && method ...'
                                        #'value:' #defineClassAndSelector
                                 )
                                 #(#MenuItem
                                        #'label:' '='
                                  )
                                 #(#MenuItem
                                        #'label:' 'install window spec.'
                                        #'value:' #doInstallSpec
                                  )
                                 #(#MenuItem
                                        #'label:' 'install help spec.'
                                        #'value:' #doInstallHelp
                                  )
                                 #(#MenuItem
                                        #'label:' 'install aspects'
                                        #'value:' #doInstallAspects
                                  )
                                 #(#MenuItem
                                        #'label:' '='
                                  )
                                 #(#MenuItem
                                        #'label:' 'show window spec.'
                                        #'value:' #doWindowSpec
                                   )
                                 #(#MenuItem
                                        #'label:' '='
                                  )
                                 #(#MenuItem
                                        #'label:' 'browse application'
                                        #'value:' #doBrowseAppClass
                                  )
                                 #(#MenuItem
                                         #'label:' 'start  application'
                                         #'value:' #doStartApplication
                                  )
                                )
                                #( 4 )
                                nil
                          )
         )
        #(#MenuItem
                #'label:' 'test'
                #'nameKey:' #test
                #'value:' #test
                #'submenu:'
                        #(#Menu #(
                                #(#MenuItem
                                        #'label:' 'test mode'
                                        #'indication:' #testMode:
                                 )
                                )
                                nil
                                nil
                          )
         )
        )
        nil
        nil
      )
!

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

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

    "
     UIPainter new openOnClass:UIPainter andSelector:#nameAndSelectorSpec
     UIPainter new openInterface:#nameAndSelectorSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'uIPainterView'
              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
              #'label:' 'Painter'
              #'bounds:' #(#Rectangle 0 0 391 170)
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'classLabel'
                    #'layout:' #(#AlignmentOrigin 45 0.11 51 0 1 0.5)
                    #'label:' 'class:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#LabelSpec
                    #'name:' 'superClassLabel'
                    #'layout:' #(#AlignmentOrigin 45 0.11 77 0 1 0.5)
                    #'label:' 'superclass:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#LabelSpec
                    #'name:' 'selectorLabel'
                    #'layout:' #(#AlignmentOrigin 45 0.11 105 0 1 0.5)
                    #'label:' 'selector:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'methodNameField'
                    #'layout:' #(#LayoutFrame 47 0.11 95 0 -5 1.0 117 0)
                    #'tabable:' true
                    #'model:' #methodNameChannel
                )
                 #(#LabelSpec
                    #'name:' 'boxLabel'
                    #'layout:' #(#Point 5 10)
                    #'label:' 'class & selector for code:'
                    #'adjust:' #left
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'classNameField'
                    #'layout:' #(#LayoutFrame 47 0.11 39 0 -5 1.0 61 0)
                    #'tabable:' true
                    #'model:' #classNameChannel
                )
                 #(#ComboBoxSpec
                    #'name:' 'comboBox1'
                    #'layout:' #(#LayoutFrame 47 0.11 67 0 -5 1.0 89 0)
                    #'tabable:' true
                    #'model:' #superclassNameChannel
                    #'comboList:' #superclassNameDefaults
                )
                 #(#HorizontalPanelViewSpec
                    #'name:' 'commitPanel'
                    #'layout:' #(#LayoutFrame 0 0.0 -24 1.0 0 1.0 0 1.0)
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ActionButtonSpec
                              #'name:' 'button1'
                              #'label:' 'cancel'
                              #'tabable:' true
                              #'model:' #cancel
                              #'extent:' #(#Point 191 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'button2'
                              #'label:' 'ok'
                              #'tabable:' true
                              #'isDefault:' true
                              #'model:' #accept
                              #'extent:' #(#Point 191 24)
                          )
                        )
                    )
                    #'horizontalLayout:' #fitSpace
                    #'verticalLayout:' #fit
                    #'horizontalSpace:' 3
                    #'verticalSpace:' 3
                )
              )
          )
      )

    "Modified: 24.6.1997 / 18:50:14 / cg"
!

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

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

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

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'flags:' 0
          #'window:' 
           #(#WindowSpec
              #'name:' 'uIPainterView'
              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
              #'flags:' 0
              #'label:' 'Tree-View'
              #'bounds:' #(#Rectangle 0 0 524 456)
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#MenuPanelSpec
                    #'name:' 'menuPullDown'
                    #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 25 0)
                    #'flags:' 0
                    #'tabable:' true
                    #'menu:' #menuPullDown
                )
                 #(#MenuPanelSpec
                    #'name:' 'menuAlignment'
                    #'layout:' #(#LayoutFrame 0 0.0 29 0 233 0 54 0)
                    #'flags:' 0
                    #'tabable:' true
                    #'menu:' #menuAlignment
                    #'showSeparatingLines:' true
                )
                 #(#PanelViewSpec
                    #'name:' 'panelViewButtons'
                    #'layout:' #(#LayoutFrame -125 1.0 25 0.0 0 1.0 57 0.0)
                    #'flags:' 0
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ActionButtonSpec
                              #'name:' 'moveLeft'
                              #'flags:' 0
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveLeft.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionLeft
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveRight'
                              #'flags:' 0
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveRight.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionRight
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveUp'
                              #'flags:' 0
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveUp.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionUp
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveDown'
                              #'flags:' 0
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveDown.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionDown
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                        )
                    )
                    #'level:' 1
                    #'horizontalLayout:' #fitSpace
                    #'verticalLayout:' #fitSpace
                    #'horizontalSpace:' 4
                    #'verticalSpace:' 4
                )
                 #(#SequenceViewSpec
                    #'name:' 'objectTree'
                    #'layout:' #(#LayoutFrame 0 0.0 59 0.0 0 0.35 -25 1.0)
                    #'flags:' 0
                    #'enableChannel:' #enableChannel
                    #'tabable:' true
                    #'menu:' #objectListMenu
                    #'model:' #objectList
                    #'hasHorizontalScrollBar:' true
                    #'hasVerticalScrollBar:' true
                    #'miniScrollerHorizontal:' true
                    #'isMultiSelect:' true
                    #'doubleClickSelector:' #doubleClick
                    #'useIndex:' true
                )
                 #(#NoteBookViewSpec
                    #'name:' 'noteBook'
                    #'layout:' #(#LayoutFrame 0 0.35 59 0.0 0 1.0 -55 1.0)
                    #'flags:' 0
                    #'enableChannel:' #enableChannel
                    #'tabable:' true
                    #'menu:' #tabList
                    #'style:' 
                     #(#FontDescription
                        #helvetica #medium
                        #roman #'10'
                    )
                    #'model:' #tabModel
                    #'tabWidget:' #Window
                    #'canvas:' #noteBookView
                )
                 #(#HorizontalPanelViewSpec
                    #'name:' 'modifyPanel'
                    #'layout:' #(#LayoutFrame 0 0.35 -55 1.0 0 1.0 -25 1.0)
                    #'flags:' 0
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ActionButtonSpec
                              #'name:' 'cancelButton'
                              #'flags:' 0
                              #'label:' 'cancel'
                              #'tabable:' true
                              #'model:' #cancel
                              #'enableChannel:' #modifiedChannel
                              #'extent:' #(#Point 166 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'acceptButton'
                              #'flags:' 0
                              #'label:' 'ok'
                              #'tabable:' true
                              #'model:' #accept
                              #'enableChannel:' #modifiedChannel
                              #'extent:' #(#Point 166 24)
                          )
                        )
                    )
                    #'level:' 0
                    #'horizontalLayout:' #fitSpace
                    #'verticalLayout:' #fitSpace
                    #'horizontalSpace:' 3
                    #'verticalSpace:' 3
                )
                 #(#LabelSpec
                    #'name:' 'helpInfo'
                    #'layout:' #(#LayoutFrame 2 0.0 -25 1.0 -2 1.0 -2 1.0)
                    #'flags:' 0
                    #'label:' ''
                    #'level:' -1
                    #'adjust:' #left
                )
                 #(#ToggleSpec
                    #'name:' 'galleryLabel'
                    #'layout:' #(#LayoutFrame -162 1.0 1 0 -82 1.0 23 0)
                    #'flags:' 0
                    #'label:' 'Gallery'
                    #'model:' #galleryShown
                    #'isTriggerOnDown:' true
                    #'showLamp:' true
                    #'lampColor:' #(#Color 100.0 100.0 0.0)
                )
                 #(#ToggleSpec
                    #'name:' 'painterLabel'
                    #'layout:' #(#LayoutFrame -81 1.0 1 0 -1 1.0 23 0)
                    #'flags:' 0
                    #'label:' 'Painter'
                    #'model:' #painterShown
                    #'isTriggerOnDown:' true
                    #'showLamp:' true
                    #'lampColor:' #(#Color 100.0 100.0 0.0)
                )
              )
          )
      )
! !

!UIPainter methodsFor:'actions'!

accept
    |layout|

    objectList removeDependent:self.

    self isLayoutToolSelected ifTrue:[
        (layout := layoutTool layout) notNil ifTrue:[
            layoutTool layoutType == #Extent ifTrue:[
                self painter setExtent:layout
            ] ifFalse:[
                self painter setLayout:layout
            ]
        ]
    ] ifFalse:[
        self isHelpToolSelected ifTrue:[
            activeHelpTool accept
        ].
        self painter updateFromSpec:(specTool specification).
    ].
    self modifiedChannel value:false.
    objectList addDependent:self.

!

cancel
    "cancel all changes and read back attributes from current view
    "
    self modifiedChannel value ifTrue:[
        specTool specification:(self painter specForSelection).
        layoutTool layoutView:(layoutTool layoutView).
        self modifiedChannel value:false.
    ]
!

doubleClick
    objectList selectGroup
! !

!UIPainter methodsFor:'active help'!

activeHelpTool
    "setup help tool
    "
    activeHelpTool isNil ifTrue:[
        activeHelpTool := UIHelpTool new.
        activeHelpTool helpSpecFrom:specClass.
    ].
    ^ activeHelpTool
!

showHelp:aHelpText for:view
    "hook to allow an application to display active help
     texts in its own info area.
     This method may be redefined in a concrete application.
     If it returns false, the ActiveHelp manager will popup a
     bubble with the help text."

    |l|

    (l := self builder componentAt:#helpInfo) notNil ifTrue:[
        aHelpText replaceAll:(Character cr) by:(Character space).
        l label:aHelpText.
      ^ true.
    ].
    ^ false


! !

!UIPainter methodsFor:'aspects'!

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

galleryShown
    |holder|

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

!

menuAlignment
    |menu channel|

    channel := self enableChannel.

    menu := Menu new.
    menu fromLiteralArrayEncoding:(self class menuAlignment).
    menu receiver:self.
    menu menuItems do:[:anItem| anItem enabled:channel].
  ^ menu
!

menuPullDown
    |menu channel|

    channel := self enableChannel.

    menu := Menu new.
    menu fromLiteralArrayEncoding:(self class menuPullDown).
    menu receiver:self.

    menu menuItems do:[:anItem| 
        anItem nameKey ~~ #test ifTrue:[anItem enabled:channel]
                               ifFalse:[anItem value:channel].
    ].
  ^ menu
!

modifiedChannel

    |holder|

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

noteBookView
    "automatically generated by UIPainter ..."

    |noteBook channel n1 n2|

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

        layoutTool masterApplication:self.
        specTool   masterApplication:self.

        n1 := SubCanvas origin:0.0@0.0 corner:1.0@1.0 in:noteBook.
        n2 := SubCanvas origin:0.0@0.0 corner:1.0@1.0 in:noteBook.

        n1 client:layoutTool.
        specTool builder:(n2 client:specTool).

        layoutTool masterApplication:self.
        specTool   masterApplication:self.
        layoutTool modifiedHolder:channel.
        specTool   modifiedHolder:channel.
        builder aspectAt:#noteBookView put:noteBook.
    ].
    ^ noteBook
!

objectList
    ^ objectList
!

objectListMenu
    "returns a block which returns the menu
     !!hack!!
    "
    ^ [ self painter showMiddleButtonMenu ].



!

painterShown
    |holder|

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

!

tabList
    "automatically generated by UIPainter ..."

    |holder|

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

tabModel
    "automatically generated by UIPainter ..."

    |holder|

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

!UIPainter methodsFor:'binding access'!

aspectFor:aKey
    "check wether aspect is assigned to a label icon
    "
    (aKey startsWith:'LABEL') ifFalse:[
        ^ aspects at:aKey ifAbsent:[ super aspectFor:aKey ]
    ].
  ^ Image fromFile:(aKey copyFrom:(('LABEL' size) + 1))
! !

!UIPainter methodsFor:'change & update'!

update:something with:aParameter from:someObject

    (someObject == objectList and:[something ~~ #list]) ifTrue:[
        something ~~ #layout ifTrue:[
            self objectListChanged
        ] ifFalse:[
            self modifiedChannel value ifTrue:[
                ^ self
            ].
            layoutTool update
        ].
      ^ self modifiedChannel value:false
    ].

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

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

! !

!UIPainter methodsFor:'event handling'!

doesNotUnderstand:aMessage
   |painter|

   painter := self painter.

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

!

objectListChanged
    "something changed in the painter view
    "
    |oldSelection view slices list spec props size nameOfSpec|

    props := objectList selectedProperty.
    oldSelection := tabSelection.
    tabSelection := nil.

    props isNil ifFalse:[
        view := props view.
        spec := props spec copy.

        layoutTool layoutView == view ifFalse:[
            slices := spec class slices.
            size   := slices size + 1.
            list   := Array new:size.
            slices keysAndValuesDo:[:i :s|list at:i put:(s first asString)].
            list at:size put:(layoutTool class label).
            (self tabList) value:list.
        ] ifTrue:[
            list := self tabList value
        ].
        (list findFirst:[:n| n = oldSelection ]) ~~ 0 ifTrue:[
            tabSelection := oldSelection
        ] ifFalse:[
            tabSelection := list first
        ].
        nameOfSpec := spec class name.
    ] ifTrue:[
        nameOfSpec := ''
    ].

    self showHelp:nameOfSpec for:nil.

    layoutTool layoutView:view.
    specTool specification:spec.

    tabSelection notNil ifTrue:[
        self isLayoutToolSelected ifTrue:[
            (self noteBookView subViews at:1) raise
        ] ifFalse:[
            specTool selection:tabSelection.
            (self noteBookView subViews at:2) raise
        ]
    ].

    (builder componentAt:#noteBook) setSelection:tabSelection.
    self modifiedChannel value:false.
! !

!UIPainter methodsFor:'private'!

hideUIView:aView
    aView beIndependent.
    aView unmap.
!

painter
    ^ objectList painter
!

raiseUIView:aView
    aView map.
    aView bePartner.
!

setClass:cls selector:selector
    |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 ? '').

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

    "Modified: 24.6.1997 / 19:07:01 / cg"
! !

!UIPainter methodsFor:'queries'!

isHelpToolSelected
    ^ tabSelection = 'Help'
!

isLayoutToolSelected
    ^ tabSelection = layoutTool class label
! !

!UIPainter methodsFor:'selection'!

tabSelection
    ^ tabSelection
!

tabSelection:something
    |raiseViewIdx|

    something notNil ifTrue:[
        raiseViewIdx := 1.
        tabSelection := something.

        self isLayoutToolSelected ifFalse:[
            specTool selection:tabSelection.
            raiseViewIdx := 2
        ].
        (self noteBookView subViews at:raiseViewIdx) raise.
        self cancel.
    ]
! !

!UIPainter methodsFor:'startup / release'!

closeRequest
    "close all windows open by builder
    "
    |anyUnsavedChanges|

    objectList painter isModified ifTrue:[
        (self confirm:'quit without saving ?') ifFalse:[
            ^ self
        ]
    ].

    objectList removeDependent:self.
    objectList painter release.

    selectionPanel notNil ifTrue:[
        selectionPanel masterApplication:nil.
        selectionPanel closeRequest
    ].
    selectionPanel := nil.
    layoutTool     := nil.
    objectList     := nil.
    activeHelpTool := nil.

    super closeRequest.

!

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

    topView := self window.

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

openInterface
    "open interfaces
    "
    |painterView painter cls topView|

    aspects := IdentityDictionary new.

    aspects at:#classNameChannel put:(
        (specClass notNil ifTrue:[specClass]
                         ifFalse:['NewApplication']) asValue
    ).
    specSuperclass isNil ifTrue:[
        specClass notNil ifTrue:[
            (cls := Smalltalk at:specClass asSymbol) 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
    ).

    painterView := StandardSystemView new.
    painterView label:'unnamed canvas'.
    painterView extent:300@300.

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

    objectList := painter listHolder.
    objectList addDependent:self.

    super openInterface.

    topView := self window.
    topView bePartner.
    topView label:'Interface Builder'.
    topView icon:(Image fromFile:'bitmaps/Builder.xbm' resolution:100).

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

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

openNewWindowCanvas
    "open new
    "
    self open.


!

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

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

    aClass isNil ifTrue:[
        self warn:'nil class given (class was probably renamed ?)'.
    ].

    self openInterface.

    aClass notNil ifTrue:[
        painter        := self painter.

        self setClass:aClass selector:aSelector.
"/        specClass      := aClass name.
"/        specSuperclass := aClass superclass name.
"/        specSelector   := aSelector.
"/
"/        (aspects at:#classNameChannel) value:specClass.
"/        (aspects at:#superclassNameChannel) value:specSuperclass.
"/        (aspects at:#methodNameChannel) value:specSelector asSymbol.
"/
"/        painter 
"/            className:aClass name 
"/            superclassName:aClass superclass name
"/            selector:aSelector.

        (aClass respondsTo:aSelector) ifTrue:[
            painter setupFromSpec:(aClass perform:aSelector).
        ]
    ]

    "Modified: 1.7.1997 / 19:18:54 / cg"
! !

!UIPainter methodsFor:'user interaction - dialog'!

checkClassAndSelector
    "check for class & superclass"

    |superclass cls|

    specClass isNil ifTrue:[^ false].

    specClass isBehavior ifFalse:[
        cls := Smalltalk at:specClass asSymbol
    ] ifTrue:[
        cls := specClass
    ].
    cls isNil ifTrue:[
        (superclass := Smalltalk at:specSuperclass asSymbol) isNil ifTrue:[
            self warn:'no class named ' , specSuperclass , ' exists.'.
            ^ false.
        ].
        (self confirm:'create ' , specClass , ' ?') ifTrue:[
            superclass subclass:(specClass asSymbol)
                       instanceVariableNames:''
                       classVariableNames:''
                       poolDictionaries:''
                       category:'New-Applications'.
            ^ true.
        ].
        ^ false.
    ].
    cls isBehavior ifFalse:[
        self warn:'a global named ' , specClass , ' exists, but is no class.'.
        ^ false.
    ].

    specSuperclass isBehavior ifFalse:[
        specSuperclass isEmpty ifFalse:[
            superclass := Smalltalk at:specSuperclass asSymbol
        ] 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: 25.6.1997 / 13:37:11 / cg"
!

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

    |again tmp|

    [
        again := false.

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

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

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

        (self openDialogInterface:#nameAndSelectorSpec) 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.
            ]
        ]

    ] doWhile:[again]

    "Modified: 17.6.1997 / 14:42:02 / cg"
! !

!UIPainter methodsFor:'user interaction - pullDown'!

doBrowseAppClass
    "open a browser on the class"

    |cls|

    specClass isNil ifTrue:[
        ^ self information:'no class yet'.
    ].

    specClass isBehavior ifFalse:[
        cls := Smalltalk at:specClass asSymbol
    ] ifTrue:[
        cls := specClass
    ].

    cls isNil ifTrue:[
        ^ self information:'no class yet'.
    ].

    SystemBrowser openInClass:cls


!

doFromClass
    |className methodName cls sel accepted failed spec s painter|

    objectList painter isModified ifTrue:[
        (self confirm:'edit another interface without saving your modifications ?') ifFalse:[
            ^ self
        ]
    ].

    className  := (specClass ? '') asValue.
    methodName := (specSelector ? '') asValue.
    painter    := self painter.

    (s := painter className) notNil ifTrue:[
        className value:s
    ].
    (s := painter methodName) notNil ifTrue:[
        methodName value:s
    ].

    failed := false.
    [
        accepted :=
            (DialogBox new
                addTextLabel:'Classes name:';
                addInputFieldOn:className; 
                addVerticalSpace;
                addTextLabel:'methods name:';
                addInputFieldOn:methodName; 
                addAbortButton; 
                addOkButton; 
                open
            ) accepted.

         accepted ifTrue:[
            cls := Smalltalk classNamed:className value.
            cls isNil ifTrue:[
                failed := true.
                self warn:'no such class'.
            ] ifFalse:[
                sel := methodName value asSymbol.
                (cls respondsTo:sel ) ifFalse:[
                    failed := true.
                    self warn:'no such method'
                ] ifTrue:[
                    spec := cls perform:sel.
                    spec isArray ifFalse:[
                        failed := true.
                        self warn:'not a windowSpec method'    
                    ].
                    "/ ok, got it
                
                    self setClass:cls selector:sel.

                    painter setupFromSpec:spec.

                    ^ self
                 ]
            ]
         ]
    ] doWhile:[accepted and:[failed]].

    "Modified: 24.6.1997 / 18:59:29 / cg"
!

doInstallAspects
    |code|

    (specClass isNil or:[specSelector isNil]) ifTrue:[
        self defineClassAndSelector
    ].

    self checkClassAndSelector ifFalse:[
        ^ self
    ].

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

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

!

doInstallHelp
    "install help text
    "
    activeHelpTool notNil ifTrue:[
        activeHelpTool installHelpSpecInto:specClass
    ] ifFalse:[
        self information:'no help text defined'
    ]    
!

doInstallSpec
    |code painter|

    (specClass isNil or:[specSelector isNil]) ifTrue:[
        self defineClassAndSelector
    ].

    self checkClassAndSelector ifFalse:[
        ^ self
    ].
    painter := self painter.

    painter className:specClass
       superclassName:specSuperclass
             selector:specSelector.

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

!

doNew
    objectList painter isModified ifTrue:[
        (self confirm:'new interface without saving your modifications ?') ifFalse:[
            ^ self
        ]
    ].

    self removeAll

    "Modified: 17.6.1997 / 12:33:31 / cg"
!

doPickAView
    |painter view cls spec|

    objectList painter isModified ifTrue:[
        (self confirm:'pick another interface without saving your modifications ?') ifFalse:[
            ^ self
        ]
    ].

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

         "/ ok, got it

            view application notNil ifTrue:[
                cls := view application class
            ] ifFalse:[
                cls := view class
            ].
            self setClass:cls selector:nil.

            painter setupFromSpec:spec.
        ]
    ]

    "Modified: 24.6.1997 / 19:02:57 / cg"
!

doRaise
    |top x|

    top := self painter topView.
    top realized ifFalse:[
        self painterShown value:true
    ].
    top raise.

    top := selectionPanel window.
    top realized ifFalse:[
        self galleryShown value:true
    ].
    top raise.
!

doStartApplication
    |cls|

    (specClass isNil or:[specSelector isNil]) ifTrue:[
        ^ self information:'no class or selector defined'.
    ].

    specClass isBehavior ifFalse:[
        cls := Smalltalk at:specClass asSymbol
    ] ifTrue:[
        cls := specClass
    ].

    cls isNil ifTrue:[
        ^ self information:'class not existant'.
    ].

    (cls respondsTo:specSelector) ifFalse:[
self halt.
        ^ self information:('no method for: #' 
                             , specSelector , ' in ' , cls name ,
                             '\\(did you install the spec ?)') withCRs.
    ].
    cls new openInterface:specSelector

    "Modified: 17.6.1997 / 14:40:21 / cg"
!

doWindowSpec
   |code code2 v|

   code := self painter generateWindowSpecMethodSource.

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

! !

!UIPainter class methodsFor:'documentation'!

version
    ^ '$Header$'
! !