total redeisign
authorClaus Gittinger <cg@exept.de>
Mon, 07 Jun 1999 14:45:09 +0200
changeset 1401 e92d55efca08
parent 1400 8dc98beb1ee9
child 1402 e97d4a6587a0
total redeisign including: NoteBookView TabView TabViewSpec UIGalleryView
NoteBookView.st
TabView.st
--- a/NoteBookView.st	Fri May 28 20:07:15 1999 +0200
+++ b/NoteBookView.st	Mon Jun 07 14:45:09 1999 +0200
@@ -1,6 +1,39 @@
 "
  COPYRIGHT (c) 1997 by eXept Software AG
-	      All Rights Reserved
+              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.
+"
+
+
+View subclass:#NoteBookView
+	instanceVariableNames:'list listHolder foregroundColor selection enabled action useIndex
+		direction numberOfLines selectConditionBlock expandSelection
+		canvas canvasInset canvasHolder halfLightColor halfShadowColor
+		fitLastRow tabModus'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Views-Layout'
+!
+
+Object subclass:#Tab
+	instanceVariableNames:'label model printableLabel disabledLabel lineNr layout extent'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:NoteBookView
+!
+
+!NoteBookView 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
@@ -10,301 +43,1557 @@
  hereby transferred.
 "
 
-SimpleView subclass:#NoteBookView
-	instanceVariableNames:'tabRaw canvas canvasHolder'
-	classVariableNames:''
-	poolDictionaries:''
-	category:'Views-Layout'
-!
-
-!NoteBookView 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
 "
-    this is not yet finished - for now it implements a Notebook
+    implements the noteBook.
+    May also be used on its own (without a surrounding noteBook).
+
+    [author:]
+        Claus Atzkern
 
     [see also:]
         TabView
 "
+
 !
 
 examples
 "
     tabs at top ( default )
                                                                                 [exBegin]                                      
-    |top tab view inset|
+    |top tab|
 
-    top  := StandardSystemView new label:'test'; extent:250@100.
-    view := NoteBookView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
-    view list:#( 'Foo' 'Bar' 'Baz' ).
-    view action:[:aName| Transcript showCR:aName].
-
+    top  := StandardSystemView extent:250@100.
+    tab := NoteBook origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
+    tab list:#( 'Foo' 'Bar' 'Baz' ).
+    tab action:[:aName| Transcript showCR:aName].
     top open.
                                                                                 [exEnd]
 
 
     tabs at bottom
                                                                                 [exBegin]                                      
-    |top tab view inset|
+    |top tab|
 
-    top  := StandardSystemView new label:'test'; extent:250@100.
-    view := NoteBookView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
-    view direction:#bottom.
-    view list:#( 'Foo' 'Bar' 'Baz' ).
-    view action:[:aName| Transcript showCR:aName].
-
+    top  := StandardSystemView extent:250@100.
+    tab := NoteBook origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
+    tab direction:#bottom.
+    tab list:#( 'Foo' 'Bar' 'Baz' ).
+    tab action:[:aName| Transcript showCR:aName].
     top open.
                                                                                 [exEnd]
 
     tabs at left
                                                                                 [exBegin]                                      
-    |top tab view inset|
+    |top tab|
 
-    top  := StandardSystemView new label:'test'; extent:100@200.
-    view := NoteBookView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
-    view direction:#left.
-    view list:#( 'Foo' 'Bar' 'Baz' ).
-    view action:[:aName| Transcript showCR:aName].
-
+    top  := StandardSystemView extent:100@200.
+    tab := NoteBook origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
+    tab direction:#left.
+    tab list:#( 'Foo' 'Bar' 'Baz' ).
+    tab action:[:aName| Transcript showCR:aName].
     top open.
                                                                                 [exEnd]
 
     tabs at right
                                                                                 [exBegin]                                      
-    |top tab view inset|
+    |top tab|
 
-    top  := StandardSystemView new label:'test'; extent:100@200.
-    view := NoteBookView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
-    view direction:#right.
-    view list:#( 'Foo' 'Bar' 'Baz' ).
-    view action:[:aName| Transcript showCR:aName].
-
+    top  := StandardSystemView extent:100@200.
+    tab := NoteBook origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.
+    tab direction:#right.
+    tab list:#( 'Foo' 'Bar' 'Baz' ).
+    tab action:[:aName| Transcript showCR:aName].
     top open.
                                                                                 [exEnd]
 
 
 "
+
+! !
+
+!NoteBookView class methodsFor:'claus'!
+
+test2:aDirection
+    |top tab|
+
+    top := StandardSystemView extent:300@300.
+    tab  := NoteBookView origin:0.1 @ 0.1 corner:0.9 @ 0.9 in:top.
+    tab direction:aDirection.
+    tab tabModus:true.
+    tab list:#( 'Tab 1' 'Tab 2' 'Tab 3' 'XgQTab 4' ).
+    tab action:[:aLabel| Transcript showCR:aLabel].
+    top open.
+
+
+!
+
+test:aDirection
+    |top tab|
+
+    top := StandardSystemView extent:300@300.
+    tab  := NoteBookView origin:0.1 @ 0.1 corner:0.9 @ 0.9 in:top.
+    tab direction:aDirection.
+    tab list:#( 'Tab 1' 'Tab 2' 'Tab 3' 'XgQTab 4' ).
+    tab canvas:(ClockView new).
+    tab action:[:aLabel| Transcript showCR:aLabel].
+    top open.
+
+
+! !
+
+!NoteBookView class methodsFor:'defaults'!
+
+defaultFont
+    ^ MenuView defaultFont
 ! !
 
 !NoteBookView methodsFor:'accessing'!
 
+action:oneArgBlock
+    "set the action block to be performed on select; the argument to
+     the block is the selected index or nil in case of no selection.
+    "
+    action := oneArgBlock.
+
+!
+
 canvas
-    "returns canvas; the container view
-    "
     ^ canvas
 !
 
 canvas:aCanvas
     "change canvas; the containter view
     "
-    |origin corner|
+    aCanvas == canvas ifFalse:[
+        canvas notNil ifTrue:[
+            canvas destroy.
+        ].
+        (canvas := aCanvas) notNil ifTrue:[
+            tabModus := false.
+            self addSubView:canvas.
+
+            (shown and:[numberOfLines notNil]) ifTrue:[
+                canvas layout:(self computeCanvasLayout)
+            ]
+        ]
+    ].
+!
+
+list
+    "return the list of Tabs or Labels
+    "
+    ^ list collect:[:aTab| aTab label ]
+
+!
 
