TabItemEditor.st
author Stefan Vogel <sv@exept.de>
Thu, 29 Jan 1998 14:06:26 +0100
changeset 516 d336effde882
parent 514 5ac07e96e448
child 526 7a4749b25748
permissions -rw-r--r--
Fix #openOnDirectory: and copyright.

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

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



ToolApplicationModel subclass:#TabItemEditor
	instanceVariableNames:'rebuildMode testView className selector aspects listOfTabs
		hasChanged selectedIndex'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

!TabItemEditor class methodsFor:'documentation'!

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

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


!

documentation
"
    create and modify or inspect a list of tabs

    [start with:]
        TabItemEditor open

    [see also:]
        TabItem
        TabView
        NoteBookView
        UIPainter

    [author:]
        Claus Atzkern
"


! !

!TabItemEditor class methodsFor:'interface specs'!

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:TabItemEditor andSelector:#nameAndSelectorSpec
     TabItemEditor new openInterface:#nameAndSelectorSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'Class & Selector'
              #'layout:' #(#LayoutFrame 219 0 193 0 584 0 319 0)
              #'label:' 'Class & Selector'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1152 900)
              #'bounds:' #(#Rectangle 219 193 585 320)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'DefineClassAndSelector'
                    #'layout:' #(#Point 2 10)
                    #'label:' 'Define Class And Selector'
                    #'adjust:' #left
                    #'resizeForLabel:' true
                )
                 #(#LabelSpec
                    #'name:' 'ClassLabel'
                    #'layout:' #(#AlignmentOrigin 50 0.11 51 0 1 0.5)
                    #'label:' 'Class:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'ClassField'
                    #'layout:' #(#LayoutFrame 51 0.11 39 0 -2 1.0 61 0)
                    #'tabable:' true
                    #'model:' #className
                )
                 #(#LabelSpec
                    #'name:' 'SelectorLabel'
                    #'layout:' #(#AlignmentOrigin 50 0.11 74 0 1 0.5)
                    #'label:' 'Selector:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'SelectorField'
                    #'layout:' #(#LayoutFrame 51 0.11 64 0 -2 1.0 86 0)
                    #'tabable:' true
                    #'model:' #selector
                )
                 #(#UISubSpecification
                    #'name:' 'CommitPanel'
                    #'layout:' #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1)
                    #'majorKey:' #ToolApplicationModel
                    #'minorKey:' #windowSpecForCommitWithoutChannels
                )
              )
          )
      )
!

tabSpec
    "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:TabItemEditor andSelector:#tabSpec
     TabItemEditor new openInterface:#tabSpec
    "

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'Tab Basic'
              #'layout:' #(#LayoutFrame 219 0 193 0 506 0 397 0)
              #'label:' 'Tab Basic'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1280 1024)
              #'bounds:' #(#Rectangle 219 193 507 398)
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#LabelSpec
                    #'name:' 'Label'
                    #'layout:' #(#AlignmentOrigin 73 0 34 0 1 0.5)
                    #'label:' 'Label:'
                    #'resizeForLabel:' true
                )
                 #(#InputFieldSpec
                    #'name:' 'LabelField'
                    #'layout:' #(#LayoutFrame 75 0 24 0 -4 1.0 46 0)
                    #'activeHelpKey:' #label
                    #'model:' #label
                )
                 #(#CheckBoxSpec
                    #'name:' 'TranslateLabel'
                    #'layout:' #(#LayoutOrigin 71 0 49 0)
                    #'activeHelpKey:' #translateLabel
                    #'model:' #translateLabel
                    #'label:' 'Label derives from Application'
                )
                 #(#ColorMenuSpec
                    #'name:' 'ForegroundColorMenu'
                    #'layout:' #(#LayoutFrame 75 0 104 0 -4 1.0 126 0)
                    #'activeHelpKey:' #foregroundColor
                    #'model:' #labelForegroundColor
                    #'labelsAreColored:' false
                )
                 #(#LabelSpec
                    #'name:' 'ForegroundLabel'
                    #'layout:' #(#AlignmentOrigin 73 0 116 0 1 0.5)
                    #'label:' 'Color:'
                    #'adjust:' #right
                    #'resizeForLabel:' true
                )
                 #(#CheckBoxSpec
                    #'name:' 'CanSelect'
                    #'layout:' #(#LayoutFrame 34 0 157 0 153 0 179 0)
                    #'model:' #enabled
                    #'label:' 'Can Select'
                )
              )
          )
      )
