UIPainter.st
author ca
Fri, 20 Jun 1997 19:33:06 +0200
changeset 166 cd5699643975
parent 161 12a70f62f414
child 168 8a79add2260f
permissions -rw-r--r--
add tools: layout and specification tool

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

    [see also:]
        UIBuilder
        ApplicationModel
        UISpecification
"

! !

!UIPainter class methodsFor:'instance creation'!

listHolder:aListHolder
    |application|

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

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

    |dict|

    dict := super helpSpec.
    dict at:#maxChars put:'set the maximum number of
characters that are allowed
in the editfield.'.
    dict at:#id put:'enter the name of the field
here. This ID can be used
by the applicationModel
to access components,
using #componentAt:<key>'.
    ^ dict
! !

!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 )
                 )
                #(#MenuItem
                        #'label:' 'align right'
                        #'value:' #alignSelectionRight
                        #'labelImage:' #( ResourceRetriever nil iconAlignR )
                 )
                #(#MenuItem
                        #'label:' 'align left & right'
                        #'value:' #alignSelectionLeftAndRight
                        #'labelImage:' #( ResourceRetriever nil iconAlignLR )
                 )
                #(#MenuItem
                        #'label:' 'align top'
                        #'value:' #alignSelectionTop
                        #'labelImage:' #( ResourceRetriever nil iconAlignT )
                 )
                #(#MenuItem
                        #'label:' 'align bottom'
                        #'value:' #alignSelectionBottom
                        #'labelImage:' #( ResourceRetriever nil iconAlignB )
                 )
                #(#MenuItem
                        #'label:' 'align top & bottom'
                        #'value:' #alignSelectionTopAndBottom
                        #'labelImage:' #( ResourceRetriever nil iconAlignTB )
                 )
                #(#MenuItem
                        #'label:' 'align centered horizontal'
                        #'value:' #alignSelectionCenterHor
                        #'labelImage:' #( ResourceRetriever nil iconAlignCenterH )
                 )
                #(#MenuItem
                        #'label:' 'align centered vertical'
                        #'value:' #alignSelectionCenterVer
                        #'labelImage:' #( ResourceRetriever nil iconAlignCenterV )
                 )
                )
               #( 4 2 )
               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:' 'quit'
                                        #'value:' #closeRequest
                                  )
                                 )
                                #(3 1)
                                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:' 'install spec'
                                        #'value:' #doInstallSpec
                                  )
                                 #(#MenuItem
                                        #'label:' 'install help spec'
                                        #'value:' #doInstallHelp
                                  )
                                 #(#MenuItem
                                        #'label:' 'install aspects'
                                        #'value:' #doInstallAspects
                                  )
                                 #(#MenuItem
                                        #'label:' 'show windowSpec'
                                        #'value:' #doWindowSpec
                                   )
                                #(#MenuItem
                                        #'label:' 'browse application'
                                        #'value:' #doBrowseAppClass
                                 )
                                #(#MenuItem
                                        #'label:' 'start application'
                                        #'value:' #doStartApplication
                                 )
                                )
                                #( 1 3 1)
                                nil
                          )
         )
        #(#MenuItem
                #'label:' 'test'
                #'nameKey:' #test
                #'value:' #test
                #'submenu:'
                        #(#Menu #(
                                #(#MenuItem
                                        #'label:' 'test mode'
                                        #'indication:' #testMode:
                                 )
                                )
                                nil
                                nil
                          )
         )
        )
        nil
        nil
      )

    "Modified: 17.6.1997 / 12:30:17 / cg"
