TabListEditor.st
author Claus Gittinger <cg@exept.de>
Tue, 21 Mar 2000 20:50:03 +0100
changeset 1370 c975b2f00291
parent 1326 295fe7dc6fbb
child 1373 623e692f53fc
permissions -rw-r--r--
create abbrev file added

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



ResourceSpecEditor subclass:#TabListEditor
	instanceVariableNames:'rebuildMode testView listOfTabs selectedIndex'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

!TabListEditor 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
"
    The TabListEditor allows you to create, modify or just inspect
    tab lists for tab headers or note books.

    [start with:]
        TabItemEditor open

    [see also:]
        TabItem
        TabView
        NoteBookView
        UIPainter

    [author:]
        Claus Atzkern, eXept Software AG
        Thomas Zwick, eXept Software AG
"


! !

!TabListEditor class methodsFor:'instance creation'!

openModalOnTabList: aTabList
    "Open a TabListEditor modal on aTabList"
    "self openModalOnTabList: (Array with: (TabItem label: 'Tab Item 1'))"

    ^self new openModalOnTabList: aTabList

! !

!TabListEditor class methodsFor:'accessing'!

resourceType
    "get the type of resource of the method generated by the TabListEditor"

    ^#tabList






! !

!TabListEditor class methodsFor:'aspects'!

aspects
    "get the aspects for the attributes of the tab list components"

    ^#(
        label
        translateLabel
        labelForegroundColor
        enabled
        editAgument
        accessCharacterPosition
        shortcutKey
    )

! !

!TabListEditor class methodsFor:'help specs'!

helpSpec
    "This resource specification was automatically generated
     by the UIHelpTool of ST/X."

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

    "
     UIHelpTool openOnClass:TabListEditor    
    "

    <resource: #help>

    ^super helpSpec addPairsFrom:#(

#addTabItem
'Adds a new tab item.'

#argument
'An optional argument stored with the tab item.'

#canSelect
'Turns on/off whether the tab item is selectable.'

#color
'Defines the foreground color of the label. The default color derives from the style sheet.'

#fileCreateAspectMethod
'Creates the aspect method for the tab list.'

#fileLoad
'Opens a dialog for selecting and loading a tab list spec from a class.'

#fileNew
'Creates a new tab list.'

#fileSave
'Saves current tab list.'

#label
'Label of the tab item.'

#labelDerivesFromApplication
'If turned on, the label''s string is a selector returning a string or bitmap image, which is used as logo in the tab item.'

#testPreview
'Turns on/off preview of the tab list.'

)
! !

!TabListEditor class methodsFor:'image specs'!

newTabItemIcon
    "This resource specification was automatically generated
     by the ImageEditor of ST/X."

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

    "
     ImageEditor openOnClass:self andSelector:#newTabItemIcon
    "

    <resource: #image>

    ^Icon
        constantNamed:#'TabListEditor newTabItemIcon'
        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'U@@@@EUPUEUUVEUPUF**+EUPUF**+EUPUF**+EUP@F**+@@@EV***UV@F*****+@F KNC*+NF(("H*+@F((BC +EF(("H*+@F(("C*+MF*****+@F"@ H*K@F"""(LK@F"" ("K@F"""(*K@F"" H*K@F*****+HK??????@@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 170 170 170 127 127 127]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'G?<@G?<@G?<@G?<@G?<@???<???<???<???????<???<???<???<???????=???<???????<???????<???<???=') ; yourself); yourself]! !