!

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

    <resource: #canvas>

    ^
     
       #(#FullSpec
          #'window:' 
           #(#WindowSpec
              #'name:' 'TabItem Editor'
              #'layout:' #(#LayoutFrame 219 0 193 0 687 0 521 0)
              #'label:' 'TabItem Editor'
              #'min:' #(#Point 10 10)
              #'max:' #(#Point 1152 900)
              #'bounds:' #(#Rectangle 219 193 688 522)
              #'menu:' #menu
              #'usePreferredExtent:' false
          )
          #'component:' 
           #(#SpecCollection
              #'collection:' 
               #(
                 #(#MenuPanelSpec
                    #'name:' 'menuToolbarView'
                    #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 34 0)
                    #'menu:' #menuToolbar
                )
                 #(#VariableHorizontalPanelSpec
                    #'name:' 'VariablePanel'
                    #'layout:' #(#LayoutFrame 0 0.0 36 0.0 0 1.0 -22 1.0)
                    #'component:' 
                     #(#SpecCollection
                        #'collection:' 
                         #(
                           #(#SequenceViewSpec
                              #'name:' 'columnView'
                              #'enableChannel:' #isNotModified
                              #'model:' #selectionHolder
                              #'menu:' #menuEdit
                              #'hasHorizontalScrollBar:' true
                              #'hasVerticalScrollBar:' true
                              #'miniScrollerHorizontal:' true
                              #'useIndex:' true
                              #'sequenceList:' #listOfLabels
                          )
                           #(#ViewSpec
                              #'name:' 'specView'
                              #'component:' 
                               #(#SpecCollection
                                  #'collection:' 
                                   #(
                                     #(#ViewSpec
                                        #'name:' 'TestView'
                                        #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
                                        #'component:' 
                                         #(#SpecCollection
                                            #'collection:' 
                                             #(
                                               #(#TabViewSpec
                                                  #'name:' 'TestTabsView'
                                                  #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 0.5)
                                              )
                                            )
                                        )
                                    )
                                     #(#SubCanvasSpec
                                        #'name:' 'specCanvas'
                                        #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -30 1.0)
                                        #'specHolder:' #specChannel
                                    )
                                     #(#HorizontalPanelViewSpec
                                        #'name:' 'modifyPanel'
                                        #'layout:' #(#LayoutFrame 0 0.0 -30 1.0 0 1.0 0 1.0)
                                        #'component:' 
                                         #(#SpecCollection
                                            #'collection:' 
                                             #(
                                               #(#ActionButtonSpec
                                                  #'name:' 'cancelButton'
                                                  #'label:' 'Cancel'
                                                  #'model:' #cancel
                                                  #'enableChannel:' #modifiedChannel
                                                  #'extent:' #(#Point 168 24)
                                              )
                                               #(#ActionButtonSpec
                                                  #'name:' 'acceptButton'
                                                  #'label:' 'OK'
                                                  #'model:' #accept
                                                  #'enableChannel:' #modifiedChannel
                                                  #'extent:' #(#Point 168 24)
                                              )
                                            )
                                        )
                                        #'horizontalLayout:' #fitSpace
                                        #'verticalLayout:' #fitSpace
                                        #'horizontalSpace:' 3
                                        #'verticalSpace:' 3
                                    )
                                  )
                              )
                              #'borderWidth:' 1
                          )
                        )
                    )
                    #'handles:' #(#Any 0.259875 1.0)
                )
                 #(#LabelSpec
                    #'name:' 'infoLabel'
                    #'layout:' #(#LayoutFrame 0 0.0 -22 1 -80 1.0 0 1.0)
                    #'labelChannel:' #valueOfInfoLabel
                    #'level:' 1
                    #'adjust:' #left
                )
                 #(#LabelSpec
                    #'name:' 'timeLabel'
                    #'layout:' #(#LayoutFrame -80 1 -22 1 0 1.0 0 1.0)
                    #'labelChannel:' #valueOfTimeLabel
                    #'level:' 1
                    #'adjust:' #right
                )
              )
          )
      )