!

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:' 'unnamed canvas'
              #'bounds:' #(#Rectangle 0 0 392 223)
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'label1'
                    #'layout:' #(#LayoutFrame 10 0 50 0 110 0 70 0)
                    #'label:' 'class:'
                    #'adjust:' #right
                )
                 #(#LabelSpec
                    #'name:' 'label2'
                    #'layout:' #(#LayoutFrame 10 0 90 0 110 0 110 0)
                    #'label:' 'superclass:'
                    #'adjust:' #right
                )
                 #(#LabelSpec
                    #'name:' 'label3'
                    #'layout:' #(#LayoutFrame 10 0 130 0 110 0 150 0)
                    #'label:' 'selector:'
                    #'adjust:' #right
                )
                 #(#InputFieldSpec
                    #'name:' 'classNameField'
                    #'layout:' #(#LayoutFrame 120 0 50 0 -2 1.0 72 0)
                    #'tabable:' true
                    #'model:' #classNameChannel
                )
                 #(#InputFieldSpec
                    #'name:' 'methodNameField'
                    #'layout:' #(#LayoutFrame 120 0 130 0 -2 1.0 152 0)
                    #'tabable:' true
                    #'model:' #methodNameChannel
                )
                 #(#ActionButtonSpec
                    #'name:' 'button1'
                    #'layout:' #(#AlignmentOrigin -2 0.5 195 0 1 0.5)
                    #'label:' 'cancel'
                    #'tabable:' true
                    #'model:' #cancel
                )
                 #(#ActionButtonSpec
                    #'name:' 'button2'
                    #'layout:' #(#AlignmentOrigin 2 0.5 195 0 0 0.5)
                    #'label:' 'ok'
                    #'tabable:' true
                    #'isDefault:' true
                    #'model:' #accept
                )
                 #(#LabelSpec
                    #'name:' 'boxLabel'
                    #'layout:' #(#LayoutFrame 0 0.0 11 0 0 1.0 32 0)
                    #'label:' 'class & selector for code:'
                    #'adjust:' #left
                )
                 #(#ComboBoxSpec
                    #'name:' 'comboBox1'
                    #'layout:' #(#LayoutFrame 120 0 90 0 -2 1.0 112 0)
                    #'tabable:' true
                    #'model:' #superclassNameChannel
                    #'immediateAccept:' false
                    #'acceptOnLeave:' true
                    #'acceptOnLostFocus:' true
                    #'comboList:' #superclassNameDefaults
                )
              )
          )
      )

    "Modified: 17.6.1997 / 13:02:12 / 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
          #'window:' 
           #(#WindowSpec
              #'name:' 'uIPainterView'
              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
              #'label:' 'Tree-View'
              #'bounds:' #(#Rectangle 0 0 478 429)
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#MenuPanelSpec
                    #'name:' 'menuPullDown'
                    #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 24 0)
                    #'tabable:' true
                    #'menu:' #menuPullDown
                )
                 #(#MenuPanelSpec
                    #'name:' 'menuAlignment'
                    #'layout:' #(#LayoutFrame 0 0.0 29 0 233 0 54 0)
                    #'tabable:' true
                    #'menu:' #menuAlignment
                    #'showSeparatingLines:' true
                )
                 #(#PanelViewSpec
                    #'name:' 'panelViewButtons'
                    #'layout:' #(#LayoutFrame -125 1.0 25 0.0 0 1.0 57 0.0)
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ActionButtonSpec
                              #'name:' 'moveLeft'
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveLeft.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionLeft
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveRight'
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveRight.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionRight
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveUp'
                              #'label:' ''
                              #'translateLabel:' true
                              #'labelChannel:' #'LABELb_moveUp.xbm'
                              #'tabable:' true
                              #'defaultable:' true
                              #'model:' #moveSelectionUp
                              #'isTriggerOnDown:' true
                              #'enableChannel:' #enableChannel
                              #'extent:' #(#Point 26 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'moveDown'
                              #'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)
                    #'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)
                    #'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)
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#ActionButtonSpec
                              #'name:' 'cancelButton'
                              #'label:' 'cancel'
                              #'tabable:' true
                              #'model:' #cancel
                              #'enableChannel:' #modifiedChannel
                              #'extent:' #(#Point 151 24)
                          )
                           #(#ActionButtonSpec
                              #'name:' 'acceptButton'
                              #'label:' 'ok'
                              #'tabable:' true
                              #'model:' #accept
                              #'enableChannel:' #modifiedChannel
                              #'extent:' #(#Point 151 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)
                    #'label:' ''
                    #'level:' -1
                    #'adjust:' #left
                )
              )
          )
      )
! !

!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 specEdited).
    ].
    self modifiedChannel value:false.
    objectList addDependent:self.

!

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

doubleClick
    objectList selectGroup
! !

!UIPainter methodsFor:'active help'!