!TabListEditor class methodsFor:'interface specs'!

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

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

    "
     UIPainter new openOnClass:TabListEditor andSelector:#tabSpec
     TabListEditor new openInterface:#tabSpec
    "

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #tabSpec
        #window: 
       #(#WindowSpec
          #label: 'Tab Basic'
          #name: 'Tab Basic'
          #min: #(#Point 10 10)
          #max: #(#Point 1280 1024)
          #bounds: #(#Rectangle 12 22 440 249)
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#LabelSpec
              #label: 'Label:'
              #name: 'labelLabel'
              #layout: #(#AlignmentOrigin 98 0 26 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #attributes: 
             #(#LabelField
                nil #label
                nil #tabable
                true
              )
              #name: 'label'
              #layout: #(#LayoutFrame 100 0 15 0 -5 1.0 37 0)
              #activeHelpKey: #label
              #tabable: true
              #model: #label
              #group: #inputGroup
              #acceptOnLostFocus: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Accelerator:'
              #name: 'shortcutKeyLabel'
              #layout: #(#AlignmentOrigin 98 0 55 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #attributes: 
             #(#label
                nil #shortcutKey
                nil #tabable
                true
              )
              #name: 'shortcutKey'
              #layout: #(#LayoutFrame 100 0 44 0 -5 1.0 66 0)
              #activeHelpKey: #label
              #tabable: true
              #model: #shortcutKey
              #group: #inputGroup
              #type: #symbolOrNil
              #acceptOnLostFocus: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Argument:'
              #name: 'editAgumentLabel'
              #layout: #(#AlignmentOrigin 98 0 84 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #attributes: 
             #(#tabable
                true #ArgumentField
                nil #editAgument
                nil
              )
              #name: 'editAgument'
              #layout: #(#LayoutFrame 100 0 73 0 -5 1.0 95 0)
              #activeHelpKey: #argument
              #tabable: true
              #model: #editAgument
              #group: #inputGroup
              #acceptOnReturn: true
              #acceptOnTab: true
              #acceptOnLostFocus: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#LabelSpec
              #label: 'Access Character Position:'
              #name: 'accessCharacterPositionLabel'
              #layout: #(#AlignmentOrigin 275 0 113 0 1 0.5)
              #resizeForLabel: true
            )
           #(#InputFieldSpec
              #attributes: 
             #(#label
                nil #accessCharacterPos
                nil #tabable
                true #accessCharacterPosition
                nil
              )
              #name: 'accessCharacterPosition'
              #layout: #(#LayoutFrame 278 0 103 0 -5 1.0 125 0)
              #activeHelpKey: #label
              #tabable: true
              #model: #accessCharacterPosition
              #group: #inputGroup
              #type: #number
              #acceptOnLostFocus: true
              #acceptChannel: #acceptChannel
              #modifiedChannel: #modifiedChannel
              #acceptOnPointerLeave: false
            )
           #(#CheckBoxSpec
              #attributes: 
             #(#tabable
                true
              )
              #label: 'Application provides translation '
              #name: 'translateLabel'
              #layout: #(#Point 96 135)
              #activeHelpKey: #labelDerivesFromApplication
              #tabable: true
              #model: #translateLabel
            )
           #(#CheckBoxSpec
              #attributes: 
             #(#tabable
                true
              )
              #label: 'Can Select'
              #name: 'enabled'
              #layout: #(#Point 96 161)
              #activeHelpKey: #canSelect
              #tabable: true
              #model: #enabled
            )
           #(#LabelSpec
              #label: 'Color:'
              #name: 'ForegroundLabel'
              #layout: #(#AlignmentOrigin 98 0 209 0 1 0.5)
              #resizeForLabel: true
              #adjust: #right
            )
           #(#ColorMenuSpec
              #attributes: 
             #(#tabable
                true
              )
              #name: 'ForegroundColorMenu'
              #layout: #(#LayoutFrame 100 0 197 0 -5 1.0 219 0)
              #activeHelpKey: #color
              #model: #labelForegroundColor
              #labelsAreColored: false
            )
           )
         
        )
      )