! !

!TabItemEditor class methodsFor:'menus'!

menu
    "this window spec was automatically generated by the ST/X MenuEditor"

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

    "
     MenuEditor new openOnClass:TabItemEditor andSelector:#menu
     (Menu new fromLiteralArrayEncoding:(TabItemEditor menu)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'File'
                #'submenu:' 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #'label:' 'New'
                          #'value:' #doNew
                          #'labelImage:' #(#ResourceRetriever nil #newIcon 'New')
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Reload'
                          #'value:' #doReload
                          #'enabled:' #hasClassAndSelector
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Save'
                          #'value:' #doInstallSpec
                          #'enabled:' #isNotModified
                          #'labelImage:' #(#ResourceRetriever nil #saveIcon 'Save')
                      )
                       #(#MenuItem
                          #'label:' '='
                      )
                       #(#MenuItem
                          #'label:' 'Define Class And Selector...'
                          #'value:' #doDefineClassAndSelector
                      )
                       #(#MenuItem
                          #'label:' '-'
                      )
                       #(#MenuItem
                          #'label:' 'Create Aspect Method'
                          #'value:' #doInstallAspect
                          #'enabled:' #hasClassAndSelector
                      )
                       #(#MenuItem
                          #'label:' '='
                      )
                       #(#MenuItem
                          #'label:' 'Exit'
                          #'value:' #closeRequest
                          #'enabled:' #isNotModified
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #'label:' 'Edit'
                #'submenuChannel:' #menuEdit
            )
             #(#MenuItem
                #'label:' 'History'
                #'submenuChannel:' #menuHistory
            )
             #(#MenuItem
                #'label:' 'Help'
                #'submenuChannel:' #menuHelp
            )
          ) nil
          nil
      )
!

menuEdit
    "this window spec was automatically generated by the ST/X MenuEditor"

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

    "
     MenuEditor new openOnClass:TabItemEditor andSelector:#menuEdit
     (Menu new fromLiteralArrayEncoding:(TabItemEditor menuEdit)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'Cut'
                #'value:' #doCutTab
                #'enabled:' #isColumnSelected
            )
             #(#MenuItem
                #'label:' 'Copy'
                #'value:' #doCopyTab
                #'enabled:' #isColumnSelected
            )
             #(#MenuItem
                #'label:' 'Paste'
                #'value:' #doPasteTab
                #'enabled:' #valueOfHavingClipboard
            )
             #(#MenuItem
                #'label:' '-'
            )
             #(#MenuItem
                #'label:' 'Create Tab'
                #'value:' #doCreateTab
                #'enabled:' #isNotModified
                #'labelImage:' #(#ResourceRetriever #MenuEditor #menuItemImage 'Create Tab')
            )
          ) nil
          nil
      )
!

menuToolbar
    "this window spec was automatically generated by the ST/X MenuEditor"

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

    "
     MenuEditor new openOnClass:TabItemEditor andSelector:#menuToolbar
     (Menu new fromLiteralArrayEncoding:(TabItemEditor menuToolbar)) startUp
    "

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #'label:' 'Test'
                #'isButton:' true
                #'value:' #doTest
                #'labelImage:' #(#ResourceRetriever #UIPainter #startIcon)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'New'
                #'isButton:' true
                #'value:' #doNew
                #'labelImage:' #(#ResourceRetriever nil #newIcon)
            )
             #(#MenuItem
                #'label:' 'Save'
                #'isButton:' true
                #'value:' #doInstallSpec
                #'enabled:' #isNotModified
                #'labelImage:' #(#ResourceRetriever nil #saveIcon)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'Create Label'
                #'isButton:' true
                #'value:' #doCreateTab
                #'enabled:' #isNotModified
                #'labelImage:' #(#ResourceRetriever #MenuEditor #menuItemImage)
            )
             #(#MenuItem
                #'label:' ''
            )
             #(#MenuItem
                #'label:' 'Move Tab Up'
                #'isButton:' true
                #'value:' #'doMoveTabUpOrDown:'
                #'enabled:' #canMoveTabUpOrDown
                #'argument:' #up
                #'labelImage:' #(#ResourceRetriever nil #upIcon)
            )
             #(#MenuItem
                #'label:' 'Move Tab Down'
                #'isButton:' true
                #'value:' #'doMoveTabUpOrDown:'
                #'enabled:' #canMoveTabUpOrDown
                #'argument:' #down
                #'labelImage:' #(#ResourceRetriever nil #downIcon)
            )
          ) nil
          nil
      )
