"
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.
"
ToolApplicationModel subclass:#HierarchicalListEditor
instanceVariableNames:'isModified didInstall treeView specClass specSelector'
classVariableNames:'CopyBuffer'
poolDictionaries:''
category:'Interface-UIPainter'
!
!HierarchicalListEditor 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
"
HierarchicalListEditor is used by the UIPainter to
create or maintain a hierarchical list.
[start with:]
HierarchicalListEditor open
[see also:]
UIPainter
[author:]
Claus Atzkern
"
! !
!HierarchicalListEditor class methodsFor:'interface specs'!
classAndMethodSpec
"this window spec was automatically generated by the ST/X UIPainter"
"do not manually edit this - the painter/builder may not be able to
handle the specification if its corrupted."
"
UIPainter new openOnClass:HierarchicalListEditor andSelector:#classAndMethodSpec
HierarchicalListEditor new openInterface:#classAndMethodSpec
"
<resource: #canvas>
^
#(#FullSpec
#'window:'
#(#WindowSpec
#'name:' 'Painter'
#'layout:' #(#LayoutFrame 233 0 430 0 533 0 558 0)
#'label:' 'Painter'
#'min:' #(#Point 10 10)
#'max:' #(#Point 1160 870)
#'bounds:' #(#Rectangle 233 430 534 559)
#'usePreferredExtent:' false
)
#'component:'
#(#SpecCollection
#'collection:'
#(
#(#LabelSpec
#'name:' 'boxLabel'
#'layout:' #(#Point 5 10)
#'label:' 'Class and selector for code:'
#'adjust:' #left
#'resizeForLabel:' true
)
#(#LabelSpec
#'name:' 'classLabel'
#'layout:' #(#AlignmentOrigin 45 0.11 51 0 1 0.5)
#'label:' 'Class:'
#'adjust:' #right
#'resizeForLabel:' true
)
#(#InputFieldSpec
#'name:' 'classField'
#'layout:' #(#LayoutFrame 47 0.11 39 0 -2 1.0 61 0)
#'tabable:' true
#'model:' #specClassChannel
)
#(#LabelSpec
#'name:' 'methodLabel'
#'layout:' #(#AlignmentOrigin 45 0.11 74 0 1 0.5)
#'label:' 'Selector:'
#'adjust:' #right
#'resizeForLabel:' true
)
#(#InputFieldSpec
#'name:' 'methodField'
#'layout:' #(#LayoutFrame 47 0.11 64 0 -2 1.0 86 0)
#'tabable:' true
#'model:' #specSelectorChannel
#'type:' #string
)
#(#UISubSpecification
#'name:' 'SubSpecification'
#'layout:' #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1.0)
#'majorKey:' #ToolApplicationModel
#'minorKey:' #windowSpecForCommitWithoutChannels
)
)
)
)
!
menu
"this window spec was automatically generated by the ST/X MenuEditor"
"do not manually edit this - the builder may not be able to
handle the specification if its corrupted."
"
MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menu
(Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#'label:' 'About'
#'labelImage:' #(#ResourceRetriever nil #icon)
#'submenuChannel:' #menuAbout
)
#(#MenuItem
#'label:' 'File'
#'submenu:'
#(#Menu
#(
#(#MenuItem
#'label:' 'New'
#'value:' #doNew
)
#(#MenuItem
#'label:' 'Reload'
#'value:' #doReload
)
#(#MenuItem
#'label:' '-'
)
#(#MenuItem
#'label:' 'Save'
#'value:' #doInstall
#'enabled:' #hasValidClass
)
#(#MenuItem
#'label:' '-'
)
#(#MenuItem
#'label:' 'Define Selector...'
#'value:' #doDefineSelector
#'enabled:' #hasValidClass
)
#(#MenuItem
#'label:' 'Define Class...'
#'value:' #doDefineClass
#'enabled:' #canChangeClassName
)
#(#MenuItem
#'label:' '-'
)
#(#MenuItem
#'label:' 'Exit'
#'value:' #closeRequest
)
) nil
nil
)
)
#(#MenuItem
#'label:' 'Edit'
#'submenuChannel:' #menuEdit
)
#(#MenuItem
#'label:' 'Browse'
#'enabled:' #hasValidClass
#'submenu:'
#(#Menu
#(
#(#MenuItem
#'label:' 'Class'
#'value:' #'doBrowse:'
#'argument:' #class
)
#(#MenuItem
#'label:' 'Method'
#'value:' #'doBrowse:'
#'enabled:' #hasValidMethodSelector
#'argument:' #method
)
#(#MenuItem
#'label:' 'Specification'
#'value:' #'doBrowse:'
#'enabled:' #hasValidSpecSelector
#'argument:' #spec
)
) nil
nil
)
)
) nil
nil
)
!
menuEdit
"this window spec was automatically generated by the ST/X MenuEditor"
"do not manually edit this - the builder may not be able to
handle the specification if its corrupted."
"
MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menuEdit
(Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menuEdit)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#'label:' 'Cut'
#'value:' #doCut
#'enabled:' #canCut
)
#(#MenuItem
#'label:' 'Copy'
#'value:' #doCopy
#'enabled:' #canCopy
)
#(#MenuItem
#'label:' 'Paste'
#'value:' #doPaste
#'enabled:' #canPaste
)
#(#MenuItem
#'label:' '-'
)
#(#MenuItem
#'label:' 'Create Child'
#'value:' #doCreateChild
#'enabled:' #canCreateChildChannel
#'labelImage:' #(#ResourceRetriever #HierarchicalListEditor #iconCreateChild)
)
#(#MenuItem
#'label:' 'Create Sister'
#'value:' #doCreateSister
#'enabled:' #canCreateSisterChannel
#'labelImage:' #(#ResourceRetriever #HierarchicalListEditor #iconCreateSister)
)
) nil
nil
)
!
menuToolbar
"this window spec was automatically generated by the ST/X MenuEditor"
"do not manually edit this - the builder may not be able to
handle the specification if its corrupted."
"
MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menuToolbar
(Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menuToolbar)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#'label:' 'New'
#'isButton:' true
#'value:' #doNew
#'enabled:' #canCreateChildChannel
#'labelImage:' #(#ResourceRetriever nil #newIcon)
)
#(#MenuItem
#'label:' 'Save'
#'isButton:' true
#'value:' #doInstall
#'enabled:' #canCreateChildChannel
#'labelImage:' #(#ResourceRetriever nil #saveIcon)
)
#(#MenuItem
#'label:' ''
)
#(#MenuItem
#'label:' 'Create Child'
#'isButton:' true
#'value:' #doCreateChild
#'enabled:' #canCreateChildChannel
#'labelImage:' #(#ResourceRetriever nil #createChildIcon)
)
#(#MenuItem
#'label:' 'Create Sister'
#'isButton:' true
#'value:' #doCreateSister
#'enabled:' #canCreateSisterChannel
#'labelImage:' #(#ResourceRetriever nil #createSisterIcon)
)
#(#MenuItem
#'label:' ''
)
#(#MenuItem
#'label:' 'Step Up'
#'isButton:' true
#'value:' #doStepUp
#'enabled:' #canStepOverChannel
#'labelImage:' #(#ResourceRetriever nil #upIcon)
)
#(#MenuItem
#'label:' 'Step Down'
#'isButton:' true
#'value:' #doStepDown
#'enabled:' #canStepOverChannel
#'labelImage:' #(#ResourceRetriever nil #downIcon)
)
#(#MenuItem
#'label:' 'Step In'
#'isButton:' true
#'value:' #doStepIn
#'enabled:' #canStepInChannel
#'labelImage:' #(#ResourceRetriever nil #downRightIcon)
)
#(#MenuItem
#'label:' 'Step Out'
#'isButton:' true
#'value:' #doStepOut
#'enabled:' #canStepOutChannel
#'labelImage:' #(#ResourceRetriever nil #leftDownIcon)
)
) nil
nil
)
!
methodSpec
"this window spec was automatically generated by the ST/X UIPainter"
"do not manually edit this - the painter/builder may not be able to
handle the specification if its corrupted."
"
UIPainter new openOnClass:HierarchicalListEditor andSelector:#methodSpec
HierarchicalListEditor new openInterface:#methodSpec
"
<resource: #canvas>
^
#(#FullSpec
#'window:'
#(#WindowSpec
#'name:' 'Painter'
#'layout:' #(#LayoutFrame 151 0 377 0 431 0 455 0)
#'label:' 'Painter'
#'min:' #(#Point 10 10)
#'max:' #(#Point 1160 870)
#'bounds:' #(#Rectangle 151 377 432 456)
#'usePreferredExtent:' false
)
#'component:'
#(#SpecCollection
#'collection:'
#(
#(#LabelSpec
#'name:' 'boxLabel'
#'layout:' #(#LayoutFrame 0 0.0 3 0 0 1.0 20 0)
#'label:' 'Selector for code:'
#'adjust:' #left
#'resizeForLabel:' true
)
#(#InputFieldSpec
#'name:' 'methodField'
#'layout:' #(#LayoutFrame 0 0.0 22 0 0 1.0 44 0)
#'tabable:' true
#'model:' #specSelectorChannel
#'type:' #string
)
#(#UISubSpecification
#'name:' 'SubSpecification'
#'layout:' #(#LayoutFrame 0 0.0 -29 1 0 1.0 -5 1.0)
#'majorKey:' #ToolApplicationModel
#'minorKey:' #windowSpecForCommitWithoutChannels
)
)
)
)
!
windowSpec
"this window spec was automatically generated by the ST/X UIPainter"
"do not manually edit this - the painter/builder may not be able to
handle the specification if its corrupted."
"
UIPainter new openOnClass:HierarchicalListEditor andSelector:#windowSpec
HierarchicalListEditor new openInterface:#windowSpec
"
"HierarchicalListEditor open"
<resource: #canvas>
^
#(#FullSpec
#'window:'
#(#WindowSpec
#'name:' 'Hierarchical List Editor'
#'layout:' #(#LayoutFrame 195 0 319 0 669 0 631 0)
#'label:' 'Hierarchical List Editor'
#'min:' #(#Point 10 10)
#'max:' #(#Point 1160 870)
#'bounds:' #(#Rectangle 195 319 670 632)
#'menu:' #menu
#'usePreferredExtent:' false
)
#'component:'
#(#SpecCollection
#'collection:'
#(
#(#MenuPanelSpec
#'name:' 'menuToolbarView'
#'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 32 0)
#'menu:' #menuToolbar
)
#(#VariableHorizontalPanelSpec
#'name:' 'variableHorizontalPanel'
#'layout:' #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -22 1.0)
#'component:'
#(#SpecCollection
#'collection:'
#(
#(#ArbitraryComponentSpec
#'name:' 'treeView'
#'menu:' #menuEdit
#'hasHorizontalScrollBar:' true
#'hasVerticalScrollBar:' true
#'miniScrollerHorizontal:' true
#'miniScrollerVertical:' true
#'component:' #treeView
#'hasBorder:' false
)
#(#ViewSpec
#'name:' 'specView'
#'component:'
#(#SpecCollection
#'collection:'
#(
#(#LabelSpec
#'name:' 'nameLabel'
#'layout:' #(#AlignmentOrigin 107 0 25 0 1 0.5)
#'label:' 'Name:'
#'resizeForLabel:' true
)
#(#InputFieldSpec
#'name:' 'nameInputField'
#'layout:' #(#LayoutFrame 110 0 15 0 -5 1.0 37 0)
#'tabable:' true
#'model:' #itemName
)
#(#LabelSpec
#'name:' 'valueLabel'
#'layout:' #(#AlignmentOrigin 107 0 51 0 1 0.5)
#'label:' 'Value:'
#'resizeForLabel:' true
)
#(#InputFieldSpec
#'name:' 'valueInputField'
#'layout:' #(#LayoutFrame 110 0 41 0 -5 1.0 63 0)
#'tabable:' true
#'model:' #itemValue
#'type:' #symbolOrNil
)
#(#UISubSpecification
#'name:' 'SubSpecification'
#'layout:' #(#LayoutFrame 2 0.0 -26 1.0 -2 1.0 -2 1.0)
#'majorKey:' #ToolApplicationModel
#'minorKey:' #windowSpecForCommit
)
)
)
#'level:' -1
)
)
)
#'handles:' #(#Any 0.368421 1.0)
)
#(#LabelSpec
#'name:' 'infoLabel'
#'layout:' #(#LayoutFrame 0 0.0 -22 1 -80 1.0 0 1.0)
#'labelChannel:' #valueOfInfoLabel
#'level:' 1
#'adjust:' #left
)
#(#LabelSpec
#'name:' 'timeLabel'
#'layout:' #(#LayoutFrame -80 1 -22 1 0 1.0 0 1.0)
#'labelChannel:' #valueOfTimeLabel
#'level:' 1
#'adjust:' #right
)
)
)
)
! !
!HierarchicalListEditor class methodsFor:'printing'!
prettyPrintArray:anArray on:aStream indent:anIndent
"print a literal array in a nice format
"
|arg sol|
sol := aStream position.
aStream spaces:anIndent.
aStream nextPutAll:'#('.
anArray first isSymbol ifTrue:[
arg := anArray first.
aStream nextPut:$#.
aStream nextPutAll:anArray first.
aStream cr.
anArray size == 2 ifTrue:[
self prettyPrintArray:(anArray last)
on:aStream
indent:(anIndent + 4).
].
aStream spaces:anIndent.
aStream nextPut:$).
^ self
].
aStream nextPut:$'.
aStream nextPutAll:(anArray at:1).
aStream nextPut:$'.
arg := anArray at:2 ifAbsent:nil.
arg isString ifTrue:[
aStream spaces:((50 - (aStream position - sol)) max:4).
arg isSymbol ifTrue:[
aStream nextPut:$#.
].
aStream nextPut:$'.
aStream nextPutAll:arg.
aStream nextPut:$'.
arg := anArray at:3 ifAbsent:nil.
].
arg isArray ifTrue:[
aStream nextPutAll:' #('.
aStream cr.
arg do:[:e|self prettyPrintArray:e on:aStream indent:(anIndent + 4)].
aStream spaces:anIndent.
aStream nextPut:$).
].
aStream nextPut:$).
aStream cr.
! !
!HierarchicalListEditor class methodsFor:'resources'!
createChildIcon
"ImageEditor openOnClass:self andSelector:#createChildIcon"
<resource: #image>
^(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(#[0 0 0 0 0 0 5 85 85 85 0 0 7 255 255 255 32 0 7 255 255 255 40 0 7 255 255 255 0 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 204 204 207 14 0 7 60 204 207 50 0 7 60 12 207 50 0 7 60 204 207 50 0 7 204 204 195 14 0 7 255 255 255 254 0 14 170 170 170 170 0 0 0 0 0 0 0]) ; colorMap:(((Array new:4) at:1 put:((Color black)); at:2 put:((Color white)); at:3 put:((Color grey:49.9962)); at:4 put:((Color grey:66.9978)); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(#[127 255 128 127 255 192 127 255 224 127 255 240 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248]) ; yourself); yourself!
createSisterIcon
"ImageEditor openOnClass:self andSelector:#createSisterIcon"
<resource: #image>
^(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(#[0 0 0 0 0 0 5 85 85 85 0 0 7 255 255 255 32 0 7 255 255 255 40 0 7 255 255 255 0 0 7 255 255 255 254 0 7 255 255 255 254 0 7 255 255 255 254 0 7 195 60 63 254 0 7 63 51 255 254 0 7 207 60 240 62 0 7 243 63 63 254 0 7 15 48 255 254 0 7 255 255 255 254 0 7 3 3 15 254 0 7 207 63 51 254 0 7 207 3 15 254 0 7 207 63 51 254 0 7 207 3 51 254 0 7 255 255 255 254 0 14 170 170 170 170 0 0 0 0 0 0 0]) ; colorMap:(((Array new:4) at:1 put:((Color black)); at:2 put:((Color white)); at:3 put:((Color grey:49.9962)); at:4 put:((Color grey:66.9978)); yourself)); mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(#[127 255 128 127 255 192 127 255 224 127 255 240 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248 127 255 248]) ; yourself); yourself! !
!HierarchicalListEditor methodsFor:'accessing'!
didInstall
"returns true if spec was installed by operator"
^didInstall ? false
!
selectorName
"returns current spec. selector"
^specSelector
! !
!HierarchicalListEditor methodsFor:'aspects'!
canCreateChildChannel
"automatically generated by UIPainter ..."
^builder booleanValueAspectFor:#canCreateChildChannel
!
canCreateSisterChannel
"automatically generated by UIPainter ..."
^builder booleanValueAspectFor:#canCreateSisterChannel
!
canStepInChannel
"automatically generated by UIPainter ..."
^builder booleanValueAspectFor:#canStepInChannel
!
canStepOutChannel
"automatically generated by UIPainter ..."
^builder booleanValueAspectFor:#canStepOutChannel
!
canStepOverChannel
"automatically generated by UIPainter ..."
^builder booleanValueAspectFor:#canStepOverChannel
!
itemName
"automatically generated by UIPainter ..."
|holder|
(holder := builder bindingAt:#itemName) isNil ifTrue:[
builder aspectAt:#itemName put:(holder := ValueHolder new).
holder addDependent:self.
].
^ holder
!
itemValue
"automatically generated by UIPainter ..."
|holder|
(holder := builder bindingAt:#itemValue) isNil ifTrue:[
builder aspectAt:#itemValue put:(holder := ValueHolder new).
holder addDependent:self.
].
^ holder
!
treeView
"automatically generated by UIPainter ..."
^treeView
! !
!HierarchicalListEditor methodsFor:'change & update'!
update:something with:aParameter from:someObject
"one of my models changed"
self valueOfEnablingCommitButtons value: true
! !
!HierarchicalListEditor methodsFor:'private'!
checkMenuItemModified
"check item modification"
self valueOfEnablingCommitButtons value
ifTrue:
[
((YesNoBox title:'Item was modified!!\Save it?\' withCRs)
noText:'No';
yesText:'Yes';
showAtPointer;
accepted) ifFalse: [self valueOfEnablingCommitButtons value: false. ^true].
self accept
].
^true
!
newItem
"creates and returns a new default item"
^TreeItem name: 'Undefined' contents: nil
!
updateChannels
"update channels"
|node parent chnStepIn chnStepOut chnStepOvr chnChild chnSister|
chnStepIn := chnStepOut := chnStepOvr := chnChild := chnSister := false.
(node := treeView selectedNode) notNil
ifTrue:
[
(builder componentAt: #specView) beVisible.
chnChild := true.
(parent := node parent) notNil
ifTrue:
[
chnSister := true.
chnStepOvr := parent numberOfChildren > 1.
chnStepOut := parent parent notNil.
chnStepIn := node ~~ parent lastChild
]
]
ifFalse:
[
(builder componentAt: #specView) beInvisible
].
self canCreateChildChannel value:chnChild.
self canCreateSisterChannel value:chnSister.
self canStepOverChannel value:chnStepOvr.
self canStepOutChannel value:chnStepOut.
self canStepInChannel value:chnStepIn
!
updateInputFields
"reload item value into input fields"
|node|
(node := treeView selectedNode) notNil
ifTrue:
[
self itemName value:node name.
self itemValue value:node contents
]
ifFalse:
[
self itemName value:''.
self itemValue value:nil
].
self valueOfEnablingCommitButtons value: false
! !
!HierarchicalListEditor methodsFor:'queries'!
canChangeClassName
"returns true if current class could be changed which is dependent on
the mode: standalone or started by UIPainter"
^masterApplication isNil
!
canCopy
"returns true if any selection exists"
^treeView selection notNil
!
canCut
"returns true if any selection exists and not includes
the anchor (first element into list)."
treeView selection notNil ifTrue:[^(treeView isInSelection:1) not].
^false
!
canPaste
"returns true if something to be paste exists and a
single selection exists"
^CopyBuffer notNil and:[treeView selectedNode notNil]
!
hasValidClass
"returns true if the class defined allready exists"
^specClass isBehavior
!
hasValidMethodSelector
"returns true if the class and the instance selector defined
allready exists."
(specSelector notNil and:[self hasValidClass])
ifTrue:
[
^(specClass compiledMethodAt:specSelector) notNil
].
^false
!
hasValidSpecSelector
"returns true if the class and the class selector defined
allready exists."
(specSelector notNil and:[self hasValidClass])
ifTrue:
[
^(specClass class compiledMethodAt:specSelector) notNil
].
^false
! !
!HierarchicalListEditor methodsFor:'startup / release'!
buildFrom:aClass andSelector:aSelector
"rebuild window from a class and selector"
|sel anchor|
specClass := self resolveName:aClass.
specSelector := nil.
aSelector size ~~ 0
ifTrue:
[
sel := aSelector asString withoutSeparators.
sel size ~~ 0 ifTrue:[specSelector := sel asSymbol]
].
treeView selection:nil.
(specSelector notNil and:[specClass notNil])
ifTrue:
[
(specClass respondsTo:specSelector)
ifTrue:
[
anchor := specClass perform:specSelector.
anchor isArray ifTrue:[anchor := anchor decodeAsLiteralArray]
]
].
anchor notNil
ifTrue: [anchor expand. treeView root:anchor]
ifFalse:[self doNew]
!
initialize
"setup default values"
super initialize.
treeView := SelectionInTreeView new.
treeView multipleSelectOk: true.
treeView showDirectoryIndicator: true.
treeView showDirectoryIndicatorForRoot: false.
treeView action:[:aNr| self updateChannels. self updateInputFields].
treeView selectConditionBlock: [:i|self checkMenuItemModified].
treeView validateDoubleClickBlock: [:node| node ~~ treeView model list first].
self doNew.
!
openModalOnClass:aClass andSelector:aSelector
"open modal on class and selector"
specClass := Association key:aClass value:aSelector.
super openInterfaceModal.
!
openOnClass:aClass andSelector:aSelector
"open on class and selector"
specClass := Association key:aClass value:aSelector.
super openInterface.
!
postBuildWith:builder
"setup view"
|cls sel|
specClass isAssociation ifTrue:[
cls := specClass key.
sel := specClass value.
].
self buildFrom:cls andSelector:sel.
! !
!HierarchicalListEditor methodsFor:'user actions'!
accept
"invoked by button 'OK'"
|node index|
(index := treeView selectedIndex) ~~ 0
ifTrue:
[
node := treeView nodeAtIndex:index.
node name: self itemName value.
node contents: self itemValue value.
treeView redrawLine:index.
].
self valueOfEnablingCommitButtons value: false
!
cancel
"invoked by button 'Cancel'"
self updateInputFields.
self valueOfEnablingCommitButtons value: false
!
doBrowse:what
"open a system browser"
|cls sel|
(cls := specClass) notNil
ifTrue:
[
what == #class
ifFalse:
[
(sel := specSelector) isNil ifTrue:[^self].
what == #spec ifTrue:[cls := cls class]
].
SystemBrowser openInClass:cls selector:sel
]
!
doCopy
"copy current selected nodes into copy buffer"
CopyBuffer := OrderedCollection new.
treeView selectedNodesDo:[:aNode| CopyBuffer add: aNode copy]
!
doCreateChild
"create a child within selected parent"
|node|
(node := treeView selectedNode) notNil
ifTrue:
[
treeView model add: self newItem beforeIndex:1 below:node.
treeView selectedNodeExpand:true.
self updateChannels.
]
!
doCreateSister
"create a sister next to selected item
"
|node|
(node := treeView selectedNode) notNil
ifTrue:
[
node parent notNil
ifTrue: [treeView model add: self newItem after:node]
ifFalse:[treeView model add: self newItem beforeIndex:1 below:node].
self updateChannels
]
!
doCut
"cut current selected nodes"
|selection|
treeView hasSelection
ifTrue:
[
self doCopy.
selection := treeView selection asSortedCollection.
treeView selectedNodesRemove.
treeView selection: selection first - 1.
self updateChannels
]
!
doDefineClass
"define class and selector"
|sel cls bindings accepted|
masterApplication notNil ifTrue:[^self information:'Only selector can be changed.'].
accepted := true.
bindings := IdentityDictionary new.
specClass notNil ifTrue:[cls := specClass name asString]
ifFalse:[cls := ''].
specSelector notNil ifTrue:[sel := specSelector asString]
ifFalse:[sel := ''].
bindings at:#specSelectorChannel put: sel asValue.
bindings at:#specClassChannel put: cls asValue.
[accepted]
whileTrue:
[
(accepted := self openDialogInterface:#classAndMethodSpec withBindings:bindings)
ifTrue:
[
(cls := self resolveName:(bindings at:#specClassChannel) value) notNil
ifTrue:
[
(sel := (bindings at:#specSelectorChannel) value withoutSeparators) size ~~ 0
ifTrue:
[
specClass := cls.
specSelector := sel asSymbol.
^self
]
]
]
]
!
doDefineSelector
"define selector only"
|sel bindings accepted|
accepted := true.
bindings := IdentityDictionary new.
specSelector notNil ifTrue:[sel := specSelector asString]
ifFalse:[sel := ''].
bindings at:#specSelectorChannel put:(sel asValue).
[accepted]
whileTrue:
[
(accepted := self openDialogInterface:#methodSpec withBindings:bindings)
ifTrue:
[
(sel := (bindings at:#specSelectorChannel) value withoutSeparators) size ~~ 0
ifTrue:
[
specSelector := sel asSymbol.
^self
]
]
]
!
doInstall
"install code"
|code spec category mthd stream|
(specClass notNil and:[specSelector notNil])
ifFalse:
[
^self information:'No valid class and method defined!!'
].
spec := (treeView nodeAtIndex:1) literalArrayEncoding.
stream := WriteStream on:String new.
self class prettyPrintArray:spec on:stream indent:4.
spec := stream contents.
category := 'interface specs'.
didInstall := true.
(mthd := specClass class compiledMethodAt:specSelector) notNil
ifTrue:
[
category := mthd category
].
code := Character excla asString
, specClass name , ' class methodsFor:' , category storeString
, Character excla asString , '\\'
, specSelector , '\'
, ' "this window spec was automatically generated by the ST/X HierarchicalListEditor"\\'
, ' "do not manually edit this - the builder may not be able to\'
, ' handle the specification if its corrupted."\\'
, ' "\'
, ' HierarchicalListEditor new openOnClass:' , specClass name , ' andSelector:#' , specSelector , '\'
, ' "\'.
code := code
, '\'
, ' <resource: #hierarchicalList>\\'
, ' ^\'
, spec
, ' decodeAsLiteralArray\'
, Character excla asString
, ' '
, Character excla asString
, '\\'.
code := code withCRs.
(ReadStream on:code) fileIn.
(specClass compiledMethodAt:specSelector) isNil
ifTrue:
[
category := 'aspects'.
code := Character excla asString
, specClass name , ' methodsFor:' , category storeString
, Character excla asString , '\\'
, specSelector , '\'
, ' "this window spec was automatically generated by the ST/X HierarchicalListEditor"\\'
, ' ^ self class ', specSelector
, '\'
, Character excla asString
, ' '
, Character excla asString
, '\\'.
code := code withCRs.
(ReadStream on:code) fileIn
]
!
doNew
"remove all items; restart"
treeView root:(TreeItem name:'Anchor' contents:#anchor).
treeView selection:0
!
doPaste
"paste after current selected item"
treeView selectedNodeAdd:CopyBuffer.
self updateChannels
!
doReload
"reload spec from current class and selector"
self buildFrom:specClass andSelector:specSelector
!
doStepDown
"move selected item after next item"
treeView selectedNodeChangeSequenceOrder:1.
self updateChannels
!
doStepIn
"lets become the selected item a child of its next sister"
treeView selectedNodeBecomeChildOfNext.
self updateChannels
!
doStepOut
"let selected node become a sister of its current parent"
treeView selectedNodeBecomeSisterOfParent.
self updateChannels
!
doStepUp
"move selected item before previous item"
treeView selectedNodeChangeSequenceOrder:-1.
self updateChannels
! !
!HierarchicalListEditor class methodsFor:'documentation'!
version
^ '$Header$'
! !