HierarchicalListView.st
changeset 2224 bfcabf142faa
parent 2210 c2b830a14832
child 2227 c5e6912cc6b2
--- a/HierarchicalListView.st	Thu Sep 26 20:49:13 2002 +0200
+++ b/HierarchicalListView.st	Fri Sep 27 13:32:55 2002 +0200
@@ -17,7 +17,8 @@
 	instanceVariableNames:'imageInset imageWidth lineMask lineColor showRoot showLines
 		showLeftIndicators indicatorAction useDefaultIcons icons
 		openIndicator closeIndicator alignTextRight alignTextRightX
-		maxWidthOfText levelOfLastItem'
+		maxWidthOfText levelOfLastItem expandOnSelect
+		autoScrollHorizontal'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Views-Trees'
@@ -243,6 +244,36 @@
     ^ imageInset + imageWidth
 ! !
 
+!HierarchicalListView methodsFor:'accessing-behavior'!
+
+autoScrollHorizontal
+    "true, than automatically scroll horizontal upto the text label
+     of the current selected line.
+    "
+    ^ autoScrollHorizontal ? false
+!
+
+autoScrollHorizontal:aBoolean
+    "true, than automatically scroll horizontal upto the text label
+     of the current selected line.
+    "
+    autoScrollHorizontal := aBoolean.
+!
+
+expandOnSelect
+    "true, than the item selected by a buttonPress event will
+     be immediately expanded.
+    "
+    ^ expandOnSelect
+!
+
+expandOnSelect:aBoolean
+    "true, than the item selected by a buttonPress event will
+     be immediately expanded.
+    "
+    expandOnSelect := aBoolean.
+! !
+
 !HierarchicalListView methodsFor:'accessing-colors'!
 
 lineColor
@@ -425,16 +456,42 @@
 !HierarchicalListView methodsFor:'change & update'!
 
 indicatorPressedAt:aLnNr
-    |item|
+    "handle indicator pressed action;
+     if the item changed expanded, we try to show all
+     new visible children
+    "
+    |item expanded availY usedY vwOrgX vwOrgY idx|
+
+    indicatorAction ifNil:[^ self].
+
+    item := list at:aLnNr ifAbsent:nil.
+    item ifNil:[^ self].
+
+    item hasIndicator ifFalse:[^ self].
+
+    expanded := item isExpanded.
+    indicatorAction valueWithOptionalArgument:aLnNr.
+    (expanded or:[item isExpanded not]) ifTrue:[^ self].
 
-    indicatorAction notNil ifTrue:[
-        item := list at:aLnNr ifAbsent:nil.
-        item ifNotNil:[
-            item hasIndicator ifTrue:[
-                indicatorAction valueWithOptionalArgument:aLnNr
-            ]
-        ]
-    ]
+    "/ compute the index of last child assigned to item
+
+    idx := item numberOfVisibleChildren.        "/ no visible children
+    idx == 0 ifTrue:[^ self].
+
+    idx    := aLnNr + idx.
+    vwOrgY := viewOrigin y.
+    availY := (self yVisibleOfLine:aLnNr) - margin.
+
+    availY > margin ifTrue:[
+        usedY := (self yVisibleOfLine:(idx + 1)) - (height - margin - margin).
+
+        usedY > 1 ifTrue:[
+            vwOrgY := vwOrgY + (usedY min:availY).
+        ].
+    ].
+    vwOrgX := self computeViewOriginXat:aLnNr.
+
+    self scrollTo:(vwOrgX @ vwOrgY).
 !
 
 lineChangedAt:aLnNr with:arg
@@ -450,7 +507,21 @@
     |
 
     (arg == #icon or:[arg == #hierarchy]) ifFalse:[
-        ^ super lineChangedAt:aLnNr with:arg
+        item := list at:aLnNr ifAbsent:nil.
+        item ifNil:[^ self].
+
+        super lineChangedAt:aLnNr with:arg.
+
+        (arg ~~ #redraw and:[widthOfContents notNil]) ifTrue:[
+            x0 := self xOfStringLevel:aLnNr.
+            x0 := x0 + (item widthOn:self) + 5.
+
+            x0 > widthOfContents ifTrue:[
+                widthOfContents := x0.
+                self contentsChanged.
+            ]
+        ].
+        ^ self
     ].
     shown ifFalse:[^ self].
 
@@ -888,16 +959,38 @@
 buttonPress:button x:x y:y
     "handle a button press event
     "
