TreeItem.st
author ca
Wed, 22 Oct 1997 15:26:06 +0200
changeset 569 2a1014d6697c
parent 545 d01d14358b07
child 761 d0cf8f76f1b6
permissions -rw-r--r--
checkin from browser

"
 COPYRIGHT (c) 1997 by eXept Software AG / Claus Gittinger
              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.
"




Object subclass:#TreeItem
	instanceVariableNames:'name parent children contents hide'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Support'
!

!TreeItem class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by eXept Software AG / Claus Gittinger
              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
"
    class to build up trees like structures to represent
    file-trees, class tress etc.

    Especially suited for use with SelectionInTree and
    SelectionInTreeView.

    [Author:]
        W. Olberding
        Claus Atzkern

    [See also:]
        SelectionInTree
        SelectionInTreeView

"



! !

!TreeItem class methodsFor:'instance creation'!

name:aName
    ^ self name:aName contents:nil
!

name:aName contents:aContents
    |node|

    node := self new.
    node name:aName.
    node contents:aContents.
  ^ node
!

name:aName value:aContents
    ^ self name:aName contents:aContents
!

new
    ^ self basicNew initialize
! !

!TreeItem class methodsFor:'example - instance creation'!

newAsTreeFromSmalltalkClass:aClass
    "create a tree of nodes with aClass and all its
     subclasses as contents. Set the initial level as given."

    |newInst clsName|

    aClass isNil ifTrue:[
        "/ nil subclasses requested
        clsName := 'nil'
    ] ifFalse:[
        "/ regular tree requested
        clsName := aClass name
    ].

    newInst := super new initialize.
    newInst name:clsName.

    aClass isNil ifTrue:[
        ((Smalltalk allClasses select:[:cls | cls superclass isNil])
            asSortedCollection:[:a :b | a name < b name])
        do:[:aSubClass |
            newInst add:(self newAsTreeFromSmalltalkClass:aSubClass).
        ]
    ] ifFalse:[
        (aClass subclasses asSortedCollection:[:a :b | a name < b name])
        do:[:aSubClass |
            newInst add:(self newAsTreeFromSmalltalkClass:aSubClass).
        ]
    ].
    ^newInst

"
      |top model sel root|

      root  := TreeItem newAsTreeFromSmalltalkClass:ByteArray.
      root expand.
      model := SelectionInTree new root:root.
      top := StandardSystemView new.
      top extent:300@300.

      sel := SelectionInTreeView new.
      sel model: model.
      sel action:[:nr | Transcript show:'selected:'; showCR:nr].
      top add:(ScrollableView forView:sel) in:((0.0 @ 0.0 ) corner:( 1.0 @ 1.0)).
      top open.
"
! !

!TreeItem methodsFor:'accessing'!

children
    "get's a list of children; in case that no child exists an empty
     collection is returned.
    "
    ^ children
!

children:aCollection 
    "set children
    "
    aCollection do:[:child| child parent:self ].
    children := aCollection.
!

contents
    "get contents
    "
    ^ contents
!

contents:something 
    "set contents
    "
    contents:= something
!

firstChild
    "returns first child in sequence
    "
    self numberOfChildren ~~ 0 ifTrue:[
        ^ self children first
    ].
    ^ nil
        
!

hide
    ^ hide
!

hide:aBoolean
   "Set hide flag
   "
   hide:= aBoolean
!

lastChild
    "returns last child in sequence
    "
    self numberOfChildren ~~ 0 ifTrue:[
        ^ self children last
    ].
    ^ nil
        
!

level
    "get level
    "
    parent notNil ifTrue:[^ parent level + 1].
  ^ 1
!

name
    "get name
    "
    ^ name
!

name:aString
    "set name
    "
    name := aString.
!

parent
    "get parent
    "
    ^ parent
!

parent:something
    "set parent
    "
    parent := something.
!

value
    "get contents
    "
    ^ self contents
!

value:something 
    "set contents
    "
    self contents:something
! !

!TreeItem methodsFor:'accessing hierarchy'!

childAt:anIndex
    "get child at an index or nil
    "
  ^ self children at:anIndex ifAbsent:nil
!

collapse 
    "hide all my children
    "
    hide := true
!

collapseAll 
    "hide all my children and sub children
    "
    hide ifFalse:[
        hide := true.
        self allChildrenDo:[:aChild| aChild hide:true].
    ]
!

expand
    "show all my children
    "
    hide := false.
!

expandAll 
    "show all my children and sub children
    "
    hide ifTrue:[
        hide := false.
        self allChildrenDo:[:aChild| aChild hide:false].
    ]
! !

!TreeItem methodsFor:'adding & removing'!

add:something
    "add a child or collection of children add end
    "
    self add:something beforeIndex:(self children size + 1)
!

add:something after:aChild
    "add a child or collection of children add end
    "
    self add:something afterIndex:(self indexOfChild:aChild)
!

add:something afterIndex:anIndex
    "add a child or collection after an index
    "
    self add:something beforeIndex:(anIndex + 1)
!

add:something before:aChild
    "add a child or collection of children add end
    "
    self add:something beforeIndex:(self indexOfChild:aChild)
!

removeIndex:anIndex
    "remove child at index
    "
    self remove:(self childAt:anIndex)
! !

!TreeItem methodsFor:'adding & removing basics'!

