diff -r e5241f829446 -r d8e14b853cb7 SelectionInTree.st --- 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 $' ! !