!

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

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

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

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #windowSpec
        #window: 
       #(#WindowSpec
          #label: 'Tab List Editor'
          #name: 'Tab List Editor'
          #layout: #(#LayoutFrame 58 0 290 0 659 0 707 0)
          #min: #(#Point 440 280)
          #max: #(#Point 1152 900)
          #bounds: #(#Rectangle 58 290 660 708)
          #menu: #menu
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#MenuPanelSpec
              #name: 'menuToolbarView'
              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 34 0)
              #menu: #menuToolbar
              #showSeparatingLines: true
            )
           #(#VariableHorizontalPanelSpec
              #name: 'VariablePanel'
              #layout: #(#LayoutFrame 0 0.0 36 0.0 0 1.0 -26 1.0)
              #handles: #(#Any 0.259875 1.0)
              #component: 
             #(#SpecCollection
                #collection: #(
                 #(#SequenceViewSpec
                    #name: 'ColumnView'
                    #model: #selectionHolder
                    #menu: #menuEdit
                    #hasHorizontalScrollBar: true
                    #hasVerticalScrollBar: true
                    #miniScrollerHorizontal: true
                    #useIndex: true
                    #sequenceList: #listOfLabels
                  )
                 #(#ViewSpec
                    #name: 'SpecView'
                    #level: -1
                    #component: 
                   #(#SpecCollection
                      #collection: #(
                       #(#ViewSpec
                          #name: 'TestView'
                          #layout: #(#LayoutFrame 1 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 1 0.0 0 0.0 0 1.0 -30 1.0)
                          #specHolder: #specChannel
                        )
                       #(#UISubSpecification
                          #name: 'subSpec'
                          #layout: #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1)
                          #majorKey: #ToolApplicationModel
                          #minorKey: #windowSpecForCommit
                        )
                       )
                     
                    )
                  )
                 )
               
              )
            )
           #(#UISubSpecification
              #name: 'infoBarSubSpec'
              #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
              #majorKey: #ToolApplicationModel
              #minorKey: #windowSpecForInfoBar
            )
           )
         
        )
      )
! !

!TabListEditor class methodsFor:'menu specs'!

menu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

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

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'About'
                #activeHelpKey: #about
                #labelImage: #(#ResourceRetriever nil #menuIcon)
                #submenuChannel: #menuAbout
            )
             #(#MenuItem
                #label: 'File'
                #activeHelpKey: #file
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'New'
                          #value: #doNew
                          #activeHelpKey: #fileNew
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Load...'
                          #translateLabel: true
                          #value: #doLoad
                          #activeHelpKey: #fileLoad
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Save'
                          #value: #doSave
                          #activeHelpKey: #fileSave
                      )
                       #(#MenuItem
                          #label: 'Save As...'
                          #value: #doSaveAs
                          #activeHelpKey: #fileSave
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Browse Class'
                          #value: #doBrowseClass
                          #activeHelpKey: #fileBrowseClass
                      )
                       #(#MenuItem
                          #label: '-'
                      )
                       #(#MenuItem
                          #label: 'Exit'
                          #value: #closeRequest
                          #activeHelpKey: #fileExit
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Edit'
                #activeHelpKey: #edit
                #submenuChannel: #menuEdit
            )
             #(#MenuItem
                #label: 'Add'
                #activeHelpKey: #add
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Tab Item'
                          #value: #doCreateTabItem
                          #activeHelpKey: #addTabItem
                          #labelImage: #(#ResourceRetriever nil #newTabItemIcon 'Tab Item')
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Generate'
                #activeHelpKey: #add
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Aspect Method'
                          #value: #doGenerateAspectMethod
                          #activeHelpKey: #fileCreateAspectMethod
                          #enabled: #hasClassAndSelector
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'Test'
                #activeHelpKey: #test
                #submenu: 
                 #(#Menu
                    
                     #(
                       #(#MenuItem
                          #label: 'Preview'
                          #activeHelpKey: #testPreview
                          #enabled: #canShowTestMode
                          #indication: #testMode
                      )
                    ) nil
                    nil
                )
            )
             #(#MenuItem
                #label: 'History'
                #activeHelpKey: #history
                #submenuChannel: #menuHistory
            )
             #(#MenuItem
                #label: 'Help'
                #startGroup: #right
                #activeHelpKey: #help
                #submenuChannel: #menuHelp
            )
          ) nil
          nil
      )
!

menuEdit
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

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

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'Cut'
                #value: #doCut
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
            )
             #(#MenuItem
                #label: 'Copy'
                #value: #doCopy
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
            )
             #(#MenuItem
                #label: 'Paste'
                #value: #doPaste
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPaste
            )
             #(#MenuItem
                #label: 'Delete'
                #value: #doDelete
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanCut
            )
             #(#MenuItem
                #label: '-'
            )
             #(#MenuItem
                #label: 'Move Up'
                #value: #doMoveTabUpOrDown:
                #activeHelpKey: #editMoveUp
                #enabled: #canMoveTabItemUpOrDown
                #argument: #up
                #labelImage: #(#ResourceRetriever #Icon #upIcon 'Move Up')
            )
             #(#MenuItem
                #label: 'Move Down'
                #value: #doMoveTabUpOrDown:
                #activeHelpKey: #editMoveDown
                #enabled: #canMoveTabItemUpOrDown
                #argument: #down
                #labelImage: #(#ResourceRetriever #Icon #downIcon 'Move Down')
            )
          ) nil
          nil
      )