-    |lnNr|
+    |lineNr|
+
+    enabled ifFalse:[^ self].
+
+    (button == 1 or:[button == #select]) ifTrue:[
+        lineNr := self indicatorLineAtX:x y:y.
+
+        lineNr ifNotNil:[
+            self indicatorPressedAt:lineNr.
+          ^ self
+        ].
+    ].
+    super buttonPress:button x:x y:y.
+!
 
-    enabled ifTrue:[
-        (button == 1 or:[button == #select]) ifTrue:[
-            (lnNr := self indicatorLineAtX:x y:y) notNil ifTrue:[
-                ^ self indicatorPressedAt:lnNr
-            ]
+buttonPressOrReleaseAtLine:aLnNr x:x y:y
+    "handle a button press or release at a line
+    "
+    |oldIdx newIdx newItem|
+
+    oldIdx := self selectedIndex.
+    super buttonPressOrReleaseAtLine:aLnNr x:x y:y.
+    newIdx := self selectedIndex.
+
+    (newIdx ~~ oldIdx and:[newIdx ~~ 0]) ifTrue:[
+        expandOnSelect ifTrue:[
+            newItem := list at:newIdx ifAbsent:nil.
+            newItem ifNil:[^ self].
+            newItem expand
         ].
-        super buttonPress:button x:x y:y
-    ]
+        self makeLineVisible:newIdx.
+    ].
 !
 
 keyPress:aKey x:x y:y
@@ -1018,6 +1111,9 @@
     alignTextRight     := false.
     alignTextRightX    := 8.
     maxWidthOfText     := 0.
+
+    expandOnSelect       := false.
+    autoScrollHorizontal := true.
 !
 
 initialize
@@ -1254,8 +1350,92 @@
 
 ! !
 
+!HierarchicalListView methodsFor:'scrolling'!
+
+computeViewOriginXat:aLnrNr
+    "compute the visible viewOrigin x for the item at a line
+    "
+    |item xLft xRgt xOrg level viewOriginX offset|
+
+    aLnrNr == 1 ifTrue:[^ 0].
+
+    viewOriginX := viewOrigin x.
+    alignTextRight ifTrue:[ ^ viewOriginX ].
+
+    item := list at:aLnrNr ifAbsent:nil.
+    item ifNil:[ ^ viewOriginX ].
+
+    level := item level.
+    level <= 2 ifTrue:[^ 0 ].
+
+    xLft := self xOfFigureLevel:(level - 1).
+    offset := imageInset + imageWidth.
+
+    xLft > (offset + margin) ifFalse:[
+        xLft >= margin ifTrue:[ ^ viewOriginX ].
+     ^ (xLft + viewOriginX) max:0
+    ].
+    "/ x - left is visible
+
+    xRgt := (self xOfStringLevel:level) + (item widthOn:self).
+
+    xRgt < width ifTrue:[
+        "/ x - right and left is visible
+        ^ viewOriginX
+    ].
+    xOrg := xLft + viewOriginX.
+
+    [     (xLft := xLft - offset) >= margin
+     and:[(xRgt := xRgt - offset) > width]
+    ] whileTrue:[
+        xOrg := xOrg + offset
+    ].
+    ^ xOrg
+!
+
+makeLineVisible:aLnrNr
+    "scroll to make the selection line visible
+    "
+    |newY item y0 newX|
+
+    (shown and:[aLnrNr notNil]) ifFalse:[^ self].
+
+    aLnrNr <= 1 ifTrue:[
+        aLnrNr == 1 ifTrue:[ self scrollTo:(0 @ 0) ].
+      ^ self
+    ].
+
+    item := list at:aLnrNr ifAbsent:nil.
+    item ifNil:[^ self].
+
+    y0 := self yVisibleOfLine:aLnrNr.
+
+    (     y0 < margin
+     or:[(y0 + (item heightOn:self)) > (height - margin)]
+    ) ifTrue:[
+        newY := ((self yAbsoluteOfLine:aLnrNr) - (height // 2)) max:0.
+    ] ifFalse:[
+        newY := viewOrigin y.
+    ].
+
+    newX := viewOrigin x.
+
+    (autoScrollHorizontal or:[newX ~~ 0]) ifTrue:[
+        newX := self computeViewOriginXat:aLnrNr
+    ].
+    self scrollTo:(newX @ newY).
+!
+
+makeSelectionVisible
+    "scroll to make the selection line visible
+    "
+    shown ifTrue:[
+        self makeLineVisible:(self firstInSelection).
+    ].
+! !
+
 !HierarchicalListView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/HierarchicalListView.st,v 1.47 2002-09-20 15:55:10 ca Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/HierarchicalListView.st,v 1.48 2002-09-27 11:32:55 ca Exp $'
 ! !