activeHelpTool
    |cls|

    activeHelpTool isNil ifTrue:[
        activeHelpTool := UIHelpTool new.

        specClass notNil ifTrue:[
            specClass isBehavior ifFalse:[
                cls := Smalltalk at:specClass asSymbol
            ] ifTrue:[
                cls := specClass
            ].
            (cls isSubclassOf:UISpecification) ifTrue:[
                cls := self class
            ].
            activeHelpTool dictionary:(cls helpSpec).
        ].
    ].
    ^ activeHelpTool

    "Modified: 17.6.1997 / 12:51:15 / cg"
!

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
!

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



!

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

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

    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
        ]
    ].
    layoutTool layoutView:view.
    specTool   specEdited: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) selection:tabSelection.
    self modifiedChannel value:false.
! !

!UIPainter methodsFor:'private'!

painter
    ^ objectList painter
! !

!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 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:[
        topView raise.
        topView device beep
    ].
!

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 newDefault.
    selectionPanel allButOpenInterface:#windowSpec.
    selectionPanel window openInGroup:(topView windowGroup).
    selectionPanel window bePartner.
    selectionPanel openWindow.
    selectionPanel window application:self.

    "Modified: 17.6.1997 / 14:41:15 / cg"
!

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.
        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.
        painter methodName:aSelector.
        painter setupFromSpec:(aClass perform:aSelector).
    ]

    "Modified: 17.6.1997 / 14:41:25 / 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:[
        superclass := Smalltalk at:specSuperclass asSymbol
    ] ifTrue:[
        superclass := specSuperclass
    ].
    specSuperclass notNil ifTrue:[
        superclass isNil ifTrue:[
            self warn:'no class named ' , specSuperclass , ' exists.'.
            ^ false.
        ].

        (cls isSubclassOf:superclass) ifFalse:[
            self warn:'a global named ' , specClass , ' exists, but is not a subclass of ' , superclass name , '.'.
            ^ false.
        ]
    ].
    ^ true


!

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

    |again|

    [
        again := false.

        aspects at:#classNameChannel put:specClass asValue.
        aspects at:#methodNameChannel put:specSelector asValue.
        aspects at:#superclassNameChannel put:specSuperclass 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  := '' asValue.
    methodName := '' 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
                    painter className:className value.
                    painter methodName:methodName value.
                    painter setupFromSpec:spec.
                  ^ self
                 ]
            ]
         ]
    ] doWhile:[accepted and:[failed]].

    "Modified: 17.6.1997 / 12:33:36 / 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
    |dict cls src|

    specClass isNil ifTrue:[
        ^ self information:'no class defined'
    ].
    specClass isBehavior ifFalse:[
        cls := Smalltalk at:specClass asSymbol
    ] ifTrue:[
        cls := specClass
    ].

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

    activeHelpTool isNil ifTrue:[
        ^ self information:'no help text defined'
    ].    
    dict := activeHelpTool dictionary.
    (cls isSubclassOf:UISpecification) ifTrue:[
        cls := self class
    ].

    src := '' writeStream.
    src nextPutAll:'helpSpec
    "return a dictionary filled with helpKey -> helptext associations.
     These are used by the activeHelp tool."

    |dict|

    dict := super helpSpec.
'.

    dict keysAndValuesDo:[:key :txt |
        |t|

        t := txt asString.
        (t endsWith:Character cr) ifTrue:[t := t copyWithoutLast:1].
        src nextPutLine:'    dict at:' , key storeString , ' put:' , t storeString , '.'.
    ].
    src nextPutLine:'    ^ dict'.
    src := src contents.
    Compiler compile:src forClass:cls class inCategory:'help specs'
!

doInstallSpec
    |code|

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

    self checkClassAndSelector ifFalse:[
        ^ self
    ].

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

    code := self painter generateCode.
    (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 className methodName cls sel accepted spec s|

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

    (view := Display viewFromUser) notNil ifTrue:[
        painter := self painter.

        spec := UISpecification fromView:view topView.

     "/ ok, got it
        painter setupFromSpec:spec.
        painter className:view class name.
        painter methodName:#newSpec.
    ]

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

doRaise
    self painter topView raise.

    selectionPanel notNil ifTrue:[
        selectionPanel window 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$'
! !