!

menuToolbar
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

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

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

    <resource: #menu>

    ^
     
       #(#Menu
          
           #(
             #(#MenuItem
                #label: 'New'
                #isButton: true
                #value: #doNew
                #activeHelpKey: #fileNew
                #labelImage: #(#ResourceRetriever #Icon #newIcon)
            )
             #(#MenuItem
                #label: 'Load'
                #isButton: true
                #value: #doLoad
                #activeHelpKey: #fileLoad
                #labelImage: #(#ResourceRetriever #Icon #loadIcon)
            )
             #(#MenuItem
                #label: 'Save'
                #isButton: true
                #value: #doSave
                #activeHelpKey: #fileSave
                #labelImage: #(#ResourceRetriever #Icon #saveIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Cut'
                #isButton: true
                #value: #doCut
                #activeHelpKey: #editCut
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever #Icon #cutIcon)
            )
             #(#MenuItem
                #label: 'Copy'
                #isButton: true
                #value: #doCopy
                #activeHelpKey: #editCopy
                #enabled: #valueOfCanCopy
                #labelImage: #(#ResourceRetriever #Icon #copyIcon)
            )
             #(#MenuItem
                #label: 'Paste'
                #isButton: true
                #value: #doPaste
                #activeHelpKey: #editPaste
                #enabled: #valueOfCanPaste
                #labelImage: #(#ResourceRetriever #Icon #pasteIcon)
            )
             #(#MenuItem
                #label: 'Delete'
                #isButton: true
                #value: #doDelete
                #activeHelpKey: #editDelete
                #enabled: #valueOfCanCut
                #labelImage: #(#ResourceRetriever #Icon #deleteIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Add Tab Item'
                #isButton: true
                #value: #doCreateTabItem
                #activeHelpKey: #addTabItem
                #labelImage: #(#ResourceRetriever nil #newTabItemIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Move Tab Up'
                #isButton: true
                #value: #doMoveTabUpOrDown:
                #activeHelpKey: #editMoveUp
                #enabled: #canMoveTabItemUpOrDown
                #argument: #up
                #labelImage: #(#ResourceRetriever #Icon #upIcon)
            )
             #(#MenuItem
                #label: 'Move Tab Down'
                #isButton: true
                #value: #doMoveTabUpOrDown:
                #activeHelpKey: #editMoveDown
                #enabled: #canMoveTabItemUpOrDown
                #argument: #down
                #labelImage: #(#ResourceRetriever #Icon #downIcon)
            )
             #(#MenuItem
                #label: ''
            )
             #(#MenuItem
                #label: 'Preview'
                #activeHelpKey: #testPreview
                #enabled: #canShowTestMode
                #indication: #testMode
            )
          ) nil
          nil
      )
! !

!TabListEditor methodsFor:'aspects'!

canMoveTabItemUpOrDown

    |holder|

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

!

canShowTestMode

    |holder|

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

!

inputGroup

    |holder|

    (holder := builder bindingAt:#inputGroup) isNil ifTrue:[
        builder aspectAt:#inputGroup put:(holder := EnterFieldGroup new)
    ].
    ^ holder.


!

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

    ^ builder listAspectFor:#listOfLabels
!

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
!

testMode

    |holder|

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

! !

!TabListEditor methodsFor:'building'!

