HierarchicalListView.st
changeset 2383 ed5e995b7dc4
parent 2378 1352390d1916
child 2392 2e61452ae911
--- a/HierarchicalListView.st	Mon Nov 18 12:36:54 2002 +0100
+++ b/HierarchicalListView.st	Wed Nov 20 11:00:56 2002 +0100
@@ -192,6 +192,31 @@
 
 
 "
+!
+
+test
+    |top sel list item|
+
+    list := HierarchicalList new.
+    item := HierarchicalItem::Example labeled:'Root Item'.
+
+    item expand.
+    list showRoot:false.
+    list root:item.
+
+    top := StandardSystemView new; extent:300@300.
+    sel := ScrollableView for:HierarchicalListView miniScrollerH:true
+                       origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+    sel useDefaultIcons:false.
+    sel list:list.
+    sel multipleSelectOk:true.
+    sel showLines:false.
+
+    sel doubleClickAction:[:i| (list at:i) toggleExpand ].
+    sel   indicatorAction:[:i| (list at:i) toggleExpand ].
+
+    top open.
 ! !
 
 !HierarchicalListView class methodsFor:'resources'!
@@ -317,12 +342,6 @@
         showRoot := aList showRoot
     ].
     super list:aList
-!
-
-parentToChildInset
-    "returns the computed inset between parent / child
-    "
-    ^ imageInset + imageWidth
 ! !
 
 !HierarchicalListView methodsFor:'accessing-behavior'!
@@ -399,7 +418,7 @@
 alignTextRightX:aNumber
     "set the minimum used text inset, if text is aligned right.
     "
-    aNumber > self parentToChildInset ifTrue:[
+    aNumber > 0 ifTrue:[
         alignTextRightX := aNumber.
 
         (alignTextRight and:[widthOfContents notNil]) ifTrue:[
@@ -464,7 +483,10 @@
     "
     aBoolean ~~ showLeftIndicators ifTrue:[
         showLeftIndicators := aBoolean.
-        shown ifTrue:[ self invalidate ].
+
+        (shown and:[indicatorAction notNil]) ifTrue:[
+            self invalidate
+        ]
     ].
 !
 
@@ -642,9 +664,7 @@
     x1 := (self xVisibleOfTextAtLevel:level) - 1.
     x1 > margin ifFalse:[^ self].
 
-    arg == #hierarchy ifTrue:[ level := level - 1 ].
-
-    x0 := (self xVisibleOfIconAtLevel:level) max:margin.
+    x0 := (self xVisibleOfIndicatorAtLevel:level) max:margin.
     x1 := x1 min:(width - margin).
 
     x0 < x1 ifTrue:[
@@ -670,9 +690,9 @@
      and:[(item := list at:firstAddedIndex ifAbsent:nil) notNil
      and:[(level := item level) > 1]]]]]
     ) ifFalse:[
-         ^ self.
+        ^ self.
     ].