add:something beforeIndex:anIndex
    "add a child or collection before an index
    "
    |idx children|

    children := self children.

    (idx := anIndex) > children size ifTrue:[
        idx := children size + 1
    ] ifFalse:[
        idx == 0 ifTrue:[idx := 1]
    ].

    self each:something do:[:el|
        children add:el beforeIndex:idx.
        el parent:self.
        el allWithParentAndChildrenDo:[:aParent :aChild| aChild parent:aParent ].
        idx := idx + 1.
    ]
!

remove:something 
    "remove a child or collection of children
    "
    |children|

    children := self children.

    self each:something do:[:aChild|
        aChild parent:nil.
        children remove:aChild.
    ].
  ^ something
!

removeAll
    "remove all children
    "
    self childrenDo:[:aChild| aChild parent:nil ].
    self children removeAll.
! !

!TreeItem methodsFor:'converting'!

fromLiteralArrayEncoding:aLiteralEncodedArray

    |narg|

    (     (aLiteralEncodedArray size > 0)
     and:[(name := aLiteralEncodedArray at:1) isString]) ifFalse:[
        ^ nil
    ].
    narg := aLiteralEncodedArray at:2 ifAbsent:nil.

    name isSymbol ifTrue:[
        (narg isArray and:[aLiteralEncodedArray size == 2]) ifTrue:[
            ^ self fromLiteralArrayEncoding:narg
        ].
        ^ nil
    ].

    narg isArray ifFalse:[
        contents := narg.
        narg := aLiteralEncodedArray at:3 ifAbsent:nil.
    ].

    narg isArray ifTrue:[
        children := OrderedCollection new.

        narg do:[:aSubArray||aChild|
            children add:(aChild := TreeItem new).
            aChild fromLiteralArrayEncoding:aSubArray.
            aChild parent:self.
        ]
    ]



!

literalArrayEncoding

    |array childs size|

    contents isString ifTrue:[size := 2]
                     ifFalse:[size := 1].

    self numberOfChildren == 0 ifTrue:[
        array := Array new:size
    ] ifFalse:[
        array  := Array new:(size + 1).
        childs := Array new:(self numberOfChildren).
        array at:(size + 1) put:childs.

        self children keysAndValuesDo:[:i :aChild|
            childs at:i put:(aChild literalArrayEncoding)
        ]
    ].
    array at:1 put:(name ? '').

    contents isString ifTrue:[
        array at:2 put:contents
    ].
    parent isNil ifTrue:[
        array := Array with:#TreeItem with:array.
    ].
    ^ array


! !

!TreeItem methodsFor:'copy'!

copy
    |node|

    node := self species new.

    node name:(name copy).
    node contents:(contents copy).
    node children:(self children collect:[:c| c copy]).
  ^ node
! !

!TreeItem methodsFor:'enumerating'!

allChildrenDo:aOneArgBlock
    "evaluate a block on each children and subchildren
    "
    self children do:[:aChild|
        aOneArgBlock value:aChild.
        aChild allChildrenDo:aOneArgBlock
    ]
!

allWithParentAndChildrenDo:aTwoArgBlock
    self childrenDo:[:aChild|
        aTwoArgBlock value:self value:aChild.
        aChild allWithParentAndChildrenDo:aTwoArgBlock
    ]
!

childrenDo:aOneArgBlock
    "evaluate a block on each children( excluding  sub-children )
    "
    self children do:[:aChild| aOneArgBlock value:aChild ]
!

each:something do:aBlock
    "evaluate a block for something or in case of a collection for each
     element in the collection
    "
    something notNil ifTrue:[
        something isCollection ifTrue:[something do:[:el|aBlock value:el]]
                              ifFalse:[aBlock value:something]
    ]

! !

!TreeItem methodsFor:'initialize-release'!

initialize
    "setup defaults
    "
    super initialize.

    children := OrderedCollection new.
    hide     := true.
! !

!TreeItem methodsFor:'queries'!

hasChildren
    "returns true if children exists
    "
    ^ self children size ~~ 0
!

hidden
    ^ hide
!

isCollapsable
    "is collabsable; children existing and shown
    "
    ^ (self hasChildren and:[hide == false])
!

isContainedByParent:aParent
    "returns true if contained in subtree of a parent
    "
    |p|

    p := parent.

    [p notNil] whileTrue:[
        p == aParent ifTrue:[^ true ].
        p := p parent
    ].
    ^ false
!

isExpandable
    "is expandable; children existing and hidden
    "
    ^ (self hasChildren and:[hide == true])

!

numberOfChildren
    ^ self children size
!

recomputeList:aList
    "add all shown children and its shown sub children into
     a list
    "
    hide ifFalse:[
        self childrenDo:[:aChild|
            aList add:aChild.
            aChild recomputeList:aList
        ]
    ]
!

showIndicator
    ^ self hasChildren
!

shown
    ^ hide not
! !

!TreeItem methodsFor:'searching'!

detectChild:aOneArgBlock
    "evaluate the block on each child; returns the child's node
     or nil
    "
    ^ self children detect:aOneArgBlock ifNone:nil

!

indexOfChild:aChild
    "get index of a child or 0
    "
    (aChild notNil and:[self hasChildren]) ifTrue:[
        ^ self children findFirst:[:c| c == aChild ]
    ].
  ^ 0
! !

!TreeItem class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libwidg2/TreeItem.st,v 1.7 1997-10-22 13:25:39 ca Exp $'
! !