--- a/SelectionInTree.st Tue Apr 14 13:31:49 1998 +0200
+++ b/SelectionInTree.st Tue Apr 14 13:32:54 1998 +0200
@@ -86,9 +86,9 @@
(root := aRoot) notNil ifTrue:[
root parent:nil.
root tree: self.
- ].
- self recomputeList.
-
+ ].
+ self listFromRoot.
+ self changed:#list.
! !
!SelectionInTree methodsFor:'accessing behavior'!
@@ -103,9 +103,6 @@
"set children action block
"
childrenAction := aBlock.
-
- self changed:#list.
-
!
contentsAction
@@ -118,9 +115,6 @@
"set contents action block
"
contentsAction := aBlock.
-
- self changed:#list.
-
!
iconAction
@@ -133,9 +127,6 @@
"set icon action block
"
iconAction := aBlock.
-
- self changed:#list.
-
!
labelAction
@@ -148,9 +139,6 @@
"set label action block
"
labelAction := aBlock.
-
- self changed:#list.
-
!
showRoot
@@ -166,10 +154,13 @@
showRoot := aState.
root notNil ifTrue:[
- aState ifTrue:[list addFirst:root]
- ifFalse:[list removeFirst].
-
- self changed:#list.
+ aState ifTrue:[
+ list addFirst:root.
+ self changed:#insertCollection: with:(Array with:1 with:1 with:nil).
+ ] ifFalse:[
+ list removeFirst.
+ self changed:#removeFrom: with:(Array with:1 with:1 with:nil).
+ ].
].
].
! !
@@ -179,15 +170,21 @@
collapse:something
"collapse a node or collection of nodes
"
- |invalidate|
+ |listChanged|
+
+ listChanged := false.
self each:something do:[:aNode|
aNode isCollapsable ifTrue:[
aNode collapse.
- invalidate := true
+ listChanged := true
]
].
- invalidate == true ifTrue:[self recomputeList]
+ listChanged ifTrue:[
+ self listFromRoot.
+ self changed:#list.
+ ]
+
!
expand
@@ -199,15 +196,79 @@
expand:something
"expand a node or collection of nodes
"
- |invalidate|
+ |listChanged|
+
+ listChanged := false.
self each:something do:[:aNode|
aNode isExpandable ifTrue:[
aNode expand.
- invalidate := true
+ listChanged := true
]
].
- invalidate == true ifTrue:[self recomputeList]
+ listChanged ifTrue:[
+ self listFromRoot.
+ self changed:#list.
+ ]
+! !
+
+!SelectionInTree methodsFor:'accessing hierarchy new'!
+
+doCollapse:something
+ "collapse all children under an item or a sequence of items;
+ if the list changed, notifications are raised
+ "
+ self each:something do:[:anItem|
+ self collapseItem:anItem do:[ anItem collapse ]
+ ]
+!
+
+doCollapseAll:something
+ "collapse all children and subChildren under an item or sequence of items;
+ if the list changed, notifications are raised
+ "
+ self each:something do:[:anItem|
+ self collapseItem:anItem do:[ anItem collapseAll ]
+ ]
+!
+
+doExpand:something
+ "expand all children under an item or collection of items;
+ if the list changed, notifications are raised
+ "
+ self each:something do:[:anItem|
+ self expandItem:anItem do:[anItem expand]
+ ]
+!
+
+doExpandAll:something
+ "expand all children and subChildren under an item or sequence of items;
+ if the list changed, notifications are raised
+ "
+ self each:something do:[:anItem|
+ self expandItem:anItem do:[anItem expandAll]
+ ]
+!
+
+doMakeVisible:something
+ "make an item or list of items to become visible
+ "
+ |anchor parent|
+
+ self each:something do:[:anItem|
+ parent := anItem.
+ anchor := nil.
+
+ [(parent := parent parent) notNil] whileTrue:[
+ parent hidden ifTrue:[
+ anchor notNil ifTrue:[ anchor expand ].
+ anchor := parent.
+ ]
+ ].
+ anchor notNil ifTrue:[
+ self expandItem:anchor do:[anchor expand]
+ ]
+ ]
! !
!SelectionInTree methodsFor:'adding & removing'!
@@ -217,93 +278,188 @@
"
"add a node or collection of nodes to after a child
"
- aChild notNil ifTrue:[
- aChild parent add:something after:aChild.
- self recomputeList
+ |p|
+
+ (aChild notNil and:[(p := aChild parent) notNil]) ifTrue:[
+ self add:something afterIndex:(p indexOfChild:aChild) below:p
]
+
!
add:something afterIndex:anIndex below:aParent
"add a node or collection of nodes to parent after an index
"
- aParent add:something afterIndex:anIndex.
- self recomputeList
-
+ self add:something beforeIndex:(anIndex + 1) below:aParent
!
add:something before:aChild
"add a node or collection of nodes to before a child
"
- aChild notNil ifTrue:[
- aChild parent add:something before:aChild.
- self recomputeList
+ |p|
+
+ (aChild notNil and:[(p := aChild parent) notNil]) ifTrue:[
+ self add:something beforeIndex:(p indexOfChild:aChild) below:p
]
!
add:something beforeIndex:anIndex below:aParent
"add a node or collection of nodes to parent before an index
"
- aParent add:something beforeIndex:anIndex.
- self recomputeList
+ |children start index size pList|
+
+ ( aParent isNil
+ or:[something isNil
+ or:[(something isCollection and:[something isEmpty])]]
+ ) ifTrue:[
+ ^ self
+ ].
+
+ (start := self indexOf:aParent) == 0 ifTrue:[
+ "/
+ "/ parent not visible; list not changed
+ "/
+ aParent add:something beforeIndex:anIndex.
+ ^ self
+ ].
+
+ aParent shown ifFalse:[
+ aParent add:something beforeIndex:anIndex.
+ self changed:#at: with:start.
+ ^ self
+ ].
+ children := aParent children.
+
+ (children isEmpty or:[anIndex <= 1]) ifTrue:[
+ index := 1.
+ ] ifFalse:[
+ size := children size.
+
+ anIndex > size ifTrue:[
+ index := size + 1.
+ start := aParent numberOfAllVisibleChildren + start.
+ ] ifFalse:[
+ index := anIndex.
+ start := (self indexOf:(children at:index)) - 1.
+ ]
+ ].
+ aParent add:something beforeIndex:index.
+
+ (start := start + 1) == 0 ifTrue:[
+ "/
+ "/ not visible
+ "/
+ ^ self
+ ].
+ pList := OrderedCollection new:2048.
+
+ self each:something do:[:aNode|
+ pList add:aNode.
+ aNode addVisibleChildrenTo:pList
+ ].
+ pList isEmpty ifTrue:[
+ ^ self
+ ].
+ list addAll:pList beforeIndex:start.
+
+ self changed:#insertCollection:
+ with:(Array with:start with:pList size with:aParent).
!
add:something below:aParent
"add a node or collection of nodes to parent
"
- aParent add:something.
- self recomputeList
-
+ aParent notNil ifTrue:[
+ self add:something beforeIndex:(aParent numberOfChildren + 1) below:aParent
+ ]
!
remove:something
"remove a node or collection of nodes
"
- |invalidate|
+ |node coll index loNums loItem start size parent|
+
+ something isNil ifTrue:[
+ ^ something
+ ].
+ loNums := SortedCollection new.
+
+ self each:something do:[:el|
+ node := el isNumber ifTrue:[list at:el ifAbsent:nil]
+ ifFalse:[el].
+
+ node notNil ifTrue:[
+ self stopIndicatorValidationFor:node.
- self each:something do:[:aNode|
- self stopIndicatorValidationFor:aNode.
+ node parent isNil ifTrue:[
+ "/ remove all including root
+ node == root ifTrue:[ self root:nil ].
+ ^ something
+ ].
+ index := self indexOf:node.
- aNode parent notNil ifTrue:[
- aNode parent remove:aNode.
- invalidate := true
+ index == 0 ifTrue:[
+ "/ not visible
+ node parent removeChild:node
+ ] ifFalse:[
+ loNums add:index
+ ].
]
].
- invalidate == true ifTrue:[self recomputeList].
- ^ something
+
+ loNums isEmpty ifTrue:[
+ "/ nothing visible changed
+ ^ something
+ ].
+ loItem := OrderedCollection new.
+ loNums do:[:i| loItem add:(list at:i)].
+
+ loItem do:[:aNode|
+ start := self indexOf:aNode.
+
+ start ~~ 0 ifTrue:[
+ parent := aNode parent.
+ size := 1 + aNode numberOfAllVisibleChildren.
+ parent remove:aNode.
+ list removeFromIndex:start toIndex:(start + size - 1).
+ self changed:#removeFrom:
+ with:(Array with:start with:size with:parent).
+ ]
+ ].
+ ^ something
+!
+
+removeAllOtherThanRoot
+ "remove all other than the root
+ "
+ |listChanged|
+
+ root notNil ifTrue:[
+ listChanged := root isCollapsable.
+ root children:(OrderedCollection new).
+
+ listChanged ifTrue:[
+ self listFromRoot.
+ self changed:#list
+ ]
+ ]
!
removeIndex:something
"remove a node at index or collection of indexed nodes
"
- |invalidate node|
-
- something isCollection ifFalse:[
- (something isNil or:[something == 0]) ifFalse:[
- ^ self remove:(list at:something)
- ].
- ^ nil
- ].
-
- (SortedCollection withAll:something) reverseDo:[:anIndex|
- node := list at:anIndex.
- self stopIndicatorValidationFor:node.
-
- node parent notNil ifTrue:[
- node parent remove:node.
- invalidate := true
- ]
- ].
- invalidate == true ifTrue:[self recomputeList].
-
+ self remove:something
!
removeSelection
"remove selected nodes
"
- self removeIndex:(self selectionIndex).
- self selectionIndex:nil
+ |sel|
+
+ sel := self selectionIndex.
+ self selectionIndex:nil.
+ self remove:sel.
! !
!SelectionInTree methodsFor:'change & update'!
@@ -356,15 +512,91 @@
recomputeList
"Travers the tree and build a new list."
+ self listFromRoot.
+ self changed:#list.
+! !
+
+!SelectionInTree methodsFor:'private hierarchy'!
+
+collapseItem:anItem do:collapseBlock
+ "collapse all children under an item; raise a notification if
+ the list changed
+ "
+ |start stop size|
+
+ anItem isCollapsable ifFalse:[
+ ^ self
+ ].
+
+ (start := self indexOf:anItem) == 0 ifTrue:[
+ "/
+ "/ item not visible
+ "/
+ collapseBlock value.
+ ] ifFalse:[
+ size := anItem numberOfAllVisibleChildren.
+ collapseBlock value.
+
+ size == 0 ifTrue:[
+ "/
+ "/ no children before; list not changed
+ "/
+ self changed:#at: with:start
+ ] ifFalse:[
+ stop := start + size.
+ start := start + 1.
+ list removeFromIndex:start toIndex:stop.
+ self changed:#removeFrom: with:(Array with:start with:size with:anItem).
+ ]
+ ]
+!
+
+expandItem:anItem do:expandBlock
+ "expand all children under an item; raise a notification if
+ the list changed
+ "
+ |start size pList|
+
+ anItem isExpandable ifFalse:[
+ ^ self
+ ].
+ expandBlock value.
+
+ (start := self indexOf:anItem) ~~ 0 ifTrue:[
+ anItem addVisibleChildrenTo:(pList := OrderedCollection new:2048).
+
+ (size := pList size) ~~ 0 ifTrue:[
+ start := 1 + start.
+ list addAll:pList beforeIndex:start.
+
+ self changed:#insertCollection:
+ with:(Array with:start with:size with:anItem).
+ ] ifFalse:[
+ self changed:#at: with:start
+ ]
+ ]
+!
+
+listFromRoot
+ "Travers the tree and build a new list;
+ no change notification is raised
+ "
list clearContents.
root notNil ifTrue:[
- showRoot ifTrue:[
- list add:root
- ].
- root recomputeList:list.
- ].
- self changed:#list.
+ showRoot ifTrue:[ list add:root ].
+ root addVisibleChildrenTo:list
+ ]
+
+! !
+
+!SelectionInTree methodsFor:'queries'!
+
+indexOf:anItem
+ "returns the index of an item or 0
+ "
+ ^ anItem notNil ifTrue:[list identityIndexOf:anItem]
+ ifFalse:[0]
! !
!SelectionInTree methodsFor:'searching'!
@@ -396,6 +628,35 @@
!SelectionInTree methodsFor:'selection'!
+selectedNodes
+ "returns list of selected nodes or nil
+ "
+ |node coll|
+
+ selection isNil ifTrue:[
+ ^ nil
+ ].
+
+ selection isCollection ifFalse:[
+ node := list at:selection ifAbsent:nil.
+ ^ node notNil ifTrue:[Array with:node] ifFalse:[nil]
+ ].
+
+ selection isEmpty ifTrue:[
+ ^ nil
+ ].
+
+ coll := OrderedCollection new:(selection size).
+
+ selection do:[:idx|
+ (node := list at:idx ifAbsent:nil) notNil ifTrue:[
+ coll add:node
+ ]
+ ].
+ ^ coll notEmpty ifTrue:[coll] ifFalse:[nil]
+
+!
+
selection
"get the selection or nil
"
@@ -522,5 +783,5 @@
!SelectionInTree class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libwidg2/SelectionInTree.st,v 1.12 1998-04-09 11:37:54 ca Exp $'
+ ^ '$Header: /cvs/stx/stx/libwidg2/SelectionInTree.st,v 1.13 1998-04-14 11:32:54 ca Exp $'
! !