-    xLft := (self xVisibleOfIconAtLevel:(level - 1)) + (imageWidth // 2) - 1.
+    xLft := self xVisibleOfVerticalLineAt:level.
 
     (xLft > margin and:[xLft < (width - margin)]) ifFalse:[
         ^ self
@@ -690,7 +710,7 @@
 
             yTop < maxY ifTrue:[
                 yBot := (self yVisibleOfLine:firstAddedIndex) - 1 min:maxY.
-                self invalidate:(Rectangle left:xLft top:yTop width:3 height:(yBot - yTop))
+                self invalidate:(Rectangle left:xLft top:yTop width:2 height:(yBot - yTop))
             ].
             ^ self
         ]
@@ -737,10 +757,11 @@
 drawElementsFrom:start to:stop x:xLeft y:yT w:w
     "draw the items between start to stop without clearing the background
     "
-    |item prevItem parent icon showIndc showIcon showText nxtPrnt extent
+    |item prevParent icon showIndc showIcon showText
      yTop      "{ Class:SmallInteger }"
      yCtr      "{ Class:SmallInteger }"
      yBot      "{ Class:SmallInteger }"
+     level     "{ Class:SmallInteger }"
 
      xIndc     "{ Class:SmallInteger }"
      xIcon     "{ Class:SmallInteger }"
@@ -749,72 +770,45 @@
      xR        "{ Class:SmallInteger }"
      height    "{ Class:SmallInteger }"
 
-     widthLvl  "{ Class:SmallInteger }"
-     insetTxt  "{ Class:SmallInteger }"
-
-     offIndcX  "{ Class:SmallInteger }"
      offIndcY  "{ Class:SmallInteger }"
-     offIconX  "{ Class:SmallInteger }"
     |
-    widthLvl := self parentToChildInset.
-    insetTxt := textStartLeft + imageWidth.
-    xL       := xLeft.
-    xR       := xL + w.
-
-    alignTextRight ifTrue:[
-        xText    := alignTextRightX - (viewOrigin x).
-        showText := xText < xR.
-    ].
-
-    offIconX := self xVisibleOfIconAtLevel:0.
-    showIndc := false.
+    xL := xLeft.
+    xR := xL + w.
 
     indicatorAction notNil ifTrue:[
-        offIndcX := offIndcY := 0.
-        openIndicator notNil ifTrue:[
-            extent   := openIndicator extent // 2.
-            offIndcX := imageWidth // 2 - widthLvl.
-            offIndcX := offIndcX - extent x.
-            offIndcY := extent y.
-        ]
+        offIndcY := openIndicator width // 2.
     ].
 
     showLines ifTrue:[
         self drawLinesFrom:start to:stop x:xL y:yT toX:xR
     ].
-
-    parent   := 4711.   "/ to force a recompute
-    prevItem := 4711.   "/ to force a recomputation of the level
-    yBot     := yT.
-    xIcon    := offIconX.
+    prevParent := #NIL.         "/ to force a recompute
+    yBot       := yT.
+    showIndc   := false.
 
     start to:stop do:[:anIndex|
         (item := list at:anIndex ifAbsent:nil) isNil ifTrue:[
             ^ self      "/ list changed
         ].
-        yTop := yBot.
-        yBot := self yVisibleOfLine:(anIndex + 1).
+        yTop   := yBot.
+        yBot   := self yVisibleOfLine:(anIndex + 1).
         height := yBot - yTop.
-
-        yCtr := yTop + (height // 2).
+        yCtr   := yTop + (height // 2).
 
-        (nxtPrnt := item parent) ~~ parent ifTrue:[
-            parent := nxtPrnt.
-            xIcon  := prevItem == parent ifTrue:[xIcon + widthLvl]
-                                        ifFalse:[item level * widthLvl + offIconX].
-
-            alignTextRight ifFalse:[
-                xText    := xIcon + insetTxt.
-                showText := (xText < xR).
-            ].
-            showIcon := (xIcon < xR and:[xText > xL]).
+        item parent ~~ prevParent ifTrue:[
+            prevParent := item parent.
+            level      := item level.
+            xIcon      := self xVisibleOfIconAtLevel:level.
+            xText      := self xVisibleOfTextAtLevel:level.
+            showText   := (xText < xR).
+            showIcon   := (xIcon < xR and:[xText > xL]).
 
             indicatorAction notNil ifTrue:[
-                xIndc    := xIcon + offIndcX.
+                xIndc  := self xVisibleOfIndicatorAtLevel:level.
                 showIndc := (xIcon > xL and:[xIndc < xR]).
 
                 showIndc ifTrue:[
-                    showIndc := parent notNil or:[showLeftIndicators]
+                    showIndc := prevParent notNil or:[showLeftIndicators]
                 ]
             ]
         ].
@@ -834,15 +828,13 @@
 
             icon displayOn:self x:xIndc y:(yCtr - offIndcY)
         ].
-        prevItem := item.
-    ]
+    ].
 !
 
 drawLinesFrom:start to:stop x:xL y:yT toX:xR
     "draw the lines between start to stop without clearing the background
     "
-    |item prevItem parent p1 p2 showVLines showHLine lv nxtPrnt
-     showRootNot isFirst buildInArray
+    |item prevItem parent p1 p2 showVLines showHLine lv buildInArray showLeftIdc
 
      x        "{ Class:SmallInteger }"
      xText    "{ Class:SmallInteger }"
@@ -854,50 +846,36 @@
 
      begHLnY  "{ Class:SmallInteger }"
      runHLnY  "{ Class:SmallInteger }"
-     begHLnX  "{ Class:SmallInteger }"
-     endHLnX  "{ Class:SmallInteger }"
-
-     widthLvl  "{ Class:SmallInteger }"
-     offsHLnX  "{ Class:SmallInteger }"
+     lftVrtX  "{ Class:SmallInteger }"
+     rgtVrtX  "{ Class:SmallInteger }"
+     level    "{ Class:SmallInteger }"
 
-     level     "{ Class:SmallInteger }"
-     startLvI  "{ Class:SmallInteger }"
-     startLvX  "{ Class:SmallInteger }"
-     limitLvI  "{ Class:SmallInteger }"
-     limitLvX  "{ Class:SmallInteger }"
-     imgHWdt   "{ Class:SmallInteger }"
-     minXVLine "{ Class:SmallInteger }"
+     minVertLevel   "{ Class:SmallInteger }"
+     minHorzLevel   "{ Class:SmallInteger }"
+     smallestLevel  "{ Class:SmallInteger }"
     |
-    imgHWdt  := imageWidth // 2.
-    widthLvl := self parentToChildInset.
-    offsHLnX := imgHWdt + (self xVisibleOfIconAtLevel:-1).
-
-    parent   := 4711.                           "/ to force a recompute
-    prevItem := 4711.                           "/ to force a recomputation of the level
+    parent := prevItem := 4711. "/ to force a recompute
 
     self setMaskOrigin:(self viewOrigin + (0 @ 1) \\ (lineMask extent)).
     self paint:lineColor on:bgColor.
     self mask:lineMask.
-    startLvI := self smallestLevelBetween:start and:stop.
-    startLvX := self xVisibleOfIconAtLevel:startLvI.
-    limitLvI := 2.
-    limitLvX := limitLvI * widthLvl + offsHLnX.
+
+    smallestLevel := self smallestLevelBetween:start and:stop.
+
+    showRoot ifFalse:[ minHorzLevel := 2 ]
+              ifTrue:[ minHorzLevel := 1 ].
 
-    showRoot ifFalse:[
-        minXVLine := (self xVisibleOfIconAtLevel:2) - 2.       "/ tolerance
-    ] ifTrue:[
-        minXVLine := 0
+    minVertLevel := 2.
+    showLeftIdc  := indicatorAction notNil and:[showLeftIndicators].
+
+    showLeftIdc ifTrue:[
+        showRoot ifFalse:[ minVertLevel := 3 ]
+    ] ifFalse:[
+        minHorzLevel := minHorzLevel + 1
     ].
 
-    showRootNot  := showRoot not.
-    yBot         := yT.
-    begHLnY      := runHLnY := yT.
-    endHLnX      := limitLvX.
-    level        := 1.
-
-    alignTextRight ifTrue:[
-        xText := alignTextRightX - (viewOrigin x) - textStartLeft.
-    ].
+    yBot  := begHLnY := runHLnY := yT.
+    level := 1.
 
     start to:stop do:[:anIndex|
         (item := list at:anIndex ifAbsent:nil) isNil ifTrue:[
@@ -906,105 +884,95 @@
         yTop := yBot.
         yBot := self yVisibleOfLine:(anIndex + 1).
         yCtr := yTop + (yBot - yTop // 2).
-        anIndex == 1 ifTrue:[ begHLnY := runHLnY := yCtr ].
 
-        (nxtPrnt := item parent) ~~ parent ifTrue:[
-            parent := nxtPrnt.
+        item parent ~~ parent ifTrue:[
+            anIndex == 1 ifTrue:[ begHLnY := runHLnY := yCtr ].
+            parent := item parent.
 
             prevItem == parent ifTrue:[
                 level   := level + 1.
-                begHLnX := endHLnX.
+                lftVrtX := rgtVrtX.
             ] ifFalse:[
                 level   := item level.
-                begHLnX := level * widthLvl + offsHLnX.
+                lftVrtX := self xVisibleOfVerticalLineAt:level.
             ].
-
-            isFirst    := parent isNil or:[(showRootNot and:[level == 2])].
-            endHLnX    := begHLnX + widthLvl.
-            showVLines := begHLnX >= xL and:[level > 1].
+            showVLines := (level >= minVertLevel and:[lftVrtX >= xL]).
+            rgtVrtX    := self xVisibleOfVerticalLineAt:level + 1.
 
-            alignTextRight ifFalse:[
-                xText := endHLnX + (widthLvl // 2).
+            level >= minHorzLevel ifTrue:[
+                xText := (self xVisibleOfTextAtLevel:level) - textStartLeft.
+                showHLine := (xL < xText and:[xR > lftVrtX]). 
+            ] ifFalse:[
+                showHLine := false
             ].
-            showHLine := (xL < xText and:[xR > begHLnX]).
-
-            (showHLine and:[isFirst]) ifTrue:[
-                showHLine := showLeftIndicators and:[indicatorAction notNil]
-            ]
         ].
 
         showHLine ifTrue:[
-            item drawHorizontalLineUpToText ifTrue:[
-                p1 := xText
-            ] ifFalse:[
-                item hasChildren ifTrue:[
-                    p1 := endHLnX.
-                ] ifFalse:[
-                    (showRoot not and:[item parent isRootItem]) ifTrue:[
-                        p1 := xL - 1    "/ do not draw the horizontal line
-                    ] ifFalse:[
-                        p1 := begHLnX + imgHWdt
-                    ]
-                ]
+            ( level ~~ 2
+             or:[showRoot or:[(showLeftIdc and:[item hasIndicator])]]
+            ) ifTrue:[
+                item drawHorizontalLineUpToText ifTrue:[ x := xText ]
+                                               ifFalse:[ x := rgtVrtX ].
+
+                self displayLineFromX:lftVrtX y:yCtr toX:x y:yCtr.
             ].
-            xL < p1 ifTrue:[
-                self displayLineFromX:begHLnX y:yCtr toX:p1 y:yCtr
+        ].
+
+        anIndex == start ifTrue:[
+            (item isExpanded and:[item hasChildren]) ifTrue:[
+                self displayLineFromX:rgtVrtX y:yCtr toX:rgtVrtX y:yBot.
             ]
         ].
 
         showVLines ifTrue:[
-            y  := (parent last == item) ifTrue:[yCtr] ifFalse:[yBot].
-            x  := begHLnX.
+            parent last == item ifTrue:[ y := yCtr ]
+                               ifFalse:[ y := yBot ].
+            x  := lftVrtX.
             p2 := parent.
             lv := level - 1.
 
-            x >= minXVLine ifTrue:[
+            level >= smallestLevel ifTrue:[
                 self displayLineFromX:x y:runHLnY toX:x y:y.
             ].
 
-            [((p1 := p2 parent) notNil and:[(x := x - widthLvl) >= limitLvX])] whileTrue:[
-                (p1 last ~~ p2 and:[x <= xR]) ifTrue:[
-                    x >= startLvX ifTrue:[
-                        x >= minXVLine ifTrue:[
-                            self displayLineFromX:x y:(yTop - 1) toX:x y:yBot
-                        ]
+            [ (p2 notNil and:[lv >= minVertLevel]) ] whileTrue:[
+                p1 := p2 parent.
+
+                p1 notNil ifTrue:[
+                    x := self xVisibleOfVerticalLineAt:lv.
+
+                    x < xL ifTrue:[
+                        p1 := nil.
                     ] ifFalse:[
-                        buildInArray isNil ifTrue:[buildInArray := Array new:startLvI].
-                        buildInArray at:lv put:yBot
+                        p1 last ~~ p2 ifTrue:[
+                            lv >= smallestLevel ifTrue:[
+                                self displayLineFromX:x y:(yTop - 1) toX:x y:yBot
+                            ] ifFalse:[
+                                buildInArray isNil ifTrue:[buildInArray := Array new:smallestLevel].
+                                buildInArray at:lv put:yBot
+                            ]    
+                        ].
                     ].
                 ].
+                p2 := p1.
                 lv := lv - 1.
-                p2 := p1
-            ]
+            ].
         ].
         prevItem := item.
         runHLnY  := yCtr.
     ].
 
-    "/
-    "/ draw outstanding verical lines to left
-    "/
-    x := minXVLine max:xL.
-
-    (item isExpanded and:[item hasChildren]) ifTrue:[
-        (endHLnX >= x and:[endHLnX <= xR]) ifTrue:[
-            self displayLineFromX:endHLnX y:yCtr toX:endHLnX y:yBot.
-        ]
-    ].
-
     buildInArray notNil ifTrue:[
-        x := limitLvX.
         y := begHLnY.
 
-        limitLvI to:startLvI do:[:i|
-            |yB|
+        2 to:smallestLevel do:[:i| |u yB|
+            (yB := buildInArray at:i) notNil ifTrue:[
+                x := self xVisibleOfVerticalLineAt:i.
 
-            (yB := buildInArray at:i) notNil ifTrue:[
-                x >= minXVLine ifTrue:[
+                x >= xL ifTrue:[
                     self displayLineFromX:x y:y toX:x y:yB
                 ]
             ].
-            x := x + widthLvl.
         ]
     ].
     self mask:nil.
@@ -1014,7 +982,7 @@
     "returns the icon to be drawn for an item or nil
      test the extent of the icopn; on error an exception is raised
     "
-    |width needMore icon maxLevel startOfText|
+    |width needMore icon maxLevel startOfText oldX newX|
 
     icon := self iconFor:anItem.
     icon isNil ifTrue:[^ nil].
@@ -1033,21 +1001,23 @@
         width <= imageWidth ifTrue:[ ^ icon ].
     ].
 
-    needMore   := width - imageWidth max:2.
-    imageWidth := imageWidth + needMore.
-    maxLevel   := 1.
+    maxLevel := 1.
 
     list criticalDo:[
         list do:[:el| maxLevel := maxLevel max:(el level) ].
     ].
-    alignTextRightX := alignTextRightX max:(self xVisibleOfIconAtLevel:(maxLevel + 1)).
+
+    needMore        := (width - imageWidth) max:2.
+    oldX            := self xVisibleOfIconAtLevel:(maxLevel + 1).
+    imageWidth      := imageWidth + needMore.
+    newX            := self xVisibleOfIconAtLevel:(maxLevel + 1).
+    alignTextRightX := alignTextRightX max:newX.
 
     widthOfContents notNil ifTrue:[
         alignTextRight ifTrue:[
             widthOfContents := alignTextRightX + maxWidthOfText
         ] ifFalse:[
-            list showRoot ifFalse:[ maxLevel := maxLevel - 1 ].
-            widthOfContents := widthOfContents + (maxLevel * needMore)
+            widthOfContents := widthOfContents + (newX - oldX)
         ].
         width           := renderer widthFor:anItem.
         startOfText     := self xVisibleOfTextAtLevel:(anItem level).
@@ -1092,9 +1062,9 @@
 
     (button == 1 or:[button == #select]) ifTrue:[
         (item notNil and:[indicatorAction notNil and:[item hasIndicator]]) ifTrue:[
-            x0 := self xVisibleOfIconAtLevel:(item level - 1).
+            x0 := self xVisibleOfIndicatorAtLevel:(item level).
 
-            (x > x0 and:[(x0 + imageWidth) > x]) ifTrue:[
+            (x between:x0 and:(x0 + openIndicator width)) ifTrue:[
                 self indicatorPressedAt:line.
                 ^ self
             ].
@@ -1229,7 +1199,7 @@
     useDefaultIcons    := true.
     showLines          := true.
     imageInset         := 4.
-    imageWidth         := 16. "/ default
+    imageWidth         := 0.
     alignTextRight     := false.
     alignTextRightX    := 8.
     maxWidthOfText     := 0.
@@ -1349,84 +1319,81 @@
 widthOfWidestLineBetween:firstLine and:lastLine
     "returns the width of the longest line in pixels in a range
     "
-    |nprnt pprnt pitem item
-     textX     "{ Class: SmallInteger }"
-     level     "{ Class: SmallInteger }"
-     width     "{ Class: SmallInteger }"
-     deltaX    "{ Class: SmallInteger }"
-     startX    "{ Class: SmallInteger }"
-     itemW     "{ Class: SmallInteger }"
+    |parent item
+     textX        "{ Class: SmallInteger }"
+     level        "{ Class: SmallInteger }"
+     width        "{ Class: SmallInteger }"
+     widthOfLabel "{ Class: SmallInteger }"
     |
-    width  := 20.
-    level  := 1.
-    pprnt  := 4711.  "/ force a computation
-    deltaX := self parentToChildInset.
+    width := 20.
 
     alignTextRight ifTrue:[
+        parent := nil.
+        level  := 1.
+
         firstLine to:lastLine do:[:idx|
             item := list at:idx ifAbsent:nil.
 
             item notNil ifTrue:[
                 width := (renderer widthFor:item) max:width.
 
-                nprnt := item parent.
-                nprnt ~~ pprnt ifTrue:[
-                    level := item level max:level.
-                    pprnt := nprnt.
+                item parent ~~ parent ifTrue:[
+                    level  := item level max:level.
+                    parent := item parent.
                 ].
             ].
         ].
         maxWidthOfText := maxWidthOfText max:width.
-        startX         := self xVisibleOfIconAtLevel:(level + 1).
+        textX := self xVisibleOfIconAtLevel:(level + 1).
 
-        alignTextRightX < startX ifTrue:[
+        alignTextRightX < textX ifTrue:[
+            alignTextRightX := textX
             shown ifTrue:[ self invalidate].
-            alignTextRightX := startX
         ].
         ^ alignTextRightX + width
     ].
 
-    pitem  := 4712.  "/ force a computation
-    startX := (self xVisibleOfTextAtLevel:1) + (viewOrigin x).
-    textX  := 0.
-    level  := 1.
+    parent := 4711.  "/ force a computation
 
     firstLine to:lastLine do:[:idx|
         item := list at:idx ifAbsent:nil.
-        item isNil ifTrue:[^ width + startX].
 
-        (nprnt := item parent) ~~ pprnt ifTrue:[
-            (pprnt := nprnt) == pitem ifTrue:[
-                level := level + 1.
-                textX := textX + deltaX.
-            ] ifFalse:[
-                level := item level.
-                textX := level - 1 * deltaX.
-            ]
+        item notNil ifTrue:[
+            item parent ~~ parent ifTrue:[
+                textX  := self xVisibleOfTextAtLevel:(item level).
+                parent := item parent.
+            ].
+            widthOfLabel   := renderer widthFor:item.
+            maxWidthOfText := maxWidthOfText max:widthOfLabel.
+            width          := widthOfLabel + textX max:width
         ].
-        pitem := item.
-        itemW := renderer widthFor:item.
-        maxWidthOfText := maxWidthOfText max:itemW.
-        width := (itemW + textX) max:width
     ].
-    ^ width + startX.
+    ^ width + viewOrigin x.
 !
 
 xVisibleOfIconAtLevel:aLevel
     "returns the visible origin x of the icon at a level.
     "
-    |l "{ Class:SmallInteger }"|
+    |x|
 
-    l := showRoot ifTrue:[aLevel] ifFalse:[aLevel - 1].
+    x := self xVisibleOfVerticalLineAt:aLevel.
 
-    indicatorAction isNil ifTrue:[
-        l := l - 1
-    ] ifFalse:[
-        showLeftIndicators ifFalse:[
-            l := l - 1
-        ]
+    (showRoot and:[aLevel == 1]) ifTrue:[
+        (indicatorAction notNil and:[showLeftIndicators]) ifFalse:[
+            ^ x - (imageWidth // 2)
+        ].
     ].
-  ^ (l * (self parentToChildInset)) + imageInset - (viewOrigin x)
+    ^ x + (openIndicator width // 2) + imageInset
+!
+
+xVisibleOfIndicatorAtLevel:aLevel
+    "returns the visible origin x of the vertical line at a level.
+    "
+    |x|
+
+    x := self xVisibleOfVerticalLineAt:aLevel.
+    x := x - (openIndicator width // 2).
+    ^ x
 !
 
 xVisibleOfItem:anItem
@@ -1442,6 +1409,35 @@
         ^ alignTextRightX - (viewOrigin x)
     ].
     ^ (self xVisibleOfIconAtLevel:aLevel) + imageWidth + textStartLeft
+!
+
+xVisibleOfVerticalLineAt:aLevel
+    "returns the visible origin x of the vertical line assigned to a level.
+    "
+    |xOffset opWidth2 igWidth2 firstLevel|
+
+    opWidth2 := openIndicator width // 2.
+    igWidth2 := imageWidth // 2.
+    xOffset  := igWidth2 + opWidth2 + imageInset.
+
+    showRoot ifTrue:[ firstLevel := 1 ]
+            ifFalse:[ firstLevel := 2 ].
+
+    (indicatorAction notNil and:[showLeftIndicators]) ifTrue:[
+        aLevel < firstLevel ifTrue:[
+            xOffset := opWidth2 - (firstLevel * xOffset)
+        ] ifFalse:[
+            xOffset := opWidth2 + (aLevel - firstLevel * xOffset)
+        ]
+    ] ifFalse:[
+        aLevel < 2 ifTrue:[
+            xOffset := igWidth2 - (aLevel - firstLevel * xOffset)
+        ] ifFalse:[
+            xOffset := igWidth2 + (aLevel - firstLevel - 1 * xOffset)
+        ].
+    ].
+    "/ 2 := a left margin
+    ^ xOffset + 2 - (viewOrigin x)
 ! !
 
 !HierarchicalListView methodsFor:'scrolling'!
@@ -1449,33 +1445,32 @@
 computeViewOriginXat:aLnrNr
     "returns the viewOrigin x to make the item at a line visisble
     "
-    |item xLft xRgt lvWidth level vwOrgX xInset|
-
-    alignTextRight ifTrue:[^ viewOrigin x ].
-
-    aLnrNr == 1 ifTrue:[^ 0].
+    |item xLft xRgt level vwOrgX useX|
 
     vwOrgX := viewOrigin x.
 
+    alignTextRight ifTrue:[ ^ vwOrgX ].
+    aLnrNr == 1    ifTrue:[ ^ 0 ].
+
     item := list at:aLnrNr ifAbsent:nil.
     item isNil ifTrue:[ ^ vwOrgX ].
 
     level := item level.
-    level <= 2 ifTrue:[^ 0 ].
+    level == 1 ifTrue:[ ^ 0 ].                                  "/ is root item
+
+    level == 2 ifTrue:[                                         "/ parent is root
+        (showRoot and:[showLeftIndicators]) ifFalse:[ ^ 0 ].
+    ].
 
     xLft := self xVisibleOfIconAtLevel:(level - 1).
-    lvWidth := self parentToChildInset.
+    xLft > 0 ifFalse:[ ^ vwOrgX + xLft max:0 ].
 
     xRgt := (self xVisibleOfTextAtLevel:level) + (renderer widthFor:item).
-
-    xLft > lvWidth negated ifTrue:[
-        xRgt < width ifTrue:[^ vwOrgX]
-    ].
+    useX := xRgt - width.
 
-    xInset := ((width - (xRgt - xLft) // 2) // lvWidth * lvWidth) max:0.
-    vwOrgX := xLft + vwOrgX - xInset - margin.
-    vwOrgX < lvWidth ifTrue:[^ 0 ].
-    ^ vwOrgX
+    useX > 0 ifFalse:[ ^ vwOrgX ].
+    useX := useX + 16 min:xLft.
+    ^ vwOrgX + useX.
 !
 
 makeLineVisible:aLnrNr
@@ -1516,5 +1511,5 @@
 !HierarchicalListView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/HierarchicalListView.st,v 1.74 2002-11-15 09:22:43 ca Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/HierarchicalListView.st,v 1.75 2002-11-20 10:00:56 ca Exp $'
 ! !