TabListEditor.st
changeset 739 cc3413fc1afb
child 749 8f8767c6f32f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TabListEditor.st	Fri Mar 20 19:11:50 1998 +0100
@@ -0,0 +1,1285 @@
+"
+ 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
+"
+
+
+! !
+
+!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
+    )
+
+! !
+
+!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 argument not explicitly used by 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
+          #window: 
+           #(#WindowSpec
+              #name: 'Tab Basic'
+              #layout: #(#LayoutFrame 463 0 289 0 825 0 514 0)
+              #label: 'Tab Basic'
+              #min: #(#Point 10 10)
+              #max: #(#Point 1280 1024)
+              #bounds: #(#Rectangle 463 289 826 515)
+              #usePreferredExtent: false
+          )
+          #component: 
+           #(#SpecCollection
+              #collection: 
+               #(
+                 #(#LabelSpec
+                    #name: 'Label'
+                    #layout: #(#AlignmentOrigin 98 0 26 0 1 0.5)
+                    #label: 'Label:'
+                    #resizeForLabel: true
+                )
+                 #(#InputFieldSpec
+                    #name: 'LabelField'
+                    #layout: #(#LayoutFrame 100 0 15 0 -5 1.0 37 0)
+                    #activeHelpKey: #label
+                    #model: #label
+                )
+                 #(#CheckBoxSpec
+                    #name: 'TranslateLabel'
+                    #layout: #(#LayoutFrame 100 0 40 0 -5 1 66 0)
+                    #activeHelpKey: #labelDerivesFromApplication
+                    #model: #translateLabel
+                    #label: 'Label derives from Application'
+                )
+                 #(#LabelSpec
+                    #name: 'ArgumentLabel'
+                    #layout: #(#AlignmentOrigin 98 0 81 0 1 0.5)
+                    #label: 'Argument:'
+                    #resizeForLabel: true
+                )
+                 #(#InputFieldSpec
+                    #name: 'ArgumentField'
+                    #layout: #(#LayoutFrame 100 0 70 0 -5 1.0 92 0)
+                    #activeHelpKey: #argument
+                    #model: #editAgument
+                )
+                 #(#LabelSpec
+                    #name: 'ForegroundLabel'
+                    #layout: #(#AlignmentOrigin 98 0 115 0 1 0.5)
+                    #label: 'Color:'
+                    #adjust: #right
+                    #resizeForLabel: true
+                )
+                 #(#ColorMenuSpec
+                    #name: 'ForegroundColorMenu'
+                    #layout: #(#LayoutFrame 100 0 103 0 -5 1.0 125 0)
+                    #activeHelpKey: #color
+                    #model: #labelForegroundColor
+                    #labelsAreColored: false
+                )
+                 #(#CheckBoxSpec
+                    #name: 'CanSelect'
+                    #layout: #(#LayoutFrame 100 0 135 0 -5 1 157 0)
+                    #activeHelpKey: #canSelect
+                    #model: #enabled
+                    #label: 'Can Select'
+                )
+              )
+          )
+      )
+!
+
+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
+          #window: 
+           #(#WindowSpec
+              #name: 'Tab List Editor'
+              #layout: #(#LayoutFrame 516 0 302 0 984 0 630 0)
+              #label: 'Tab List Editor'
+              #min: #(#Point 10 10)
+              #max: #(#Point 1152 900)
+              #bounds: #(#Rectangle 516 302 985 631)
+              #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
+                    #showSeparatingLines: true
+                )
+                 #(#VariableHorizontalPanelSpec
+                    #name: 'VariablePanel'
+                    #layout: #(#LayoutFrame 0 0.0 36 0.0 0 1.0 -26 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'
+                              #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
+                                    )
+                                  )
+                              )
+                              #level: -1
+                          )
+                        )
+                    )
+                    #handles: #(#Any 0.259875 1.0)
+                )
+                 #(#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: 'Settings'
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Fonts'
+                          #submenuChannel: #menuFont
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#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 #ToolApplicationModel #upIcon 'Move Up')
+            )
+             #(#MenuItem
+                #label: 'Move Down'
+                #value: #doMoveTabUpOrDown:
+                #activeHelpKey: #editMoveDown
+                #enabled: #canMoveTabItemUpOrDown
+                #argument: #down
+                #labelImage: #(#ResourceRetriever #ToolApplicationModel #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 nil #newIcon)
+            )
+             #(#MenuItem
+                #label: 'Load'
+                #isButton: true
+                #value: #doLoad
+                #activeHelpKey: #fileLoad
+                #labelImage: #(#ResourceRetriever nil #loadIcon)
+            )
+             #(#MenuItem
+                #label: 'Save'
+                #isButton: true
+                #value: #doSave
+                #activeHelpKey: #fileSave
+                #labelImage: #(#ResourceRetriever nil #saveIcon)
+            )
+             #(#MenuItem
+                #label: ''
+            )
+             #(#MenuItem
+                #label: 'Cut'
+                #isButton: true
+                #value: #doCut
+                #activeHelpKey: #editCut
+                #enabled: #valueOfCanCut
+                #labelImage: #(#ResourceRetriever nil #cutIcon)
+            )
+             #(#MenuItem
+                #label: 'Copy'
+                #isButton: true
+                #value: #doCopy
+                #activeHelpKey: #editCopy
+                #enabled: #valueOfCanCopy
+                #labelImage: #(#ResourceRetriever nil #copyIcon)
+            )
+             #(#MenuItem
+                #label: 'Paste'
+                #isButton: true
+                #value: #doPaste
+                #activeHelpKey: #editPaste
+                #enabled: #valueOfCanPaste
+                #labelImage: #(#ResourceRetriever nil #pasteIcon)
+            )
+             #(#MenuItem
+                #label: 'Delete'
+                #isButton: true
+                #value: #doDelete
+                #activeHelpKey: #editDelete
+                #enabled: #valueOfCanCut
+                #labelImage: #(#ResourceRetriever nil #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 nil #upIcon)
+            )
+             #(#MenuItem
+                #label: 'Move Tab Down'
+                #isButton: true
+                #value: #doMoveTabUpOrDown:
+                #activeHelpKey: #editMoveDown
+                #enabled: #canMoveTabItemUpOrDown
+                #argument: #down
+                #labelImage: #(#ResourceRetriever nil #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
+
+!
+
+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
+!
+
+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|
+
+    self testMode value: false.
+    self selectionHolder value:0.
+
+    "if opened on a tab list"
+    (aClass isNil and: [aSelector isNil and: [listOfTabs size > 0]]) 
+    ifTrue: 
+    [
+        listOfTabs notEmpty ifTrue:[
+            self 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"
+
+    rebuildMode := true.
+
+    self selectionHolder value: nil.
+    self listOfLabels removeAll.
+    listOfTabs removeAll.
+
+    aTabList do:[:aTabItem|
+        listOfTabs add: aTabItem.
+        self listOfLabels add: aTabItem label
+    ].
+    rebuildMode := false.          
+
+    modified := false.
+
+    listOfTabs notEmpty ifTrue:[
+        self 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
+    |s oldSel|
+
+    self listOfLabels notEmpty ifTrue: [self canShowTestMode value: true].
+    anIndex notNil ifTrue: [self testMode value: false].
+
+    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.
+    ].
+
+    self valueOfCanCut value: (anIndex ~~ 0).
+    self valueOfCanCopy value: (anIndex ~~ 0).
+    self valueOfCanPaste.
+
+    self updateFonts
+! !
+
+!TabListEditor methodsFor:'startup / release'!
+
+initialize
+    "setup aspects used by column description specifications
+    "
+    |holder|
+
+    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|
+
+    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)    
+        ].
+
+        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
+    ]
+!
+
+doCreateTabItem
+
+    |tab|
+    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.
+
+    selectedIndex == 0 ifTrue:[
+        self selectionHolder value:1
+    ] ifFalse:[    
+        self selectionHolder value:selectedIndex + 1.
+        self cancel.
+    ].
+
+    modified := true.
+!
+
+doCut
+    "cut selected tab
+    "
+    |list index|
+
+    (index := selectedIndex) ~~ 0 ifTrue:[
+        self testMode value: false.
+        list := self listOfLabels.
+        self clipboard:(listOfTabs at:index) deepCopy.
+        self selectionHolder value:0.
+        listOfTabs removeIndex:index.
+        list removeIndex:index.
+        index > list size ifTrue:[
+            index := index - 1
+        ].
+        self selectionHolder value:index.
+        self listOfLabels isEmpty ifTrue: [self canShowTestMode value: false].
+        modified := true.
+    ].
+
+!
+
+doDelete
+    "delete selected tab
+    "
+    |list index|
+
+    (index := selectedIndex) ~~ 0 ifTrue:[
+        self testMode value: false.
+        list := self listOfLabels.
+        self selectionHolder value:0.
+        listOfTabs removeIndex:index.
+        list removeIndex:index.
+        index > list size ifTrue:[index := index - 1].
+        self selectionHolder value:index.
+        self 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 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.
+
+    rebuildMode := true.
+    self selectionHolder value:index.
+    rebuildMode := false.
+
+    modified := true.
+
+!
+
+doPaste
+    "paste a tab
+    "
+    |tab|
+
+    self testMode value: false.
+    (tab := self class clipboard deepCopy) isNil ifTrue: [^nil].
+    listOfTabs add:tab afterIndex:selectedIndex.
+    self listOfLabels add:(tab label) afterIndex:selectedIndex.
+
+    selectedIndex == 0 ifTrue:[
+        self selectionHolder value:1
+    ] ifFalse:[    
+        self selectionHolder value:selectedIndex + 1.
+        self cancel.
+    ].
+      
+    modified  := true.
+
+!
+
+doSave
+    "generate code for class and instance
+    "
+    |cls code spec category mthd|
+
+    (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.
+    UISpecification prettyPrintSpecArray:(listOfTabs literalArrayEncoding) 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: /files/CVS/stx/libtool2/TabListEditor.st,v'
+! !