-    aCanvas == canvas ifFalse:[
-        canvas destroy.
+list:aList
+    "set the list
+    "
+    |size|
+
+    list do:[:aTab| aTab removeDependent:self].
+
+    aList notNil ifTrue:[
+        list := aList collect:[:el| Tab label:el on:self].
+        list do:[:aTab| aTab addDependent:self].
+    ] ifFalse:[
+        list := #()
+    ].
+    preferredExtent := nil.
+    numberOfLines   := nil.
+
+    selection notNil ifTrue:[
+        selection > list size ifTrue:[
+            selection := nil.
+            self selectionChanged.
+        ]
+    ].
+    shown ifTrue:[
+        self invalidate
+    ].
+
+!
 
-        (canvas := aCanvas) isNil ifTrue:[
-            canvas := View in:self
-        ] ifFalse:[
-            self addSubView:canvas.
-        ].
-        canvas viewBackground:viewBackground.
-        canvas allSubViewsDo:[:s|s viewBackground:viewBackground].
-        canvas origin:0.0@0.0 corner:1.0@1.0.
+listIndexOf:something
+    "convert something to an index into list or nil.
+    "
+    |index|
+
+    something isNil ifTrue:[^ nil ].
+
+    something isNumber ifTrue:[
+        index := something
+    ] ifFalse:[
+        index := list findFirst:[:aTab|aTab label = something].
+        index == 0 ifTrue:[
+            index := list findFirst:[:aTab|aTab printableLabel = something]
+        ]
+    ].
+    ^ (index between:1 and:list size) ifTrue:[index] ifFalse:[nil]
+
+
+!
+
+useIndex
+    "use index instead of name
+    "
+    ^ useIndex
+
+
+!
+
+useIndex:aBoolean
+    "set/clear the useIndex flag. If set, both actionBlock and change-messages
+     are passed the index(indices) of the selection as argument. 
+     If clear, the value(s) (i.e. the selected string) is passed.
+     Default is false."
+
+    useIndex := aBoolean
+
+
+! !
+
+!NoteBookView methodsFor:'accessing behavior'!
+
+enabled
+    "returns true if tabs are enabled
+    "
+    ^ enabled
+!
+
+enabled:aState
+    "set enabled state
+    "
+    |state|
+
+    state := aState ? true.
+
+    enabled ~~ state ifTrue:[
+        enabled := state.
+        self invalidate.
     ]
 !
 
-labels
-    ^ tabRaw list
+selectConditionBlock
+    "get the conditionBlock; this block is evaluated before a selection
+     change is performed; the change will not be done, if the evaluation
+     returns false. The argument to the block is the selection index
+    "
+    ^ selectConditionBlock
 !
 
-labels:aListOfLabels
-    tabRaw list:aListOfLabels
+selectConditionBlock:aOneArgBlock
+    "get the conditionBlock; this block is evaluated before a selection
+     change is performed; the change will not be done, if the evaluation
+     returns false. The argument to the block is the selection index
+    "
+    selectConditionBlock := aOneArgBlock
 ! !
 
-!NoteBookView methodsFor:'accessing holders'!
+!NoteBookView methodsFor:'accessing channels/holders'!
 
 canvasHolder
+    "get the model, which keeps the canvas, a kind of SimpleView
+    "
     ^ canvasHolder
 !
 
 canvasHolder:aValueHolder
-    canvasHolder notNil ifTrue:[
-        canvasHolder removeDependent:self. 
+    "set the model, which keeps the canvas, a kind of SimpleView
+    "
+    canvasHolder removeDependent:self. 
+
+    (canvasHolder := aValueHolder) notNil ifTrue:[
+        canvasHolder addDependent:self.
+        self canvas:(canvasHolder value)
+    ]
+
+
+!
+
+listHolder
+    "get the model, which keeps the list of Tabs or Labels
+    "
+    ^ listHolder
+!
+
+listHolder:aValueHolder
+    "set the model, which keeps the list of Tabs or Labels
+    "
+    listHolder removeDependent:self. 
+
+    (listHolder := aValueHolder) notNil ifTrue:[
+        listHolder addDependent:self.
+        self list:listHolder value.
     ].
-    canvasHolder := aValueHolder .
-    self canvas:(canvasHolder value).
 !
 
-labelsHolder
-    ^ tabRaw listHolder
+model:aValueHolder
+    "set the model, which keeps the selection
+    "
+    super model:aValueHolder.
+
+    model notNil ifTrue:[
+        self selection:(model value)
+    ]
+! !
+
+!NoteBookView methodsFor:'accessing dimension'!
+
+maxTabHeight
+    |e y|
+
+    e := self preferredExtent.
+    y := self isHorizontal ifTrue:[e y] ifFalse:[e x].
+  ^ y - (expandSelection y)
 !
 
-labelsHolder:aHolder
-    tabRaw listHolder:aHolder
+preferredExtent
+    "compute max extent x/y based on one line
+    "
+    |x "{ Class:SmallInteger }"
+     y "{ Class:SmallInteger }"
+    |
+    preferredExtent isNil ifTrue:[
+        y := 0.
+        x := 0.
+
+        list notEmpty ifTrue:[
+            list do:[:aTab|
+                x := x + aTab preferredExtentX.
+                y := y max:(aTab preferredExtentY).
+            ]
+        ].
+        y := y + (expandSelection y).
+        x := x + (expandSelection x).
+        preferredExtent := self isHorizontal ifTrue:[x @ y] ifFalse:[y @ x]
+    ].
+    ^ preferredExtent
+!
+
+preferredSizeXorY
+    "returns preferred size dependant on the current view layout and
+     the direction of the tabs
+    "
+    |e y|
+
+    list isEmpty ifTrue:[^ 0].
+
+    y := self maxTabHeight.
+    e := expandSelection y.
+
+    numberOfLines isNil ifTrue:[
+        self shown ifFalse:[^ y + e ].
+        self recomputeList.
+    ].
+    ^ numberOfLines * y + e
 ! !
 
 !NoteBookView methodsFor:'accessing look'!
 
-backgroundColor:aColor
-    "change viewBackground
+backgroundColor
+    "get backgroundColor of the notebook view
     "
-    self viewBackground:aColor
+    ^ viewBackground
 !
 
-font:aFont
-    "set a font
+foregroundColor
+    "get the color to be used for drawing text
     "
-    super font:aFont.
-    tabRaw font:aFont.
+    ^ foregroundColor
+!
+
+foregroundColor:aColor
+    "set the color to be used for drawing text
+    "
+    aColor ~= foregroundColor ifTrue:[
+        foregroundColor := aColor.
+
+        shown ifTrue:[
+            self invalidate
+        ]
+    ]
 
 !
 
-viewBackground:aColor
-    "viewBackground changed
+halfLightColor
+    "get the color to be used for drawing text
     "
-    viewBackground ~~ aColor ifTrue:[
-        super  viewBackground:aColor.
-        tabRaw viewBackground:viewBackground.
-        canvas allSubViewsDo:[:s| s viewBackground:viewBackground].
-    ]
+    ^ halfLightColor
+!
+
+halfShadowColor
+    ^ halfShadowColor
+!
+
+lightColor
+    "get the color to be used for lighted edges
+    "
+    ^ lightColor
+!
+
+shadowColor
+    "get the color to be used for shadowed edges
+    "
+    ^ shadowColor
 ! !
 
-!NoteBookView methodsFor:'actions'!
+!NoteBookView methodsFor:'accessing style'!
+
+direction
+    "returns the direction of tabs as symbol. On default the value is
+     set to #top. Valid symbols are:
+	#top       arrange tabs to be on top of a view
+	#bottom    arrange tabs to be on bottom of a view
+	#left      arrange tabs to be on left of a view
+	#right     arrange tabs to be on right of a view
+    "
+    ^ direction
+
+!
+
+direction:aDirection
+    "change the direction of tabs. On default the value is set to #top.
+     Valid symbols are:
+        #top       arrange tabs to be on top of a view
+        #bottom    arrange tabs to be on bottom of a view
+        #left      arrange tabs to be on left of a view
+        #right     arrange tabs to be on right of a view
+    "
+    direction ~~ aDirection ifTrue:[
+        direction       := aDirection.
+        preferredExtent := nil.
+        numberOfLines   := nil.
+        self invalidate.
+    ].
+!
 
-clearCanvas
-    "destroy all subviews in canvas
+fitLastRow
+    "in case of true, the last row is expanded to the view  size like all
+     other raws. In case of false all the tabs in the last raw keep their
+     preferred extent (x or y) dependant on the direction.
+    "
+    ^ fitLastRow
+!
+
+fitLastRow:aBool
+    "in case of true, the last row is expanded to the view  size like all
+     other raws. In case of false all the tabs in the last raw keep their
+     preferred extent (x or y) dependant on the direction.
     "
-    canvas destroySubViews
+    fitLastRow := aBool
+!
+
+tabModus
+    ^ tabModus
+!
 
+tabModus:aBoolean
+
+    tabModus ~~ aBoolean ifTrue:[
+        (aBoolean and:[canvas notNil]) ifFalse:[
+            tabModus := aBoolean.
+            numberOfLines := nil.
+            shown ifTrue:[self invalidate]
+        ]
+    ]
 
 ! !
 
 !NoteBookView methodsFor:'change & update'!
 
-recomputeSizes
-    "recompute sizes dependent on list
+update:something with:aParameter from:changedObject
+    "one of my models changed its value
+    "
+    |idx tab|
+
+    changedObject == model         ifTrue:[^ self selection:model value].
+    changedObject == listHolder    ifTrue:[^ self list:(listHolder value)].
+    changedObject == enableChannel ifTrue:[^ self enabled:enableChannel value].
+
+    (idx := list findFirst:[:aTab| aTab label == changedObject]) ~~ 0 ifTrue:[
+        tab := list at:idx.
+
+        idx == selection ifTrue:[
+            tab isEnabled ifFalse:[
+                ^ self selection:nil
+            ]
+        ].
+        tab label:(tab label) on:self.
+        self invalidateTab:tab
+    ]
+! !
+
+!NoteBookView methodsFor:'drawing'!
+
+invalidateTab:aTab
+    "invalidate a tab
+    "
+    shown ifTrue:[
+        self invalidate:(self computeLayoutForTab:aTab)
+    ]
+!
+
+redrawX:x y:y width:w height:h
+    "a region must be redrawn
     "
-    |y x tabExt maxExt|
+    |savClip selTab damage lyt savLyt|
+
+    self shown ifFalse:[
+        ^ self
+    ].
+    numberOfLines isNil ifTrue:[
+        self recomputeList.
+      ^ self invalidate
+    ].
+    selTab := selection notNil ifTrue:[list at:selection] ifFalse:[nil].
+
+    (selTab notNil and:[selTab lineNr ~~ 1]) ifTrue:[
+        self makeToBaseLine:(selTab lineNr).
+      ^ self invalidate
+    ].
+
+    self paint:(self viewBackground).
+    self fillRectangleX:x y:y width:w height:h.
+
+    savClip := clipRect.
+    damage  := Rectangle left:x top:y width:w height:h.
+    self clippingRectangle:damage.
+
+    list notEmpty ifTrue:[
+        numberOfLines to:1 by:-1 do:[:aLnNr|
+            list reverseDo:[:aTab|
+                (     aTab lineNr == aLnNr
+                 and:[aTab ~~ selTab
+                 and:[aTab intersects:damage]]
+                ) ifTrue:[
+                    aTab redrawAt:direction selected:false on:self
+                ]
+            ]
+        ]
+    ] ifFalse:[
+        selTab := nil
+    ].
+
+    tabModus ifFalse:[
+        lyt := self computeBorderLayout.
 
-    maxExt := self extent - (margin * 2).
-    tabExt := tabRaw preferredExtent.
+        self drawEdgesForX:lyt left 
+                         y:lyt top
+                     width:lyt width 
+                    height:lyt height
+                     level:2
+                    shadow:shadowColor 
+                    light:lightColor
+                    halfShadow:halfShadowColor 
+                    halfLight:halfLightColor 
+                    style:#softWin95.
+    ].
+
+
+    selTab notNil ifTrue:[
+        lyt := self computeLayoutForTab:selTab.
+
+        (lyt intersects:damage) ifTrue:[
+            savLyt := selTab layout.
+            selTab layout:lyt.
+            selTab redrawAt:direction selected:true on:self.
+            selTab layout:savLyt.
+        ]
+    ].
+    self clippingRectangle:savClip
+! !
+
+!NoteBookView methodsFor:'event handling'!
+
+buttonPress:button x:x y:y
+    "a button is pressed; find tab under point and set the selection
+    "
+    |idx|
+
+    (enabled and:[list notEmpty]) ifTrue:[
+        idx := list findFirst:[:aTab| aTab containsPointX:x y:y ].
 
-    x := tabExt x.
-    y := tabExt y.
+        (idx ~~ 0 and:[(list at:idx) isEnabled]) ifTrue:[
+            self selection:idx
+        ]
+    ]
+!
+
+keyPress:aKey x:x y:y
+    "selection might change; look for corresponding list entry
+    "
+    |size index n|
+
+    (enabled and:[(size := list size) > 1]) ifFalse:[
+        ^ self
+    ].
+
+    (aKey == #CursorRight or:[aKey == #CursorDown]) ifTrue:[
+        n := selection ? 0.
+
+        (size - 1) timesRepeat:[
+            (n := n + 1) > size ifTrue:[n := 1].
+
+            (self isSelectable:n) ifTrue:[
+                ^ self selection:n
+            ]
+        ].
+        ^ self
+    ].
+
+    (aKey == #CursorLeft or:[aKey == #CursorUp]) ifTrue:[
+        n := selection ? size.
+
+        (size - 1) timesRepeat:[
+            (n := n - 1) < 1 ifTrue:[n := size].
+
+            (self isSelectable:n) ifTrue:[
+                ^ self selection:n
+            ]
+        ].
+        ^ self
+    ].
+
+    aKey isCharacter ifTrue:[
+        (selection isNil or:[selection == size]) ifTrue:[index := 1]
+                                                ifFalse:[index := selection + 1].
 
-    canvas viewBackground:(tabRaw styleAt:#selectedColor).
-    tabRaw isHorizontalDirection ifTrue:[
-        x > (maxExt x) ifTrue:[y := tabRaw preferredSizeXorY].
+        n := index - 1.
+        [   
+            n := self findTabStartingWithKey:aKey startingAt:n + 1.
+
+            (n ~~ 0 and:[self isSelectable:n]) ifTrue:[
+                ^ self selection:n
+            ].
+            n ~~ 0
+
+        ] whileTrue.
+
+        index ~~ 1 ifTrue:[
+            (n := self findTabStartingWithKey:aKey startingAt:1) ~~ 0 ifTrue:[
+                ^ self selection:n
+            ]
+        ]
+    ].
+
+    super keyPress:aKey x:x y:y
+!
+
+sizeChanged:how
+    "size of view changed 
+    "
+    super sizeChanged:how.
+
+    list notEmpty ifTrue:[
+        numberOfLines := nil.
+        shown ifTrue:[self invalidate]
+    ]
+! !
+
+!NoteBookView methodsFor:'initialize / release'!
+
+destroy
+    "remove dependencies
+    "
+    list removeDependent:self.
+
+    listHolder    removeDependent:self. 
+    enableChannel removeDependent:self.
+    canvasHolder  removeDependent:self.
+
+    super destroy.
+!
+
+initStyle
+    "setup style attributes
+    "
+
+    super initStyle.
+    self font:self class defaultFont.
+    foregroundColor := Color black on:device.
+    shadowColor     := foregroundColor.
+    halfLightColor  := Color white on:device.
+    halfShadowColor := Color gray  on:device.
+    tabModus        := false.
+!
+
+initialize
+    "setup default attributes
+    "
+    super initialize.
+
+    self cursor:Cursor hand.
+
+    list            := #().
+    useIndex        := false.
+    direction       := #top.
+    fitLastRow      := true.
+    enabled         := true.
+    expandSelection := 6@4.
+    canvasInset     := 8.
+
+    self lineWidth:0.
+
+    canvas notNil ifTrue:[
+        canvas := canvas in:self.
+    ].
 
-        tabRaw direction == #top ifTrue:[
-            tabRaw origin:0.0@0.0 corner:1.0@(y+margin).
-            canvas origin:0.0@(y+margin) corner:1.0@1.0.
+! !
+
+!NoteBookView methodsFor:'layout'!
+
+computeBorderLayout
+    |xL yT xR yB tab|
+
+    self paint:lightColor.
+    tab := list detect:[:aTab| aTab lineNr == 1] ifNone:nil.
+    xL  := 0.
+    yT  := 0.
+    xR  := width.
+    yB  := height.
+
+    tab notNil ifTrue:[
+                 direction == #top    ifTrue:[yT := tab layout bottom]
+        ifFalse:[direction == #bottom ifTrue:[yB := tab layout top]
+        ifFalse:[direction == #left   ifTrue:[xL := tab layout right]
+                                     ifFalse:[xR := tab layout left]]]
+    ].
+    ^ Rectangle left:xL top:yT right:xR bottom:yB
+
+!
+
+computeCanvasLayout
+
+    ^ self computeBorderLayout expandBy:(canvasInset negated).
+
+!
+
+computeLayoutForTab:aTab
+    "calculate extent of a tab
+    "
+    |layout x y w h level|
+
+    layout := aTab layout.
+    level  := 2.
+
+    self selectedTab == aTab ifTrue:[
+        layout := layout copy.
+        w := expandSelection x.
+        h := expandSelection y.
+        x := w // 2.
+        y := h // 2.
+
+        self isHorizontal ifTrue:[
+            layout setLeft:(layout left   - x).
+            layout   width:(layout width  + w).
+            layout  setTop:(layout top    - y).
+            layout  height:(layout height + y + level).
         ] ifFalse:[
-            y := maxExt y - y.
-            canvas origin:0.0@0.0 corner:1.0@(y+margin).
-            tabRaw origin:0.0@(y+margin) corner:1.0@1.0.
+            layout setLeft:(layout left       - level).
+            layout   width:(layout width  + y + level).
+            layout  setTop:(layout top    - x).
+            layout  height:(layout height + w).
+        ]
+    ].
+    ^ layout
+!
+
+makeToBaseLine:aLnNr
+    |layout1 layoutN topN top1 leftN left1
+     nr "{ Class:SmallInteger }"
+    |
+    nr := list findFirst:[:aTab| aTab lineNr == 1].
+    layout1 := (list at:nr) layout.
+
+    nr := list findFirst:[:aTab| aTab lineNr == aLnNr].
+    layoutN := (list at:nr) layout.
+
+    self isHorizontal ifTrue:[
+        top1 := layout1 top.
+        topN := layoutN top.
+
+        list do:[:el|
+            (nr := el lineNr) == 1 ifTrue:[
+                el layout setTop:topN. el lineNr:aLnNr
+            ] ifFalse:[
+                nr == aLnNr ifTrue:[
+                    el layout setTop:top1. el lineNr:1
+                ]
+            ]
         ]
     ] ifFalse:[
-        y > (maxExt y) ifTrue:[x := tabRaw preferredSizeXorY].
+        left1 := layout1 left.
+        leftN := layoutN left.
+
+        list do:[:el|
+            (nr := el lineNr) == 1 ifTrue:[
+                el layout setLeft:leftN. el lineNr:aLnNr
+            ] ifFalse:[
+                nr == aLnNr ifTrue:[
+                    el layout setLeft:left1. el lineNr:1
+                ]
+            ]
+        ]
+    ]
+
+!
+
+recomputeList
+    "recompute list
+    "
+    numberOfLines := 1.
+
+    list notEmpty ifTrue:[
+        self isHorizontal ifTrue:[
+            self recomputeListHorizontal
+        ] ifFalse:[
+            self recomputeListVertical
+        ]
+    ].
+    canvas notNil ifTrue:[
+        canvas layout:(self computeCanvasLayout)
+    ]
+!
+
+recomputeListHorizontal
+    "recompute list
+    "
+    |layout lastLyt checkDir
+     xLeft     "{ Class:SmallInteger }"
+     yTop      "{ Class:SmallInteger }"
+     tabWidth  "{ Class:SmallInteger }"
+     tabHeight "{ Class:SmallInteger }"
+     lineWidth "{ Class:SmallInteger }"
+     startX    "{ Class:SmallInteger }"
+     delta     "{ Class:SmallInteger }"
+     first     "{ Class:SmallInteger }"
+     last      "{ Class:SmallInteger }"
+    |
+    startX     := expandSelection x // 2.
+    lineWidth  := self width - startX.
+    tabHeight  := self maxTabHeight.
+    xLeft      := startX.
+    yTop       := expandSelection y.
+
+    checkDir := canvas isNil ifTrue:[#top] ifFalse:[#bottom].
+
+    direction == #bottom ifTrue:[
+        yTop := self height - tabHeight - yTop
+    ].
+
+    list do:[:aTab|
+        tabWidth := aTab preferredExtentX.
+
+        (xLeft + tabWidth > lineWidth and:[xLeft ~~ startX]) ifTrue:[
+            numberOfLines := numberOfLines + 1.
+            xLeft := startX.
+        ].
+        aTab lineNr:numberOfLines.
+        aTab layout:(Rectangle left:xLeft top:yTop width:tabWidth height:tabHeight).
+        xLeft := xLeft + tabWidth
+    ].
+
+    numberOfLines ~~ 1 ifTrue:[
+        last  := numberOfLines.
+        delta := direction == #bottom ifFalse:[tabHeight]
+                                       ifTrue:[tabHeight negated].
+
+        list reverseDo:[:aTab|
+            aTab lineNr ~~ last ifTrue:[
+                last := aTab lineNr.
+                yTop := yTop + delta
+            ].
+            aTab layout setTop:yTop
+        ]
+    ].
+    tabModus ifTrue:[
+        layout := (list at:1) layout.
+        delta  := direction == #top ifTrue:[self height - layout bottom]
+                                   ifFalse:[layout top negated].
+
+        list do:[:aTab| aTab layout setTop:(aTab layout top + delta)].
+    ].
+
+    "/ FIT LINES
+    (numberOfLines ~~ 1 or:[fitLastRow]) ifFalse:[
+        ^ self
+    ].
+
+    first := 1.
+
+    1 to:numberOfLines do:[:aLnNr|
+        last    := list findLast:[:t|t lineNr == aLnNr].
+        lastLyt := (list at:last) layout.
+
+        (delta := lineWidth - lastLyt right) ~~ 0 ifTrue:[
+            xLeft := startX.
+            delta := delta // (last - first + 1).
+
+            delta ~~ 0 ifTrue:[
+                list from:first to:last do:[:aTab|
+                    layout   := aTab layout.
+                    tabWidth := layout width + delta.
+                    layout setLeft:xLeft.
+                    layout width:tabWidth.
+                    xLeft := xLeft + tabWidth.
+                ]
+            ].
+            lastLyt width:(lineWidth - lastLyt left)
+        ].
+        first := last + 1.
+    ]
+
+!
+
+recomputeListVertical
+    "recompute list
+    "
+    |layout lastLyt
+     xTop      "{ Class:SmallInteger }"
+     yTop      "{ Class:SmallInteger }"
+     tabWidth  "{ Class:SmallInteger }"
+     tabHeight "{ Class:SmallInteger }"
+     lineHeight "{ Class:SmallInteger }"
+     startY    "{ Class:SmallInteger }"
+     delta     "{ Class:SmallInteger }"
+     first     "{ Class:SmallInteger }"
+     last      "{ Class:SmallInteger }"
+    |
+    startY     := expandSelection x // 2.
+    lineHeight := self height - startY.
+    tabHeight  := self maxTabHeight.
+    yTop       := startY.
+    xTop       := expandSelection y.
+
+    direction == #right ifTrue:[
+        xTop  := self width - tabHeight - xTop
+    ].
+
+    list do:[:aTab|
+        tabWidth := aTab preferredExtentX.
+
+        (yTop + tabWidth > lineHeight and:[yTop ~~ startY])ifTrue:[
+            numberOfLines := numberOfLines + 1.
+            yTop := startY.
+        ].
+        aTab lineNr:numberOfLines.
+        aTab layout:(Rectangle left:xTop top:yTop width:tabHeight height:tabWidth).
+        yTop := yTop + tabWidth
+    ].
+    numberOfLines ~~ 1 ifTrue:[
+        last  := numberOfLines.
+        delta := direction == #left ifTrue:[tabHeight] ifFalse:[tabHeight negated].
+
+        list reverseDo:[:aTab|
+            aTab lineNr ~~ last ifTrue:[
+                last := aTab lineNr.
+                xTop := xTop + delta
+            ].
+            aTab layout setLeft:xTop
+        ]
+    ].
+    tabModus ifTrue:[
+        layout := (list at:1) layout.
+        delta  := direction == #left ifTrue:[self width - layout right]
+                                    ifFalse:[layout left negated].
+
+        list do:[:aTab| aTab layout setLeft:(aTab layout left + delta)].
+    ].
+
+    "/ FIT LINES
+    (numberOfLines ~~ 1 or:[fitLastRow]) ifFalse:[
+        ^ self
+    ].
+
+    first := 1.
+
+    1 to:numberOfLines do:[:aLnNr|
+        last    := list findLast:[:t|t lineNr == aLnNr].
+        lastLyt := (list at:last) layout.
+
+        (delta := lineHeight - lastLyt bottom) ~~ 0 ifTrue:[
+            yTop  := startY.
+            delta := delta // (last - first + 1).
+
+            delta ~~ 0 ifTrue:[
+                list from:first to:last do:[:aTab|
+                    layout   := aTab layout.
+                    tabWidth := layout height + delta.
+                    layout setTop:yTop.
+                    layout height:tabWidth.
+                    yTop := yTop + tabWidth.
+                ]
+            ].
+            lastLyt height:(lineHeight - lastLyt top)
+        ].
+        first := last + 1.
+    ]
+! !
+
+!NoteBookView methodsFor:'obsolete'!
+
+labels
+    "return the list of labels
+    "
+    ^ self list
+!
+
+labels:aListOfLabels
+    "set the list of labels
+    "
+    ^ self list:aListOfLabels
+!
+
+labelsHolder
+    "get the model, which keeps the list of Tabs or Labels
+    "
+    ^ self listHolder
+!
+
+labelsHolder:aValueHolder
+    "set the model, which keeps the list of Tabs or Labels
+    "
+    self listHolder:aValueHolder. 
+!
+
+moveSelectedRow
+     ^ true
+!
+
+moveSelectedRow:something
+!
+
+oneTabPerLine
+    ^ false
+!
+
+oneTabPerLine:something
+!
+
+tabWidget
+    ^ nil
+!
+
+tabWidget:something
+! !
+
+!NoteBookView methodsFor:'private'!
+
+findTabStartingWithKey:aKey startingAt:anIndex
+    "get index of tab starting its printableLabel with a key or 0
+    "
+    |upper lower string char|
+
+    (aKey isCharacter and:[anIndex <= list size]) ifFalse:[ ^ 0 ].
+
+    upper := aKey asUppercase.
+    lower := aKey asLowercase.
+
+  ^ list findFirst:[:aTab|
+        (     (string := aTab string) size ~~ 0
+         and:[((char  := string first) == lower or:[char == upper])]
+        )
+    ] startingAt:anIndex
+! !
+
+!NoteBookView methodsFor:'queries'!
+
+isEnabled
+    "returns enabled state
+    "
+    ^ enabled
+!
+
+isFirstTabInLine:aTab
+    |idx tab|
+
+    idx := list identityIndexOf:aTab.
+    tab := list at:(idx - 1) ifAbsent:nil.
+  ^ (tab isNil or:[tab lineNr ~~ aTab lineNr])
+!
+
+isHorizontal
+    "returns true in case of direction is #top or #bottom
+    "
+    ^ (direction == #top or:[direction == #bottom])
+
+!
+
+isLastTabInLine:aTab
+    |index tab|
+
+    index := list identityIndexOf:aTab.
+    tab := list at:(index + 1) ifAbsent:nil.
+  ^ (tab isNil or:[tab lineNr ~~ aTab lineNr])
+! !
+
+!NoteBookView methodsFor:'selection'!
 
-        tabRaw direction == #left ifTrue:[
-            tabRaw origin:0.0@0.0 corner:(x+margin)@1.0.
-            canvas origin:(x+margin)@0.0 corner:1.0@1.0.
-        ] ifFalse:[
-            x := maxExt x - x.
-            canvas origin:0.0@0.0 corner:(x+margin)@1.0.
-            tabRaw origin:(x+margin)@0.0 corner:1.0@1.0.
+isSelectable:anIndex
+    "returns true if tab at an index is selectable
+    "
+    (anIndex notNil and:[anIndex between:1 and:list size]) ifTrue:[
+        (list at:anIndex) isEnabled ifTrue:[
+            ^ selectConditionBlock isNil ifTrue:[true]
+                                        ifFalse:[selectConditionBlock value:anIndex]
+        ]
+    ].
+    ^ false
+!
+
+selectedTab
+    "returns the selected tab ot nil
+    "
+    ^ selection notNil ifTrue:[list at:selection] ifFalse:[nil]
+!
+
+selection
+    "return the selection or nil
+    "
+    selection isNil ifTrue:[
+        ^ useIndex ifTrue:[0] ifFalse:[nil]
+    ].
+    ^ useIndex ifTrue:[selection] ifFalse:[(list at:selection) label]
+!
+
+selection:anIndexOrNil
+    "change the selection to index or nil. The model and/or actionBlock is notified
+    "
+    |oldSel|
+
+    oldSel := selection.
+    self setSelection:anIndexOrNil.
+    oldSel ~~ selection ifTrue:[self selectionChanged].
+!
+
+selectionChanged
+    "selection has changed; raise notification
+    "
+    |sel|
+
+    sel := self selection.
+
+    model  notNil ifTrue:[model  value:sel].
+    action notNil ifTrue:[action value:sel]
+
+!
+
+setSelection:anIndexOrNil
+    "change the selection to index or nil. No notifications are raised
+    "
+    |newSel lnNr|
+
+    newSel := self listIndexOf:anIndexOrNil.
+
+    (newSel notNil and:[(self isSelectable:newSel) not]) ifTrue:[
+        newSel := nil
+    ].
+    selection == newSel ifTrue:[^ self].
+
+    (shown and:[numberOfLines notNil]) ifFalse:[
+        selection := newSel.
+        self invalidate
+    ] ifTrue:[
+        selection notNil ifTrue:[self invalidateTab:(list at:selection)].
+        selection := newSel.
+        selection notNil ifTrue:[self invalidateTab:(list at:selection)].
+    ]
+! !
+
+!NoteBookView::Tab class methodsFor:'instance creation'!
+
+label:aLabel on:aGC
+    ^ self basicNew label:aLabel on:aGC
+
+
+! !
+
+!NoteBookView::Tab methodsFor:'accessing'!
+
+label
+    "returns my original label
+    "
+    ^ label
+
+
+!
+
+label:aLabel on:aGC
+    "initialize attributes
+    "
+    label := aLabel.
+    model := (aLabel isKindOf:TabItem) ifTrue:[aLabel] ifFalse:[nil].
+
+    printableLabel := model notNil ifTrue:[model rawLabel]
+                                  ifFalse:[aLabel].
+
+    printableLabel notNil ifTrue:[
+        printableLabel isImageOrForm ifTrue:[
+            printableLabel := printableLabel onDevice:(aGC device)
         ]
+    ] ifFalse:[
+        printableLabel := ''
+    ].
+    extent := (printableLabel widthOn:aGC) @ (printableLabel heightOn:aGC).
+
+!
+
+lineNr
+    "get the line number
+    "
+    ^ lineNr
+
+!
+
+lineNr:aLineNr
+    "set the line number
+    "
+    lineNr := aLineNr
+
+!
+
+printableLabel
+    "get my printable label
+    "
+    ^ printableLabel
+
+!
+
+string
+    "access the printable string used for steping through a list
+     searching for an entry starting with a character.
+    "
+    ^ printableLabel perform:#string ifNotUnderstood:nil
+
+! !
+
+!NoteBookView::Tab methodsFor:'accessing dimensions'!
+
+extent
+    "returns the extent of the label
+    "
+    ^ extent
+
+
+!
+
+layout
+    "get the tab's layout
+    "
+    ^ layout
+
+
+!
+
+layout:aLayout
+    "set the tab's layout
+    "
+    layout := aLayout
+
+
+!
+
+preferredExtentX
+    "returns my preferred extent x
+    "
+    ^ 4 + extent x
+
+
+!
+
+preferredExtentY
+    "returns my preferred extent y
+    "
+    ^ 4 + extent y
+
+
+! !
+
+!NoteBookView::Tab methodsFor:'accessing mvc'!
+
+addDependent:aGC
+    "make the noteBook be a dependent of the tab model
+    "
+    model notNil ifTrue:[model addDependent:aGC]
+
+
+!
+
+removeDependent:aGC
+    "make the noteBook be independent of the tab model
+    "
+    model notNil ifTrue:[model removeDependent:aGC]
+
+
+! !
+
+!NoteBookView::Tab methodsFor:'drawing'!
+
+drawAtBottomOn:aGC selected:isSelected
+    "redraw tab at bottom of view
+    "
+    |yT "{ Class:SmallInteger }"
+     xL "{ Class:SmallInteger }"
+     xR "{ Class:SmallInteger }"
+     yB "{ Class:SmallInteger }"
+    |
+    xL := layout left.
+    yT := layout top.
+    xR := layout right  - 1.
+    yB := layout bottom - 1.
+
+    aGC paint:(aGC halfLightColor).
+    aGC displayLineFromX:xL+1 y:yB   toX:xL+1 y:yT.
+
+    aGC paint:(aGC lightColor).
+    aGC displayLineFromX:xL   y:yB-1 toX:xL   y:yT.
+
+    aGC paint:(aGC shadowColor).
+    aGC displayLineFromX:xL+1 y:yB   toX:xR-2 y:yB.
+    aGC displayLineFromX:xR   y:yT   toX:xR   y:yB-2.
+    aGC displayPointX:xR-1    y:yB-1.
+
+    aGC paint:(aGC halfShadowColor).
+    aGC displayLineFromX:xR-1 y:yT-1 toX:xR-1 y:yB-2.
+    aGC displayLineFromX:xL+2 y:yB-1 toX:xR-2 y:yB-1.
+    aGC displayPointX:xR-2    y:yB-2.
+
+    isSelected ifTrue:[
+        (aGC  isLastTabInLine:self) ifFalse:[aGC displayPointX:xR y:yT].
+        (aGC isFirstTabInLine:self) ifFalse:[aGC displayPointX:xL y:yT].
+    ]
+
+
+
+
+
+
+
+!
+
+drawAtLeftOn:aGC selected:isSelected
+    "redraw tab at left of view
+    "
+    |yT "{ Class:SmallInteger }"
+     xL "{ Class:SmallInteger }"
+     xR "{ Class:SmallInteger }"
+     yB "{ Class:SmallInteger }"
+    |
+    xL := layout left.
+    yT := layout top.
+    xR := layout right  - 1.
+    yB := layout bottom - 1.
+
+    aGC paint:(aGC shadowColor).
+    aGC displayLineFromX:xR y:yB   toX:xL+2 y:yB.
+
+    aGC paint:(aGC halfShadowColor).
+    aGC displayLineFromX:xR y:yB-1 toX:xL+1 y:yB-1.
+
+    aGC paint:(aGC lightColor).
+    aGC displayLineFromX:xL+2 y:yT   toX:xR   y:yT.
+
+    aGC paint:(aGC halfLightColor).
+    aGC displayLineFromX:xL   y:yT+2 toX:xL   y:yB-3.
+    aGC displayLineFromX:xL+1 y:yT+2 toX:xL+1 y:yB-2.
+    aGC displayLineFromX:xL+1 y:yT+1 toX:xR   y:yT+1.
+
+
+    (aGC isLastTabInLine:self)  ifFalse:[aGC displayPointX:xR y:yB].
+    (aGC isFirstTabInLine:self) ifFalse:[aGC displayPointX:xR y:yT].
+
+
+
+!
+
+drawAtRightOn:aGC selected:isSelected
+    "redraw tab at right of view
+    "
+    |yT "{ Class:SmallInteger }"
+     xL "{ Class:SmallInteger }"
+     xR "{ Class:SmallInteger }"
+     yB "{ Class:SmallInteger }"
+    |
+    xL := layout left.
+    yT := layout top.
+    xR := layout right - 1.
+    yB := layout bottom - 1.
+
+    aGC paint:(aGC lightColor).
+    aGC displayLineFromX:xL   y:yT   toX:xR-2 y:yT.
+
+    aGC paint:(aGC halfLightColor).
+    aGC displayLineFromX:xL   y:yT+1 toX:xR-2   y:yT+1.
+
+    aGC paint:(aGC shadowColor).
+    aGC displayLineFromX:xR-2   y:yB   toX:xL y:yB.
+    aGC displayLineFromX:xR   y:yT+2 toX:xR y:yB-2.
+    aGC displayPointX:xR-1 y:yB-1.
+
+    aGC paint:(aGC halfShadowColor).
+    aGC displayLineFromX:xR-2 y:yB-1 toX:xL y:yB-1.
+    aGC displayLineFromX:xR-1 y:yT+1 toX:xR-1 y:yB-2.
+
+    isSelected ifFalse:[^ self].
+
+    (aGC isLastTabInLine:self)  ifFalse:[aGC displayPointX:xL y:yB].
+
+    (aGC isFirstTabInLine:self) ifFalse:[
+        aGC displayPointX:xL y:yT+1.
+        aGC displayPointX:xL y:yT
     ].
 
 
 
 !
 
-update:something with:aParameter from:changedObject
-    "tabs changed
+drawAtTopOn:aGC selected:isSelected
+    "redraw tab at top of view
     "
-    changedObject == tabRaw ifTrue:[
-        something == #preferredExtent ifFalse:[
-            something == #direction ifFalse:[
-                ^ self
-            ].
-            tabRaw isHorizontalDirection ifTrue:[
-                tabRaw origin:0.0@0.0 corner:1.0@0.0
-            ] ifFalse:[
-                tabRaw origin:0.0@0.0 corner:0.0@1.0
+    |yT "{ Class:SmallInteger }"
+     xL "{ Class:SmallInteger }"
+     xR "{ Class:SmallInteger }"
+     yB "{ Class:SmallInteger }"
+    |
+    xL := layout left.
+    yT := layout top.
+    xR := layout right  - 1.
+    yB := layout bottom - 1.
+
+    aGC paint:(aGC shadowColor).
+    aGC displayLineFromX:xR   y:yB toX:xR   y:yT+2.
+
+    aGC paint:(aGC halfShadowColor).
+    aGC displayLineFromX:xR-1 y:yB toX:xR-1 y:yT+1.
+
+    aGC paint:(aGC lightColor).
+    aGC displayLineFromX:xL+2 y:yT toX:xR-2 y:yT.
+    aGC displayLineFromX:xL   y:yB toX:xL   y:yT+2.
+
+    aGC paint:(aGC halfLightColor).
+    aGC displayLineFromX:xL+2 y:yT+1 toX:xR-2 y:yT+1.
+    aGC displayLineFromX:xL+1 y:yB   toX:xL+1 y:yT+1.
+
+    isSelected ifFalse:[^ self].
+    (aGC isLastTabInLine:self)  ifFalse:[aGC displayPointX:xR y:yB].
+    (aGC isFirstTabInLine:self) ifFalse:[aGC displayPointX:xL y:yB].
+
+
+
+
+!
+
+redrawAt:aDirection selected:isSelected on:aGC
+    "redraw tab
+    "
+    |dispObj fgColor
+     y  "{ Class:SmallInteger }"
+     x  "{ Class:SmallInteger }"
+     dI "{ Class:SmallInteger }"
+    |
+
+    isSelected ifTrue:[
+        aGC paint:(aGC backgroundColor).
+        layout displayFilledOn:aGC.
+    ].
+             aDirection == #top    ifTrue:[self drawAtTopOn:aGC    selected:isSelected]
+    ifFalse:[aDirection == #bottom ifTrue:[self drawAtBottomOn:aGC selected:isSelected]
+    ifFalse:[aDirection == #right  ifTrue:[self drawAtRightOn:aGC  selected:isSelected]
+    ifFalse:[aDirection == #left   ifTrue:[self drawAtLeftOn:aGC   selected:isSelected]
+    ifFalse:[^ self]]]].
+
+    "/ REDRAW LABEL
+    (aGC isEnabled and:[self isEnabled]) ifTrue:[
+        dispObj := printableLabel.
+        fgColor := aGC foregroundColor.
+
+        model notNil ifTrue:[
+           fgColor := model foregroundColor ? fgColor
+        ]
+    ] ifFalse:[
+        fgColor := aGC lightColor.
+
+        (dispObj := disabledLabel) isNil ifTrue:[
+            (dispObj := printableLabel) isImageOrForm ifTrue:[
+                disabledLabel := printableLabel lightened onDevice:(aGC device)
             ]
+        ]
+    ].
+    aGC paint:fgColor.
+    dI := 4.
+    (aDirection == #top or:[aDirection == #bottom]) ifTrue:[
+        x := (layout left) + (layout width - extent x // 2).
+
+        y := aDirection == #top ifTrue:[layout top + dI]
+                               ifFalse:[layout bottom - extent y - dI].
+
+        dispObj isImageOrForm ifFalse:[
+            y := y + aGC font ascent
         ].
-        self recomputeSizes
-    ]
-! !
+    ] ifFalse:[
+        y := (layout top) + (layout height - extent x // 2).
+
+        x := aDirection == #left ifTrue:[layout left + dI]
+                                ifFalse:[layout right - extent y - dI].
 
-!NoteBookView methodsFor:'event handling'!
+        dispObj isImageOrForm ifFalse:[
+            x := x + aGC font descent.
+            "/ workaround for a bug in display-with-angle,
+            "/ iff displayed string is a labelAndIcon.
+            "/ (In this case, display is always opaque, and the current
+            "/  backgroundPaint color is used to fill the underlying rectangle)
+            "/
+            aGC backgroundPaint:(aGC paint:fgColor).
+          ^ aGC displayString:dispObj x:x y:y angle:90.
+        ]
+    ].
+    dispObj displayOn:aGC x:x y:y
 
-doesNotUnderstand:aMessage
-    (tabRaw respondsTo:(aMessage selector)) ifTrue:[
-        ^ aMessage sendTo:tabRaw
-    ].
-    ^ super doesNotUnderstand:aMessage
+
+
+
+
+""
 
 
 ! !
 
-!NoteBookView methodsFor:'initialize / release'!
+!NoteBookView::Tab methodsFor:'testing'!
 
-destroy
-    "remove dependancies
+containsPointX:x y:y
+    "return true, if the point defined by x@y is contained in the tab.
     "
-    canvasHolder notNil ifTrue:[
-        canvasHolder removeDependent:self. 
-    ].
-    tabRaw removeDependent:self.
-    self delegate:self.
-    super destroy
+    ^ layout notNil ifTrue:[layout containsPointX:x y:y]
+                   ifFalse:[false].
+
+
 !
 
-initialize
-    "initialize tabs and canvas
+intersects:aRectangle
+    "return true, if the intersection between the argument, aRectangle
+     and the tab is not empty
     "
-    super initialize.
+    ^ layout notNil ifTrue:[layout intersects:aRectangle]
+                   ifFalse:[false].
 
-    tabRaw := TabView origin:0.0@0.0 corner:1.0@0.0 in:self.
 
- "/ class for canvas could be set by a subclass
-    canvas isNil ifTrue:[
-        canvas := View
-    ].
-    canvas := canvas origin:0.0@0.0 corner:1.0@1.0 in:self.
+!
 
-    tabRaw addDependent:self.
-    self delegate:(KeyboardForwarder toView:tabRaw
-                condition:nil
-                filter:[:key | key size > 6 and:[key startsWith:#Cursor]]).
+isEnabled
+    "returne true if no model exists or the model is enabled
+    "
+    ^ (model isNil or:[model isEnabled])
 
-! !
 
-!NoteBookView methodsFor:'selection'!
-
-setSelection:something
-    tabRaw setSelection:something
 ! !
 
 !NoteBookView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/NoteBookView.st,v 1.12 1999-05-21 18:03:42 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/NoteBookView.st,v 1.13 1999-06-07 12:44:58 cg Exp $'
+
 ! !
--- a/TabView.st	Fri May 28 20:07:15 1999 +0200
+++ b/TabView.st	Mon Jun 07 14:45:09 1999 +0200
@@ -11,11 +11,8 @@
 "
 
 
-View subclass:#TabView
-	instanceVariableNames:'list listHolder selection enabled action tabStyle useIndex
-		maxRawNr direction fitLastRow moveSelectedRow
-		selectConditionBlock oldExtent oneTabPerLine fontAscent
-		fontDescent'
+NoteBookView subclass:#TabView
+	instanceVariableNames:''
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Views-Interactors'
@@ -222,1149 +219,20 @@
 "
 ! !
 
-!TabView class methodsFor:'defaults'!
-
-defaultTabWidget
-    ^ #Window
-! !
-
-!TabView methodsFor:'accessing'!
-
-action:oneArgBlock
-    "set the action block to be performed on select; the argument to
-     the block is the selected index or nil in case of no selection.
-    "
-    action := oneArgBlock.
-
-!
-
-backgroundColor
-    ^ viewBackground
-!
-
-fontAscent
-    fontAscent isNil ifTrue:[
-	fontAscent := self font ascent
-    ].
-    ^ fontAscent
-!
-
-fontDescent
-    fontDescent isNil ifTrue:[
-	fontDescent := self font descent
-    ].
-    ^ fontDescent
-!
-
-list
-    "return the list
-    "
-    ^ list
-!
-
-list:aList
-    "set the list
-    "
-    |hasChanged newSel model|
-
-    aList size == list size ifTrue:[
-        list notNil ifTrue:[
-            list keysAndValuesDo:[:aKey :aTab|
-                (aTab label) = (aList at:aKey) ifFalse:[
-                    hasChanged := true
-                ]
-            ]
-        ].
-        hasChanged == true ifFalse:[^ self ].
-    ].
-
-    self removeListDependencies.
-
-    aList size ~~ 0 ifTrue:[
-        (newSel := self tabAt:selection) notNil ifTrue:[
-            newSel := newSel printableLabel
-        ].
-        list := (tabStyle at:#widget) labels:aList for:self.
-
-        list do:[:aTab|
-            (model := aTab model) notNil ifTrue:[
-                model addDependent:self
-            ]
-        ].
-
-        newSel notNil ifTrue:[
-            (newSel := list findFirst:[:aTab| aTab printableLabel = newSel]) == 0 ifTrue:[
-                newSel := nil
-            ]
-        ].
-    ] ifFalse:[
-        list := nil.
-    ].
-    selection := newSel.
-
-    self shown ifTrue:[
-        self recomputeList.
-        self invalidateRepairNow:true
-    ].
-    self changed:#preferredExtent
-!
-
-oneTabPerLine
-    ^ oneTabPerLine
-!
-
-oneTabPerLine:aBool
-    oneTabPerLine := aBool.
-!
-
-useIndex
-    "use index instead of name
-    "
-    ^ useIndex
-
-
-!
-
-useIndex:aBoolean
-    "set/clear the useIndex flag. If set, both actionBlock and change-messages
-     are passed the index(indices) of the selection as argument. 
-     If clear, the value(s) (i.e. the selected string) is passed.
-     Default is false."
-
-    useIndex := aBoolean
-
-
-!
-
-viewBackground:aColor
-    "update colors
-    "
-    super viewBackground:aColor.
-    TabWidget computeColorsOn:self style:tabStyle.
-    shown ifTrue:[
-	self invalidate.
-    ]
-
-    "Modified: / 6.6.1998 / 19:55:59 / cg"
-! !
-
-!TabView methodsFor:'accessing behavior'!
-
-enabled
-    "returns true if tabs are enabled
-    "
-    ^ enabled
-!
-
-enabled:aState
-    "set enabled state
-    "
-    |state|
-
-    state := aState ? true.
-
-    enabled ~~ state ifTrue:[
-	enabled := state.
-	self redrawLabels.
-    ]
-!
-
-selectConditionBlock
-    "get the conditionBlock; this block is evaluated before a selection
-     change is performed; the change will not be done, if the evaluation
-     returns false. The argument to the block is the selection index
-    "
-    ^ selectConditionBlock
-!
-
-selectConditionBlock:aOneArgBlock
-    "get the conditionBlock; this block is evaluated before a selection
-     change is performed; the change will not be done, if the evaluation
-     returns false. The argument to the block is the selection index
-    "
-    selectConditionBlock := aOneArgBlock
-! !
-
-!TabView methodsFor:'accessing channels/holders'!
-
-listHolder
-    "returns the list holder
-    "
-    ^ listHolder
-!
-
-listHolder:aValueHolder
-    "change the list holder
-    "
-    listHolder notNil ifTrue:[
-	listHolder removeDependent:self. 
-    ].
-
-    listHolder := aValueHolder.
-    listHolder notNil ifTrue:[
-	listHolder addDependent:self.
-	self list:listHolder value.
-	self selection:model value.
-    ].
-!
-
-model:aValueHolder
-    super model:aValueHolder.
-
-    model notNil ifTrue:[
-	self selection:(model value)
-    ]
-! !
-
-!TabView methodsFor:'accessing dimension'!
-
-preferredExtent
-    "compute max extent x/y based on one line
-    "
-    |x y ovl size maxY|
-
-    (size := list size) == 0 ifTrue:[^ 0 @ 0 ].
-
-    maxY := tabStyle at:#maxY.
-    y    := maxY + self viewSpacing.
-
-    oneTabPerLine ifTrue:[
-	y := y + ((size - 1) * maxY).
-
-	(self isHorizontalDirection) ifTrue:[x := super extent x]
-				    ifFalse:[x := super extent y]
-    ] ifFalse:[
-	x := ovl := tabStyle at:#rightCovered.
-	list do:[:aTab|x := x - ovl + aTab preferredExtentX]
-    ].
-
-    (self isHorizontalDirection) ifTrue:[^ x @ y]
-				ifFalse:[^ y @ x]
-!
-
-preferredSizeXorY
-    "returns preferred size dependant on the current view layout and
-     the direction of the tabs
-    "
-    list size == 0 ifFalse:[
-	maxRawNr isNil ifTrue:[self recomputeList].
-
-	oneTabPerLine ifTrue:[
-	    self isHorizontalDirection ifTrue:[^ super extent y]
-				      ifFalse:[^ super extent x]
-	].
-	^ ((maxRawNr * (tabStyle at:#maxY)) + self viewSpacing).
-    ].
-    ^ 0
-!
-
-viewSpacing
-    "returns my view spacing
-    "
-    ^ ((tabStyle at:#expandSelection) y) + (self class viewSpacing)
-! !
-
-!TabView methodsFor:'accessing style'!
-
-direction
-    "returns the direction of tabs as symbol. On default the value is
-     set to #top. Valid symbols are:
-	#top       arrange tabs to be on top of a view
-	#bottom    arrange tabs to be on bottom of a view
-	#left      arrange tabs to be on left of a view
-	#right     arrange tabs to be on right of a view
-    "
-    ^ direction
-
-!
-
-direction:aDirection
-    "change the direction of tabs. On default the value is set to #top.
-     Valid symbols are:
-	#top       arrange tabs to be on top of a view
-	#bottom    arrange tabs to be on bottom of a view
-	#left      arrange tabs to be on left of a view
-	#right     arrange tabs to be on right of a view
-    "
-    direction ~~ aDirection ifTrue:[
-	direction := aDirection.
-	self changed:#direction
-    ].
-!
-
-fitLastRow
-    "in case of true, the last row is expanded to the view  size like all
-     other raws. In case of false all the tabs in the last raw keep their
-     preferred extent (x or y) dependant on the direction.
-    "
-    ^ fitLastRow
-!
-
-fitLastRow:aBool
-    "in case of true, the last row is expanded to the view  size like all
-     other raws. In case of false all the tabs in the last raw keep their
-     preferred extent (x or y) dependant on the direction.
-    "
-    fitLastRow := aBool
-!
-
-font:aFont
-    (aFont ~= font) ifTrue:[
-	super font:aFont.
-	fontAscent := fontDescent := nil
-    ]
-
-!
-
-moveSelectedRow
-    "in case of true, the raw assigned to the tab will be moved
-     to the first line (to the view). Otherwise the position of
-     the view will be kept.
-    "
-    ^ moveSelectedRow
-!
-
-moveSelectedRow:aBool
-    "in case of true, the raw assigned to the tab will be moved
-     to the first line (to the view). Otherwise the position of
-     the view will be kept.
-    "
-    moveSelectedRow := aBool
-!
-
-style
-    "returns the style sheet derived from the current widget class
-    "
-    ^ tabStyle
-!
-
-styleAt:anIdentifier
-    "returns a specific entry into the widget description. For more information
-     see the specific widget class ( TabWidget ... ).
-    "
-    ^ tabStyle at:anIdentifier
-!
-
-styleAt:anIdentifier put:something
-    "change a specific entry from the widget description. For more information
-     see the specific widget class ( TabWidget ... ).
-    "
-    tabStyle at:anIdentifier put:something.
-!
-
-tabWidget
-    "returns the current widget class as symbol
-    "
-    |widget|
-
-    widget := tabStyle at:#widget.
-    widget := widget nameWithoutPrefix asSymbol.
-  ^ widget
-!
-
-tabWidget:aWidget
-    "change the current widget class. An existing list will be
-     recomputed and redrawn
-    "
-    |widget labels|
-
-    (self tabWidget) ~~ aWidget ifTrue:[
-	widget := TabWidget widgetClass:aWidget.
-
-	widget notNil ifTrue:[
-	    tabStyle := widget tabStyleOn:self.
-
-	    list notNil ifTrue:[
-		labels := list collect:[:aTab| aTab label].
-		list   := widget labels:labels for:self.
-
-		self shown ifTrue:[
-		    self recomputeList.
-		    self invalidate.
-		]
-	    ]
-	]
-    ]
-
-    "Modified: / 6.6.1998 / 19:56:26 / cg"
-! !
-
-!TabView methodsFor:'accessing tabs'!
-
-tabAt:anIndex
-    "get tab at an index or nil
-    "
-    ^ anIndex notNil ifTrue:[list at:anIndex ifAbsent:nil] ifFalse:[nil]
-! !
-
-!TabView methodsFor:'change & update'!
-
-update:something with:aParameter from:changedObject
-    "one of my models changed its value
-    "
-    |idx tab|
-
-    changedObject == model         ifTrue:[^ self selection:model value].
-    changedObject == listHolder    ifTrue:[^ self list:(listHolder value)].
-    changedObject == enableChannel ifTrue:[^ self enabled:enableChannel value].
-
-    (    list isNil
-     or:[(idx := list findFirst:[:aTab| aTab model == changedObject]) == 0]
-    ) ifTrue:[
-        ^ self
-    ].
-
-    self shown ifTrue:[
-        tab := list at:idx.
-
-        something == #foregroundColor ifTrue:[
-            ^ self redrawLabelOfTab:tab
-        ].
-        
-        something == #enabled ifTrue:[
-            idx == selection ifTrue:[
-                ^ self selection:nil
-            ].
-            ^ self redrawLabelOfTab:tab
-        ].
-        tab labelChanged.
-        self recomputeList.
-        self invalidate.
-        self changed:#preferredExtent
-    ]
-
-    "Modified: / 30.3.1999 / 14:28:43 / stefan"
-    "Modified: / 28.4.1999 / 19:54:20 / cg"
-! !
-
-!TabView methodsFor:'drawing'!
-
-paintColor:aColorSymbol
-    "set the paint color derived from the symbol used as key into the current
-     style sheet to access the color
-    "
-    self paint:(tabStyle at:aColorSymbol)
-!
-
-redraw
-    "redraw"
-
-    self redrawX:0 y:0 width:width height:height.
-
-!
-
-redrawLabelOfTab:aTab
-    "redraw only the label of the tab
-    "
-    shown ifTrue:[
-	aTab == (self tabAt:selection) ifTrue:[
-	    self selectedTab:aTab redrawBlock:[aTab redrawLabel]
-	] ifFalse:[
-	    aTab redrawLabel
-	]
-    ].
-!
-
-redrawLabels
-    "redraw all the labels
-    "
-    |selectedTab|
-
-    (shown and:[list size ~~ 0]) ifTrue:[
-	selectedTab := self tabAt:selection.
-
-	list reverseDo:[:aTab|
-	    aTab ~~ selectedTab ifTrue:[
-		aTab redrawLabel
-	    ] ifFalse:[
-		self selectedTab:aTab redrawBlock:[aTab redrawLabel]
-	    ]
-	]
-    ].
-!
-
-redrawRawAt:aRawNr
-    "redraw raw at a number; all contained tabs are drawn unselected
-    "
-    list reverseDo:[:aTab|aTab lineNr == aRawNr ifTrue:[aTab redraw:false]].
-!
-
-redrawRawAt:aRawNr in:aRectangle
-    "redraw raw at a number; all contained tabs are drawn unselected
-    "
-    list reverseDo:[:aTab|
-	aTab lineNr == aRawNr ifTrue:[
-	    (aTab intersects:aRectangle) ifTrue:[
-		aTab redraw:false
-	    ]
-	]
-    ].
-!
-
-redrawSelection
-    "redraw current selection
-    "
-    |tab idx|
-
-    (selection notNil and:[self shown and:[list size ~~ 0]]) ifTrue:[
-	tab := list at:selection.
-	idx := tab lineNr.
-	self selectedTab:tab redrawBlock:[tab redraw:true].
-	[(idx := idx - 1) ~~ 0] whileTrue:[self redrawRawAt:idx].
-    ].
-!
-
-redrawX:x y:y width:w height:h
-    "a region must be redrawn
-    "
-    |rectangle oldSelect prevClipArea|
-
-    self shown ifFalse:[
-        ^ self
-    ].
-
-    self paint:(self viewBackground).
-    self clearRectangleX:x y:y width:w height:h.
-
-    list size == 0 ifTrue:[^ self].
-
-    prevClipArea := clipRect.
-    clipRect     := nil.
-    device setClipX:x y:y width:w height:h in:drawableId gc:gcId.
-    rectangle := Rectangle left:x top:y width:w height:h.
-
-    maxRawNr isNil ifTrue:[
-        self recomputeList.
-    ].
-    maxRawNr to:1 by:-1 do:[:i| self redrawRawAt:i in:rectangle].
-
-    selection notNil ifTrue:[
-        oldSelect := selection.
-        selection := nil.
-        self setSelection:oldSelect.
-    ].
-
-    prevClipArea isNil ifTrue:[device noClipIn:drawableId  gc:gcId]
-                      ifFalse:[self clippingRectangle:prevClipArea].
-
-    "Modified: / 20.5.1999 / 19:16:51 / cg"
-!
-
-selectedTab:aTab redrawBlock:aRedrawBlock
-    "calculate extent of selection and evaluate the block which will
-     perform a redraw action
-    "
-    |tab oldAnc newAnc oldExt newExt expSel expDlt x y|
-
-    tab    := list at:selection.
-    oldAnc := tab anchor.
-    oldExt := tab extent.
-    expSel := tabStyle at:#expandSelection.
-    expDlt := expSel x.
-
-    (self isHorizontalDirection) ifTrue:[
-        newExt := oldExt + ( expDlt @ 0 ).
-        newAnc := oldAnc - ((expDlt//2) @ ((expSel y) negated)).
-
-        (x := newAnc x) < 0 ifTrue:[
-            newExt x:(newExt x + x).
-            newAnc x:0.
-            x := 0.
-        ].
-        (x + newExt x) > width ifTrue:[newExt x:(width - x)].
-    ] ifFalse:[
-        newExt := oldExt + ( 0 @ expDlt ).
-        newAnc := oldAnc - (((expSel y) negated) @ (expDlt//2)).
-
-        (y := newAnc y) < 0 ifTrue:[
-            newExt y:(newExt y + y).
-            newAnc y:0.
-            y := 0.
-        ].
-        (y + newExt y) > height ifTrue:[newExt y:(height - y)].
-    ].
-
-    tab anchor:newAnc extent:newExt.
-    aRedrawBlock value.
-    tab anchor:oldAnc extent:oldExt.
-
-    "Modified: / 4.5.1999 / 02:01:19 / cg"
-! !
-
-!TabView methodsFor:'event handling'!
-
-buttonPress:button x:x y:y
-    "a button is pressed; find tab under point and set the selection
-    "
-    |idx|
-
-    (     self isEnabled
-     and:[list notNil
-     and:[(idx := list findFirst:[:aTab|aTab containsPoint:(x@y)]) ~~ 0]]
-    ) ifTrue:[
-	self selection:idx
-    ].
-!
-
-keyPress:aKey x:x y:y
-    "selection might change; look for corresponding list entry
-    "
-    |size index n|
-
-    (self isEnabled and:[(size := list size) > 1]) ifFalse:[
-	^ self
-    ].
-
-    (aKey == #CursorRight or:[aKey == #CursorDown]) ifTrue:[
-	n := selection ? 0.
-
-	(size - 1) timesRepeat:[
-	    (n := n + 1) > size ifTrue:[n := 1].
-
-	    (self canSelectTabAtIndex:n) ifTrue:[
-		^ self selection:n
-	    ]
-	].
-	^ self
-    ].
-
-    (aKey == #CursorLeft or:[aKey == #CursorUp]) ifTrue:[
-	n := selection ? size.
-
-	(size - 1) timesRepeat:[
-	    (n := n - 1) < 1 ifTrue:[n := size].
-
-	    (self canSelectTabAtIndex:n) ifTrue:[
-		^ self selection:n
-	    ]
-	].
-	^ self
-    ].
-
-    aKey isCharacter ifTrue:[
-	(selection isNil or:[selection == size]) ifTrue:[index := 1]
-						ifFalse:[index := selection + 1].
-
-	n := index - 1.
-	[   
-	    n := self findTabStartingWithKey:aKey startingAt:n + 1.
-
-	    (n ~~ 0 and:[self canSelectTabAtIndex:n]) ifTrue:[
-		^ self selection:n
-	    ].
-	    n ~~ 0
-
-	] whileTrue.
-
-	index ~~ 1 ifTrue:[
-	    (n := self findTabStartingWithKey:aKey startingAt:1) ~~ 0 ifTrue:[
-		^ self selection:n
-	    ]
-	]
-    ].
-
-    super keyPress:aKey x:x y:y
-!
-
-sizeChanged:how
-    "size of view changed 
-    "
-    |extent delta dX dY|
-
-    super sizeChanged:how.
-
-    list size ~~ 0 ifTrue:[
-        shown ifTrue:[
-            self invalidate
-        ].
-
-        extent := super extent.
-        delta  := oldExtent - extent.
-
-        ((dX := delta x) > 1 or:[dX < -1 
-        or:[(dY := delta y) > 1 or:[dY < -1]]]) ifTrue:[
-            oldExtent := extent.
-            self recomputeList.
-            self changed:#preferredExtent.
-        ].
-    ].
-
-    "Modified: / 22.4.1998 / 14:20:31 / cg"
-! !
-
-!TabView methodsFor:'initialize / release'!
-
-destroy
-    listHolder notNil ifTrue:[
-	listHolder removeDependent:self. 
-    ].
-    enableChannel notNil ifTrue:[
-	enableChannel removeDependent:self. 
-    ].
-    self  removeListDependencies.
-    super destroy.
-!
+!TabView methodsFor:'initialization'!
 
 initStyle
     "setup style attributes
     "
 
     super initStyle.
-    self font:(MenuView defaultFont on:device).
-
-    "Created: / 5.9.1998 / 17:36:37 / cg"
-    "Modified: / 5.9.1998 / 17:37:38 / cg"
-!
-
-initialize
-    "setup default attributes
-    "
-    |widget|
-
-    super initialize.
-
-    self cursor:Cursor hand.
-
-    widget          := TabWidget widgetClass:(self class defaultTabWidget).
-    tabStyle        := widget tabStyleOn:self.
-
-    styleSheet name == #win95 ifTrue:[
-"/        tabStyle at:#unselectedColor put:(tabStyle at:#selectedColor).
-"/        tabStyle at:#expandSelection put:(4@2).
-"/        tabStyle at:#lightColorUnselected put:(Color white).
-"/        tabStyle at:#lightColorSelected   put:(Color white).
-        tabStyle at:#labelTopInset        put:0.
-        tabStyle at:#labelBottomInset     put:0.
-    ].
-
-    useIndex        := false.
-    oneTabPerLine   := false.
-    direction       := #top.
-    fitLastRow      := true.
-    moveSelectedRow := true.
-    enabled         := true.
-    oldExtent       := 0@0.
-
-    "Modified: / 4.5.1999 / 02:26:28 / cg"
-! !
-
-!TabView methodsFor:'layout'!
-
-changeRaw:aRawA with:aRawB
-    "exchange positions of two raws
-    "
-    |tabB tabA ancA ancB hrz|
-
-    tabA := list at:(list findFirst:[:aTab|aTab lineNr == aRawA]).
-    tabB := list at:(list findFirst:[:aTab|aTab lineNr == aRawB]).
-    hrz  := (self isHorizontalDirection).
-
-    hrz ifTrue:[
-	ancA := tabA anchor y.
-	ancB := tabB anchor y.
-    ] ifFalse:[   
-	ancA := tabA anchor x.
-	ancB := tabB anchor x.
-    ].
-
-    list do:[:aTab||ln|
-	(ln := aTab lineNr) == aRawB ifTrue:[
-	    aTab lineNr:aRawA.
-	    hrz ifTrue:[aTab anchor y:ancA]
-	       ifFalse:[aTab anchor x:ancA]
-	] ifFalse:[
-	    ln == aRawA ifTrue:[
-		aTab lineNr:aRawB.
-		hrz ifTrue:[aTab anchor y:ancB]
-		   ifFalse:[aTab anchor x:ancB]
-	    ]
-	]
-    ].
-
-    oneTabPerLine ifFalse:[
-	aRawB == maxRawNr ifTrue:[
-	    self fitRawAt:aRawA.
-	    self unfitLastRaw.
-	] ifFalse:[
-	    aRawA == maxRawNr ifTrue:[
-		self fitRawAt:aRawB.
-		self unfitLastRaw.
-	    ]
-	]
-    ]
-!
-
-fitRawAt:aRawNr
-    "fit raw to view's size
-    "
-    |last first tab ext org max size|
-
-    (aRawNr ~~ maxRawNr or:[fitLastRow]) ifFalse:[
-	^ self
-    ].
-
-    last  := list  findLast:[:aTab| aTab lineNr == aRawNr ].
-    first := list findFirst:[:aTab| aTab lineNr == aRawNr ].
-    tab   := list at:last.
-    size  := last - first + 1.
-    org   := 0.
-
-    (self isHorizontalDirection) ifTrue:[
-	max := super extent x.
-	ext := (max - ((tab anchor x) + (tab extent x))) // size.
-
-	ext > 1 ifTrue:[
-	    first to:last do:[:i|
-		tab := list at:i.
-		tab extent x:((tab extent x) + ext).
-		tab anchor x:((tab anchor x) + org).
-		org := org + ext.
-	    ].
-	    tab := list at:last.
-	].
-	tab extent x:(max - tab anchor x).
-    ] ifFalse:[
-	max := super extent y.
-	ext := (max - ((tab anchor y) + (tab extent y))) // size.
-
-	ext > 1 ifTrue:[
-	    first to:last do:[:i|
-		tab := list at:i.
-		tab extent y:((tab extent y) + ext).
-		tab anchor y:((tab anchor y) + org).
-		org := org + ext.
-	    ].
-	    tab := list at:last.
-	].
-	tab extent y:(max - tab anchor y).
-    ]
-!
-
-recomputeList
-    "recompute list
-    "
-    |maxY x y maxSz ovl|
-
-    list size == 0 ifTrue:[
-	^ self
-    ].
-
-    maxY     := tabStyle at:#maxY.
-    ovl      := tabStyle at:#rightCovered.
-    maxRawNr := 1.
-
-    (self isHorizontalDirection) ifTrue:[
-	maxSz := super extent x.
-	x     := 0.
-	y     := maxY.
-        
-	oneTabPerLine ifTrue:[
-	    list do:[:aTab|
-		aTab lineNr:maxRawNr.
-		aTab anchor:x@y extent:(maxSz @ maxY).
-		maxRawNr := maxRawNr + 1.
-		y := y + maxY.
-	    ].
-	    ^ self
-	].
-	list do:[:aTab||eX n|
-	    eX := aTab preferredExtentX.
-	    n  := eX + x - ovl.
-
-	    (n > maxSz and:[x ~~ 0]) ifTrue:[
-		maxRawNr := maxRawNr + 1.
-		x := 0.
-		y := y  + maxY.
-		n := eX - ovl.
-	    ].
-	    aTab lineNr:maxRawNr.
-	    aTab anchor:x@y extent:(eX @ maxY).
-	    x := n.
-	]
-    ] ifFalse:[
-	maxSz := super extent y.
-	x     := maxY.
-	y     := 0.
-
-	oneTabPerLine ifTrue:[
-	    list do:[:aTab|
-		aTab lineNr:maxRawNr.
-		aTab anchor:x@y extent:(maxY @ maxSz).
-		maxRawNr := maxRawNr + 1.
-		x := x + maxY.
-	    ].
-	    ^ self
-	].
-	list do:[:aTab||eY n|
-	    eY := aTab preferredExtentX.
-	    n  := eY + y - ovl.
-
-	    (n > maxSz and:[y ~~ 0]) ifTrue:[
-		maxRawNr := maxRawNr + 1.
-		y := 0.
-		x := x  + maxY.
-		n := eY - ovl.
-	    ].
-	    aTab lineNr:maxRawNr.
-	    aTab anchor:x@y extent:(maxY @ eY).
-	    y := n.
-	]
-    ].
- "/ fit raws to view
-    1 to:maxRawNr do:[:aLnNr|self fitRawAt:aLnNr].
-!
-
-unfitLastRaw
-    "use the preferred extent for all tabs in the last raw
-    "
-    |last first tab ovl anchor extent pos offset hrz|
-
-    fitLastRow ifTrue:[
-	^ self
-    ].
-    last  := list  findLast:[:aTab| aTab lineNr == maxRawNr ].
-    first := list findFirst:[:aTab| aTab lineNr == maxRawNr ].
-    ovl   := tabStyle at:#rightCovered.
-    pos   := 0.
-    hrz   := (self isHorizontalDirection).
-
-    first to:last do:[:i|
-	tab := list at:i.
-	anchor := tab anchor.
-	extent := tab extent.
-	offset := tab preferredExtentX.
+    tabModus := true.
 
-	hrz ifTrue:[
-	    extent x:offset.
-	    anchor x:pos
-	] ifFalse:[
-	    extent y:offset.
-	    anchor y:pos.
-	].
-	tab anchor:anchor extent:extent.
-	pos := pos + offset - ovl.
-    ].
-! !
 
-!TabView methodsFor:'private'!
-
-findTabStartingWithKey:aKey startingAt:anIndex
-    "get index of tab starting its printableLabel with a key or 0
-    "
-    |upper lower|
-
-    (aKey isCharacter and:[anIndex <= list size]) ifFalse:[ ^ 0 ].
-
-    upper := aKey asUppercase.
-    lower := aKey asLowercase.
-
-  ^ list findFirst:[:aTab||l c|
-	(    (l := aTab printableLabel) isString
-	 and:[((c := l first) == lower or:[c == upper])]
-	)
-    ] startingAt:anIndex
-!
-
-listIndexOf:something
-    "convert something to an index into list or nil.
-    "
-    |index|
-
-    something isNil ifTrue:[^ nil ].
-
-    something isNumber ifTrue:[
-	index := something
-    ] ifFalse:[
-	index := list findFirst:[:aTab|aTab label = something].
-
-	index == 0 ifTrue:[
-	    index := list findFirst:[:aTab|aTab printableLabel = something].
-	]
-    ].
-  ^ index ~~ 0 ifTrue:[index] ifFalse:[nil]
-!
-
-removeListDependencies
-    |model|
-
-    list notNil ifTrue:[
-	list do:[:aTab|
-	    (model := aTab model) notNil ifTrue:[
-		model removeDependent:self
-	    ]
-	]
-    ]
-! !
-
-!TabView methodsFor:'queries'!
-
-canSelectTabAtIndex:anIndex
-    "returns true if tab at an index is selectable
-    "
-    (list at:anIndex) isEnabled ifTrue:[
-	^ selectConditionBlock isNil ifTrue:[true]
-				    ifFalse:[selectConditionBlock value:anIndex]
-    ].
-    ^ false
-!
-
-getBackgroundPaintForTab:aTab
-    "returns background color of the tab
-    "
-    |key|
-
-    key := aTab == (self tabAt:selection) ifFalse:[#unselectedColor]
-					   ifTrue:[#selectedColor].
-
-    ^ tabStyle at:key
-!
-
-isEnabled
-    "returns enabled state
-    "
-  ^ enabled
-!
-
-isHorizontalDirection
-    "returns true in case of direction is #top or #bottom
-    "
-    ^ (direction == #top or:[direction == #bottom])
-
-!
-
-isVerticalDirection
-    "returns true in case of direction is #left or #right
-    "
-    ^ (direction == #left or:[direction == #right])
-
-! !
-
-!TabView methodsFor:'selection'!
-
-isTabSelected:aTab
-    "returns true if tab is selected
-    "
-    ^ aTab == (self tabAt:selection)
-!
-
-selection
-    "return the selection index or nil
-    "
-    |tab|
-
-    useIndex ifTrue:[
-	^ selection ? 0
-    ].
-    tab := self tabAt:selection.
-  ^ tab notNil ifTrue:[tab label] ifFalse:[nil]
-!
-
-selection:anIndexOrNil
-    "change the selection to index or nil. The model and/or actionBlock is notified
-    "
-    |oldSel|
-
-    oldSel := selection.
-    self setSelection:anIndexOrNil.
-    oldSel ~~ selection ifTrue:[self selectionHasChanged].
-!
-
-selectionHasChanged
-    "selection might change; raise notification
-    "
-    |sel|
-
-    sel := self selection.
-
-    model  notNil ifTrue:[model  value:sel].
-    action notNil ifTrue:[action value:sel]
-
-!
-
-setSelection:something
-    "change the selection to index or nil. No notifications are raised
-    "
-    |newSel lnNr tab last first exp x y w h|
-
-    list size == 0 ifTrue:[^ self].
-    newSel := self listIndexOf:something.
-    selection == newSel ifTrue:[^ self].
-
-    newSel notNil ifTrue:[
-	(self tabAt:newSel) isNil ifTrue:[
-	    newSel := nil
-	] ifFalse:[
-	    (self canSelectTabAtIndex:newSel) ifFalse:[^ self ].
-	]
-    ].
-
-    self shown ifFalse:[
-	selection := newSel.
-      ^ self
-    ].
-
-    maxRawNr isNil ifTrue:[
-	selection := newSel.
-	self recomputeList.
-	self invalidate.
-	^ self.
-    ].
-
-    (newSel notNil 
-	 and:[moveSelectedRow
-	 and:[(lnNr := (list at:newSel) lineNr) > 1]]
-    ) ifTrue:[
-	self changeRaw:1 with:lnNr.
-	selection := 1.                                 "/ force a redraw
-    ].
-
-    selection notNil ifTrue:[
-	maxRawNr > 1 ifTrue:[
-	    self paint:(self viewBackground).           "/ total redraw
-	    self clear.
-	    selection := nil.
-	    maxRawNr to:1 by:-1 do:[:i| self redrawRawAt:i ].
-	] ifFalse:[
-	    first := 1.
-
-	    (selection ~~ 1 and:[(tabStyle at:#rightCovered) == 0]) ifTrue:[
-		first := selection - 1
-	    ].
-
-	    (last := selection + 1) > list size ifTrue:[
-		last := selection
-	    ].
-	    exp := (tabStyle at:#expandSelection) x.
-	    tab := list at:selection.
-
-	    self isHorizontalDirection ifTrue:[
-		(x := tab anchor x - (exp // 2)) < 0 ifTrue:[x := 0].
-		w := tab extent x + exp.
-		h := super extent y.
-		y := 0.
-	    ] ifFalse:[
-		(y := tab anchor y - (exp // 2)) < 0 ifTrue:[y := 0].
-		h := tab extent y + exp.
-		w := super extent x.
-		x := 0.
-	    ].
-	    self paint:(self viewBackground).
-	    self clearRectangleX:x y:y width:w height:h.
-
-	    last to:first by:-1 do:[:i|
-		tab := list at:i.
-		tab redraw:false
-	    ]
-	]
-    ].
-    selection := newSel.
-    self redrawSelection.
-
-    "Modified: / 6.6.1998 / 19:56:45 / cg"
 ! !
 
 !TabView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/TabView.st,v 1.45 1999-05-21 18:01:23 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/TabView.st,v 1.46 1999-06-07 12:45:09 cg Exp $'
 ! !