buildFromClass:aClass andSelector:aSelector
    "build from class and selector
    "
    |cls spec list selectionHolder|

    self testMode value: false.
    (selectionHolder := self selectionHolder) value:0.

    "if opened on a tab list"
    (aClass isNil and: [aSelector isNil and: [listOfTabs size > 0]]) 
    ifTrue:[
        listOfTabs notEmpty ifTrue:[
            selectionHolder value:1
        ].
        ^ nil
    ].

    self listOfLabels removeAll.
    listOfTabs removeAll.

    testView notNil ifTrue:[
        testView lower
    ].

    rebuildMode := false.

    self canShowTestMode value: false.

    cls := self resolveName:aClass.
    specSelector := aSelector.

    cls notNil ifTrue:[
        specSelector notNil ifTrue:[

            (cls respondsTo:specSelector) ifTrue:[
                spec := cls perform:specSelector.
                list := self listOfLabels.

                spec size ~~ 0 ifTrue:[

                    rebuildMode := true.

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

    modified := false.

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

    self updateInfoLabel
!

buildFromResourceSpec: aListSpec

    self buildFromTabList: aListSpec
!

buildFromTabList: aTabList
    "build from a aTabList"

    |selectionHolder listOfLabels|

    rebuildMode := true.

    (selectionHolder := self selectionHolder) value: nil.
    (listOfLabels := self listOfLabels) removeAll.
    listOfTabs removeAll.

    aTabList do:[:aTabItem|
        listOfTabs add: aTabItem.
        listOfLabels add: aTabItem label
    ].
    rebuildMode := false.          

    modified := false.

    listOfTabs notEmpty ifTrue:[
        selectionHolder value:1
    ].

    self updateInfoLabel
! !

!TabListEditor methodsFor:'change & update'!

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

    someObject = self testMode
    ifTrue:[              
        someObject value
            ifTrue: [self doTest]
            ifFalse:[testView lower. self selectionHolder value:1].

        self updateInfoLabel
    ]
! !

!TabListEditor methodsFor:'help'!

defaultInfoLabel

    ^self testMode value
        ifTrue:  ['Test mode']
        ifFalse: [super defaultInfoLabel]
! !

!TabListEditor methodsFor:'selection'!

selectedIndex
    ^ selectedIndex
!

selectedIndex:anIndex
    |oldSel specChannel|

    self listOfLabels notEmpty ifTrue: [self canShowTestMode value: true].
    anIndex notNil ifTrue: [self testMode value: false].

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

    selectedIndex == oldSel ifTrue:[^ self].

    specChannel := self specChannel.

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

    testView notNil ifTrue:[
        testView lower.
    ].

    self valueOfCanCut value: (anIndex ~~ 0).
    self valueOfCanCopy value: (anIndex ~~ 0).
    self valueOfCanPaste.

! !

!TabListEditor methodsFor:'startup / release'!

initialize
    "setup aspects used by column description specifications
    "

    super initialize.

    listOfTabs    := OrderedCollection new.
    selectedIndex := 0.
    rebuildMode   := false.
!

openModalOnTabList: aTabList
    "build a tab list from aTabList and open it modal"

    super openModalOnResourceSpec: aTabList

!

postBuildWith:builder

    super postBuildWith:builder.

    testView := builder componentAt:#TestView.
    (builder componentAt:#ColumnView) selectConditionBlock: [:i|self askForItemModification].
! !

!TabListEditor methodsFor:'user actions'!

accept
    "accept changes
    "
    |label|

    self acceptChannel 
	value:true; value:false.      "/ toggle to force inputFields to accept

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

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

        rebuildMode := false.
    ].
    self cancel.
    modified := true.
    self valueOfEnablingCommitButtons value: false
!

cancel
    "cancel all changes
    "
    |tab|

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

        rebuildMode := true.

        aspects keysAndValuesDo:[:aKey :aModel|
            aModel value:(tab perform:aKey)    
        ].
        #( label editAgument ) do:[:aKey| |v|
                v := aspects at:aKey.
                v value isNil ifTrue:[v value:'']
        ].

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



!

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

doCreateTabItem

    |tab selectionHolder|

    self testMode value: false.
    tab := TabItem label:'Tab Item ', (listOfTabs size + 1) printString.

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

    selectionHolder := self selectionHolder.

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

    modified := true.
!

doCut
    "cut selected tab
    "
    |listOfLabels index selectionHolder|

    (index := selectedIndex) ~~ 0 ifTrue:[
        self testMode value: false.
        listOfLabels := self listOfLabels.
        self clipboard:(listOfTabs at:index) deepCopy.
        (selectionHolder := self selectionHolder) value:0.
        listOfTabs removeIndex:index.
        listOfLabels removeIndex:index.
        index > listOfLabels size ifTrue:[
            index := index - 1
        ].
        selectionHolder value:index.
        listOfLabels isEmpty ifTrue: [self canShowTestMode value: false].
        self updateAllToolInstances.
        modified := true.
    ].

!

doDelete
    "delete selected tab
    "
    |listOfLabels index selectionHolder|

    (index := selectedIndex) ~~ 0 ifTrue:[
        self testMode value: false.
        listOfLabels := self listOfLabels.
        (selectionHolder := self selectionHolder) value:0.
        listOfTabs removeIndex:index.
        listOfLabels removeIndex:index.
        index > listOfLabels size ifTrue:[index := index - 1].
        selectionHolder value:index.
        listOfLabels isEmpty ifTrue: [self canShowTestMode value: false].
        modified := true.
    ].       
!

doGenerateAspectMethod
    "generate aspect method
    "
    |cls code|

    (specClass notNil and:[specSelector notNil])
    ifFalse:
    [
        ^self information:'No class and selector defined!!'   
    ].

    cls := self resolveName: specClass.

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

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

    code := '!!' , cls name , ' methodsFor:''aspects''!!\\' ,
            specSelector , '\' ,
            '    "Generated by the TabListEditor"\' ,
            '\' ,
            '    |list|\' ,
            '\' ,
            '    (list := builder bindingAt:#' , specSelector , ') isNil ifTrue:[\' ,
            '        builder aspectAt:#' , specSelector, ' put:(list := self class ', specSelector, ').\' ,
            '    ].\' ,
            '    ^ list\' ,
            '!! !!\\'.

    (ReadStream on:(code withCRs)) fileIn


!

doMoveTabUpOrDown:what
    "step up or down
    "
    |tab listOfLabels index nLabels|

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

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

    listOfLabels removeIndex:selectedIndex.
    listOfTabs removeIndex:selectedIndex.

    nLabels := listOfLabels size.

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

    listOfLabels add:(tab label) beforeIndex:index.
    listOfTabs add:tab beforeIndex:index.

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

    modified := true.

!

doPaste
    "paste a tab
    "
    |tab selectionHolder|

    self testMode value: false.
    (tab := self class clipboard deepCopy) isNil ifTrue: [^nil].
    listOfTabs add:tab afterIndex:selectedIndex.
    self listOfLabels add:(tab label) afterIndex:selectedIndex.

    selectionHolder := self selectionHolder.

    selectedIndex == 0 ifTrue:[
        selectionHolder value:1
    ] ifFalse:[    
        selectionHolder value:selectedIndex + 1.
        self cancel.
    ].
      
    modified  := true.

!

doSave
    "generate code for class and instance
    "
    |cls code spec category mthd list|

    (specClass notNil and:[specSelector notNil])
    ifFalse:
    [
        ^self doSaveAs
    ].

    cls := self resolveName: specClass.

    listOfTabs isEmpty ifTrue:[^self information:'No tab list defined!!'].

    spec  := WriteStream on:String new.
    list := Array new:(listOfTabs size).
    listOfTabs keysAndValuesDo:[:i :el|list at:i put:(el literalArrayEncoding)].

    UISpecification prettyPrintSpecArray:list on:spec indent:5.
    spec := spec contents.

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

    category := 'list specs'.

    (mthd := cls class compiledMethodAt:specSelector) notNil ifTrue:[
        category := mthd category.
    ].

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

            , specSelector , '\'
            , (self class codeGenerationComment replChar:$!! withString:'!!!!')
            , '\\    "\'
            , '     TabListEditor new openOnClass:' , cls name , ' andSelector:#' , specSelector , '\'
            , '    "\'.

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

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

    (cls canUnderstand:specSelector) ifFalse:[
        (YesNoBox confirm:'Generate aspect method?') ifTrue:[
            self doGenerateAspectMethod
        ]
    ].

    self addToHistory:(cls name, ' ', specSelector) -> #loadFromMessage:.
    modified  := false.
    hasSaved  := true.
!

doTest
    "run a test
    "
    |tabView list|

    self selectionHolder value:nil.

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

    self valueOfCanCut value: false.
    self valueOfCanCopy value: false.
    self valueOfCanPaste value: false.

! !

!TabListEditor class methodsFor:'documentation'!

version
    ^ '$Header$'
! !