! !

!TabItemEditor class methodsFor:'resources'!

newLabelIcon
    "ImageEditor openOnClass:self andSelector:#newLabelIcon"

    <resource: #image>
    ^(Depth4Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(#[17 17 16 0 0 0 0 0 0 17 17 17 17 16 17 17 17 17 17 32 17 17 17 17 16 18 34 34 34 34 48 17 17 17 17 16 18 32 2 32 34 48 17 17 17 17 16 18 2 34 2 2 48 17 17 17 17 16 18 2 34 2 2 48 17 17 17 17 16 18 32 2 32 34 48 17 17 16 17 16 18 34 34 34 34 48 17 17 17 17 16 18 2 34 2 2 48 17 17 17 17 16 18 2 34 2 2 48 17 17 17 17 16 18 2 34 2 2 48 17 17 17 17 16 18 0 2 0 2 48 17 17 17 17 16 18 34 34 34 34 48 17 17 17 17 16 18 34 34 34 34 48 17 17 17 17 16 18 2 2 2 2 48 17 17 17 17 16 18 0 2 0 2 48 17 17 17 17 16 18 2 2 0 2 48 17 17 17 17 16 18 2 2 2 2 48 17 17 17 17 16 18 34 34 34 34 48 17 17 17 17 16 18 34 34 34 34 48 17 17 17 17 16 35 51 51 51 51 48 17 17 17 17 16 0 0 0 0 0 0 17 17]) ; colorMap:((OrderedCollection new add:(Color black); add:(Color white); add:(Color grey:66.9978); add:(Color grey:49.9962); add:(Color red:100.0 green:0.0 blue:0.0); add:(Color red:0.0 green:100.0 blue:0.0); add:(Color red:0.0 green:0.0 blue:100.0); add:(Color red:0.0 green:100.0 blue:100.0); add:(Color red:100.0 green:100.0 blue:0.0); add:(Color red:100.0 green:0.0 blue:100.0); add:(Color red:49.9992 green:0.0 blue:0.0); add:(Color red:0.0 green:49.9992 blue:0.0); add:(Color red:0.0 green:0.0 blue:49.9992); add:(Color red:0.0 green:49.9992 blue:49.9992); add:(Color red:49.9992 green:49.9992 blue:0.0); add:(Color red:49.9992 green:0.0 blue:49.9992); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(#[7 255 192 7 255 192 7 255 192 7 255 192 7 255 192 7 255 192 7 255 192 7 255 192 7 255 195 7 255 192 7 255 192 7 255 192 7 255 192 7 255 195 7 255 193 7 255 192 7 255 195 7 255 192 7 255 195 7 255 192 7 255 192 7 255 193]) ; yourself); yourself


! !

!TabItemEditor methodsFor:'accessing'!

className
    ^ className
!

didInstall
    ^ hasChanged not
!

selector
    ^ selector
! !

!TabItemEditor methodsFor:'actions'!

accept
    "accept changes
    "
    |label|

    self modified ifTrue:[
        selectedIndex ~~ 0 ifTrue:[
            rebuildMode := true.
            label := listOfTabs at:selectedIndex.
            hasChanged := true.

            aspects keysAndValuesDo:[:aKey :aModel|
                label perform:(aKey , ':') asSymbol with:(aModel value).
            ].
            self listOfLabels at:selectedIndex put:(label label).

            rebuildMode := false.
        ].
        self cancel
    ]
!

cancel
    "cancel all changes
    "
    |tab|

    rebuildMode ifFalse:[
        selectedIndex ~~ 0 ifTrue:[
            tab := listOfTabs at:selectedIndex.

            rebuildMode := true.

            aspects keysAndValuesDo:[:aKey :aModel|
                aModel value:(tab perform:aKey)    
            ].

            rebuildMode := false.
        ].
        self modified:false.
    ].
    self canMoveTabUpOrDown value:(selectedIndex ~~ 0 and:[listOfTabs size > 1])




!

modified
    "returns true if current tab is modified
    "
    ^ self modifiedChannel value
!

modified:aState
    "change modification state
    "
    rebuildMode ifFalse:[
        self modifiedChannel value:aState.
        self isNotModified   value:(aState not).
    ]
! !

!TabItemEditor methodsFor:'aspects'!

aspectFor:aKey
    "returns aspect for a key or nil
    "
    ^ aspects at:aKey ifAbsent:[ super aspectFor:aKey ]


!

canMoveTabUpOrDown

    |holder|

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

!

hasClassAndSelector

    |holder|

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

!

isNotModified
    "returns true if current tab spec is not modified
    "
    |holder|

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

listOfLabels
    "returns a holder which keeps the list of tab labels
    "
    |list|

    (list := builder bindingAt:#listOfLabels) isNil ifTrue:[
        builder aspectAt:#listOfLabels put:(list :=  List new).
    ].
    ^ list
!

modifiedChannel
    "channel which is true if the current tab specification is modified
    "
    |holder|

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

selectionHolder
    "holder which keeps the current selection
    "
    |holder|

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

specChannel
    "holder which keeps the current tab specification
    "
    |holder|

    (holder := builder bindingAt:#specChannel) isNil ifTrue:[
        builder aspectAt:#specChannel put:(holder :=  ValueHolder new).
    ].
    ^ holder
! !

!TabItemEditor methodsFor:'building'!

buildFrom:aClass andSelector:aSelector
    "build from class and selector
    "
    |spec list validClSl|

    self doNew.

    selector  := nil.
    className := self resolveName:aClass.
    validClSl := false.

    className notNil ifTrue:[
        aSelector notNil ifTrue:[
            validClSl := true.
            selector  := aSelector asSymbol.

            (className respondsTo:selector) ifTrue:[
                spec := className perform:selector.
                list := self listOfLabels.

                spec size ~~ 0 ifTrue:[

                    rebuildMode := true.

                    spec do:[:aTab|
                        list add:aTab label.
                        listOfTabs add:aTab.
                    ].
                    rebuildMode := false.
                    self addToHistory:(className name, ' ', selector) -> #loadFromMessage:                        
                ]
            ]
        ]
    ].

    self hasClassAndSelector value:validClSl.
    self modified:false.
    hasChanged := false.

    listOfTabs notEmpty ifTrue:[
        self selectionHolder value:1
    ].
!

loadFromMessage:aMessage
    "load tabs from class and selector derived from history
    "
    |msg cls|

    aMessage notNil ifTrue:[
        msg := aMessage asCollectionOfWords.

        (msg size == 2 and:[(cls := self resolveName:(msg at:1)) notNil]) ifTrue:[
            self buildFrom:cls andSelector:((msg at:2) asSymbol)
        ]
    ]
! !

!TabItemEditor methodsFor:'change & update'!

update:something with:aParameter from:someObject
    "one of my aspects has changed; update modified channel
    "
    self modified:true.


! !

!TabItemEditor methodsFor:'selection'!

selectedIndex
    ^ selectedIndex
!

selectedIndex:anIndex
    |s oldSel|

    oldSel := selectedIndex.
    selectedIndex := anIndex ? 0.

    selectedIndex == oldSel ifTrue:[^ self].

    oldSel == 0 ifTrue:[
        self specChannel value:(self class tabSpec)
    ] ifFalse:[
        selectedIndex == 0 ifTrue:[
            self specChannel value:nil
        ]
    ].
    self cancel.

    testView notNil ifTrue:[
        testView lower
    ]
! !

!TabItemEditor methodsFor:'startup / release'!

closeRequest

    hasChanged ifTrue:[
        ( YesNoBox title:'tab description was modified!!'
                 yesText:'waste it and proceed'
                  noText:'cancel'
        ) confirm ifFalse:[
            ^ self
        ].
        hasChanged := false.
    ].
    super closeRequest.
!

initialize
    "setup aspects used by column description specifications
    "
    |holder|

    super initialize.

    aspects       := IdentityDictionary new.
    listOfTabs    := OrderedCollection new.
    hasChanged    := false.
    selectedIndex := 0.
    rebuildMode   := false.

   #(
        label
        translateLabel
        labelForegroundColor
        enabled

    ) do:[:aKey|
        aspects at:aKey put:(holder := ValueHolder new).
        holder addDependent:self.
    ].


!

openModalOnClass:aClass andSelector:aSelector

    className := aClass.
    selector  := aSelector.

    super openInterfaceModal.


!

openOnClass:aClass andSelector:aSelector

    className := aClass.
    selector  := aSelector.

    super openInterface.


!

postBuildWith:builder
    self buildFrom:className andSelector:selector.
    testView := builder componentAt:#TestView.
! !

!TabItemEditor methodsFor:'user interactions'!

doCopyTab
    "copy selected tab
    "
    selectedIndex ~~ 0 ifTrue:[
        self clipboard:(listOfTabs at:selectedIndex) deepCopy
    ]
!

doCreateTab
    |tab|

    tab := TabItem label:'label'.

    listOfTabs add:tab afterIndex:selectedIndex.
    self listOfLabels add:(tab label) afterIndex:selectedIndex.
    hasChanged := true.

    selectedIndex == 0 ifTrue:[
        self selectionHolder value:1
    ] ifFalse:[
        self cancel.
    ]
!

doCutTab
    "cut selected tab
    "
    |list index|

    (index := selectedIndex) ~~ 0 ifTrue:[
        list := self listOfLabels.
        self clipboard:(listOfTabs at:index) deepCopy.
        self selectionHolder value:0.
        listOfTabs removeIndex:index.
        list removeIndex:index.
        hasChanged := true.

        index > list size ifTrue:[
            index := index - 1
        ].
        self selectionHolder value:index
    ]

!

doDefineClassAndSelector
    "launch a dialog to define class and selector
    "
    |cls sel bindings|

    bindings := IdentityDictionary new.

    [true] whileTrue:[
        cls := className notNil ifTrue:[className name] ifFalse:['NewApplication'].
        sel := selector  ? 'tabItemList'.

        bindings at:#className put:cls asValue.
        bindings at:#selector  put:sel asValue.

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

        cls := (bindings at:#className) value withoutSeparators.
        sel := (bindings at:#selector)  value withoutSeparators.

        (cls := self resolveName:cls) notNil ifTrue:[
            className := cls.

            sel notNil ifTrue:[
                selector := sel asSymbol.
                self hasClassAndSelector value:true.

                listOfTabs size == 0 ifTrue:[
                    self buildFrom:className andSelector:selector
                ].
                ^ self
            ]
        ]
    ]
!

doInstallAspect
    "generate aspect method
    "
    |code|

    className isNil ifTrue:[ ^ self information:'No valid class defined!!'].
    selector isNil  ifTrue:[ ^ self information:'No selector defined!!'   ].

    (className canUnderstand:selector) ifTrue:[
        "/ method already exists, do not overwrite the method automaticaly

        ( YesNoBox title:'method '
                         , (Text string:('#', selector) emphasis:#bold)
                         , ' already exists'
                 yesText:'overwrite'
                  noText:'cancel'
        ) confirm ifFalse:[
            ^ self
        ]
    ].

    code := '!!' , className name , ' methodsFor:''aspects''!!\\' ,
            selector , '\' ,
            '    "automatically generated by TabItem Editor ..."\' ,
            '\' ,
            '    |list|\' ,
            '\' ,
            '    (list := builder bindingAt:#' , selector , ') isNil ifTrue:[\' ,
            '        builder aspectAt:#' , selector, ' put:(list := self class ', selector, ').\' ,
            '    ].\' ,
            '    ^ list\' ,
            '!! !!\\'.

    (ReadStream on:(code withCRs)) fileIn


!

doInstallSpec
    "generate code for class and instance
    "
    |code spec category mthd|

    (className isNil or:[selector isNil]) ifTrue:[
        self doDefineClassAndSelector
    ].
    className isNil ifTrue:[ ^ self information:'No valid class defined!!'].
    selector isNil  ifTrue:[ ^ self information:'No selector defined!!'   ].
    listOfTabs isEmpty ifTrue:[ ^ self information:'No valid tabs defined!!' ].

    spec  := WriteStream on:String new.
    UISpecification prettyPrintSpecArray:(listOfTabs literalArrayEncoding) on:spec indent:5.
    spec := spec contents.

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

    category := 'interface specs'.

    (mthd := className class compiledMethodAt:selector) notNil ifTrue:[
        category := mthd category.
    ].

    code := Character excla asString 
            , className name , ' class methodsFor:' , category storeString
            , Character excla asString , '\\'

            , selector , '\'
            , '    "this window spec was automatically generated by the ST/X TabItemEditor"\\'
            , '    "do not manually edit this - the builder may not be able to\'
            , '     handle the specification if its corrupted."\\'
            , '    "\'
            , '     TabItemEditor new openOnClass:' , className name , ' andSelector:#' , selector , '\'
            , '    "\'.

    code := code 
            , '\'
            , '    <resource: #tabItem>\\'
            , '    ^\' 
            , '     ', spec, '\'
            , '      collect:[:aTab| TabItem new fromLiteralArrayEncoding:aTab ]'
            , '\'
            , Character excla asString
            , ' '
            , Character excla asString
            , '\\'.

    code := code withCRs.
    (ReadStream on:code) fileIn.
    hasChanged := false.

    (className canUnderstand:selector) ifFalse:[
        (YesNoBox confirm:'install aspect method') ifTrue:[
            self doInstallAspect
        ]
    ]


!

doMoveTabUpOrDown:what
    "step up or down
    "
    |tab list index|

    (selectedIndex ~~ 0 and:[listOfTabs size > 1]) ifFalse:[
        ^ self
    ].

    list := self listOfLabels.
    tab  := listOfTabs at:selectedIndex.

    list removeIndex:selectedIndex.
    listOfTabs removeIndex:selectedIndex.

    what == #down ifTrue:[
        index := selectedIndex > list size ifTrue:[1]
                                          ifFalse:[selectedIndex + 1]
    ] ifFalse:[
        index := selectedIndex == 1 ifTrue:[list size + 1]
                                   ifFalse:[selectedIndex - 1]
    ].

    list add:(tab label) beforeIndex:index.
    listOfTabs add:tab beforeIndex:index.
    hasChanged  := true.

    rebuildMode := true.
    self selectionHolder value:index.
    rebuildMode := false.


!

doNew

    self modified:false.

    rebuildMode := true.

    self selectionHolder value:0.
    self listOfLabels removeAll.
    listOfTabs removeAll.

    testView notNil ifTrue:[
        testView lower
    ].

    hasChanged  := true.
    rebuildMode := false.
!

doPasteTab
    "paste a tab
    "
    |tab|

    tab := self class clipboard deepCopy.
    listOfTabs add:tab afterIndex:selectedIndex.
    self listOfLabels add:(tab label) afterIndex:selectedIndex.
    hasChanged := true.

    selectedIndex == 0 ifTrue:[
        self selectionHolder value:1
    ]
!

doReload
    "reload from class and selector
    "
    self buildFrom:className andSelector:selector
!

doTest
    "run a test
    "
    |tabView list|

    self selectionHolder value:nil.

    listOfTabs size ~~ 0 ifTrue:[
        list := listOfTabs collect:[:aTab||t|
            t := aTab copy.
            t setAttributesFromClass:className.
            t
        ]
    ] ifFalse:[
        list := nil
    ].
    tabView  := builder componentAt:#TestTabsView.
    tabView list:list.
    testView raise.


! !

!TabItemEditor class methodsFor:'documentation'!

version
    ^ '$Header$'
! !