ca@300: " tz@736: COPYRIGHT (c) 1997 by eXept Software AG ca@300: All Rights Reserved ca@300: ca@300: This software is furnished under a license and may be used ca@300: only in accordance with the terms of that license and with the tz@736: inclusion of the above copyright notice. This software may not ca@300: be provided or otherwise made available to, or used by, any ca@300: other person. No title to or ownership of the software is ca@300: hereby transferred. ca@300: " ca@300: ca@300: ca@300: ca@300: cg@1499: "{ Package: 'stx:libtool2' }" cg@1499: tz@736: ResourceSpecEditor subclass:#HierarchicalListEditor tz@731: instanceVariableNames:'treeView' tz@731: classVariableNames:'' ca@300: poolDictionaries:'' ca@300: category:'Interface-UIPainter' ca@300: ! ca@300: ca@300: !HierarchicalListEditor class methodsFor:'documentation'! ca@300: ca@300: copyright ca@300: " tz@736: COPYRIGHT (c) 1997 by eXept Software AG ca@300: All Rights Reserved ca@300: ca@300: This software is furnished under a license and may be used ca@300: only in accordance with the terms of that license and with the tz@736: inclusion of the above copyright notice. This software may not ca@300: be provided or otherwise made available to, or used by, any ca@300: other person. No title to or ownership of the software is ca@300: hereby transferred. ca@300: " ca@300: ca@300: ca@300: ca@300: ! ca@300: ca@300: documentation ca@300: " tz@731: The HierarchicalListEditor allows you to create, modify or just inspect tz@731: (statical) hierarchical lists for the SelectionInListView. ca@300: ca@300: [start with:] ca@300: HierarchicalListEditor open ca@300: ca@300: [see also:] ca@300: UIPainter ca@300: ca@300: [author:] tz@546: Claus Atzkern, eXept Software AG tz@731: Thomas Zwick, eXept Software AG ca@300: " ca@300: ca@300: ca@300: ca@300: ! ! ca@300: tz@731: !HierarchicalListEditor class methodsFor:'instance creation'! tz@731: tz@731: openModalOnTreeItem: aTreeItem tz@731: "Open a HierarchicalListEditor modal on aTreeItem" tz@731: "self openModalOnTreeItem: (TreeItem name: 'Label' contents: #Contents)" tz@731: tz@731: ^self new openModalOnTreeItem: aTreeItem tz@731: tz@731: ! ! tz@731: tz@731: !HierarchicalListEditor class methodsFor:'accessing'! tz@731: tz@731: resourceType tz@731: "get the type of resource of the method generated by the HierarchicalListEditor" tz@731: tz@731: ^#hierarchicalList tz@731: tz@731: ! ! tz@731: tz@551: !HierarchicalListEditor class methodsFor:'help specs'! tz@551: tz@551: helpSpec tz@736: "This resource specification was automatically generated tz@736: by the UIHelpTool of ST/X." tz@736: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the UIHelpTool may not be able to read the specification." tz@551: tz@551: " tz@736: UIHelpTool openOnClass:HierarchicalListEditor tz@551: " tz@551: tz@736: tz@736: tz@736: ^super helpSpec addPairsFrom:#( tz@551: tz@551: #addChild tz@551: 'Adds a new child item.' tz@551: tz@551: #addSister tz@551: 'Adds a new sister item.' tz@551: tz@581: #contents tz@581: 'Contents of the tree item.' tz@581: tz@731: #fileLoad tz@731: 'Opens a dialog for selecting and loading a hierarchical list spec from a class.' tz@731: tz@551: #fileNew tz@736: 'Creates a new hierarchical list. ' tz@551: tz@731: #fileSave tz@731: 'Saves current hierarchical list spec.' tz@552: tz@731: #fileSaveAs tz@731: 'Opens a dialog to save current hierarchical list spec.' tz@552: tz@581: #label tz@581: 'Label of the tree item.' tz@581: tz@551: ) tz@551: ! ! tz@551: tz@731: !HierarchicalListEditor class methodsFor:'image specs'! ca@300: tz@731: createChildIcon tz@736: "This resource specification was automatically generated tz@736: by the ImageEditor of ST/X." tz@736: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the ImageEditor may not be able to read the specification." tz@736: ca@300: " tz@736: ImageEditor openOnClass:self andSelector:#createChildIcon ca@300: " ca@300: tz@731: tz@731: tz@731: ^Icon tz@731: constantNamed:#'HierarchicalListEditor createChildIcon' cg@1499: ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@AUUUUP@@A????2@@A????2 @A????0@@A?????8@A?????8@A?????8@A?????8@A?????8@A?????8@A?????8@A?????8@A?????8@A<3L308@A33L33H@A30L33H@A33L33H@A<3L008@A?????8@C*****(@@@@@@@@@') ; colorMapFromArray:#[0 0 0 255 255 255 127 127 127 170 170 170]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'_?>@_??@_?? _??0_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8') ; yourself); yourself] cg@1499: ! ca@300: tz@731: createSisterIcon tz@736: "This resource specification was automatically generated tz@736: by the ImageEditor of ST/X." tz@736: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the ImageEditor may not be able to read the specification." tz@736: tz@731: " tz@736: ImageEditor openOnClass:self andSelector:#createSisterIcon tz@731: " tz@731: tz@731: tz@731: tz@731: ^Icon tz@731: constantNamed:#'HierarchicalListEditor createSisterIcon' cg@1499: ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@AUUUUP@@A????2@@A????2 @A????0@@A?????8@A?????8@A?????8@A@_??@_?? _??0_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8_??8') ; yourself); yourself] cg@1499: ! ! tz@731: tz@731: !HierarchicalListEditor class methodsFor:'interface specs'! ca@300: ca@300: windowSpec tz@736: "This resource specification was automatically generated tz@736: by the UIPainter of ST/X." ca@300: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the UIPainter may not be able to read the specification." ca@300: ca@300: " ca@300: UIPainter new openOnClass:HierarchicalListEditor andSelector:#windowSpec ca@300: HierarchicalListEditor new openInterface:#windowSpec tz@736: HierarchicalListEditor open ca@300: " ca@300: ca@300: ca@300: cg@1686: ^ cg@1686: #(#FullSpec cg@1686: #name: #windowSpec cg@1686: #window: cg@1686: #(#WindowSpec cg@1686: #label: 'Hierarchical List Editor' cg@1686: #name: 'Hierarchical List Editor' cg@1686: #min: #(#Point 450 280) cg@1686: #max: #(#Point 1152 900) cg@1686: #bounds: #(#Rectangle 16 46 486 376) cg@1686: #menu: #menu cg@1686: ) cg@1686: #component: cg@1686: #(#SpecCollection cg@1686: #collection: #( cg@1686: #(#MenuPanelSpec cg@1686: #name: 'menuToolbarView' cg@1686: #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 32 0) cg@1686: #menu: #menuToolbar cg@1686: ) cg@1686: #(#VariableHorizontalPanelSpec cg@1686: #name: 'VariableHorizontalPanel' cg@1686: #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0) cg@1686: #component: cg@1686: #(#SpecCollection cg@1686: #collection: #( cg@1686: #(#ArbitraryComponentSpec cg@1686: #name: 'TreeView' cg@1686: #menu: #menuEdit cg@1686: #hasHorizontalScrollBar: true cg@1686: #hasVerticalScrollBar: true cg@1686: #miniScrollerHorizontal: true cg@1686: #miniScrollerVertical: true cg@1686: #hasBorder: false cg@1686: #component: #treeView cg@1686: ) cg@1686: #(#ViewSpec cg@1686: #name: 'SpecView' cg@1686: #level: -1 tz@731: #component: cg@1686: #(#SpecCollection cg@1686: #collection: #( cg@1686: #(#LabelSpec cg@1686: #label: 'Label:' cg@1686: #name: 'nameLabel' cg@1686: #layout: #(#AlignmentOrigin 98 0 26 0 1 0.5) cg@1686: #resizeForLabel: true cg@1875: translateLabel: true cg@1686: ) cg@1686: #(#InputFieldSpec cg@1686: #name: 'labelInputField' cg@1686: #layout: #(#LayoutFrame 100 0 15 0 -5 1.0 37 0) cg@1686: #activeHelpKey: #label cg@1686: #tabable: true cg@1686: #model: #itemName cg@1686: #acceptOnLeave: true cg@1686: #acceptOnLostFocus: true cg@1686: #acceptChannel: #acceptChannel cg@1686: #modifiedChannel: #modifiedChannel cg@1686: #acceptOnPointerLeave: true cg@1686: ) cg@1686: #(#LabelSpec cg@1686: #label: 'Contents:' cg@1686: #name: 'valueLabel' cg@1686: #layout: #(#AlignmentOrigin 98 0 52 0 1 0.5) cg@1686: #activeHelpKey: #contents cg@1686: #resizeForLabel: true cg@1875: translateLabel: true ca@300: ) cg@1686: #(#InputFieldSpec cg@1686: #name: 'valueInputField' cg@1686: #layout: #(#LayoutFrame 100 0 41 0 -5 1.0 63 0) cg@1686: #activeHelpKey: #contents cg@1686: #tabable: true cg@1686: #model: #itemValue cg@1686: #type: #smalltalkObject cg@1686: #acceptOnLeave: true cg@1686: #acceptOnLostFocus: true cg@1686: #acceptChannel: #acceptChannel cg@1686: #modifiedChannel: #modifiedChannel cg@1686: #acceptOnPointerLeave: true cg@1686: ) cg@1686: #(#UISubSpecification cg@1686: #name: 'SubSpecification' cg@1686: #layout: #(#LayoutFrame 2 0.0 -26 1.0 -2 1.0 -2 1.0) cg@1686: #majorKey: #ToolApplicationModel cg@1686: #minorKey: #windowSpecForCommit cg@1686: ) cg@1686: ) cg@1686: ca@300: ) cg@1686: ) cg@1686: ) cg@1686: ca@300: ) cg@1686: #handles: #(#Any 0.368421 1.0) cg@1686: ) cg@1686: #(#UISubSpecification cg@1686: #name: 'InfoBarSubSpec' cg@1686: #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0) cg@1686: #majorKey: #ToolApplicationModel cg@1686: #minorKey: #windowSpecForInfoBar cg@1686: ) cg@1686: ) cg@1686: cg@1686: ) ca@300: ) ca@300: ! ! ca@300: tz@506: !HierarchicalListEditor class methodsFor:'menu specs'! tz@506: tz@506: menu tz@736: "This resource specification was automatically generated tz@736: by the MenuEditor of ST/X." tz@506: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the MenuEditor may not be able to read the specification." tz@506: tz@506: " tz@506: MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menu tz@506: (Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menu)) startUp tz@506: " tz@506: tz@506: tz@506: tz@506: ^ tz@506: tz@506: #(#Menu tz@506: tz@506: #( tz@506: #(#MenuItem tz@731: #label: 'File' tz@731: #submenu: tz@506: #(#Menu tz@506: tz@506: #( tz@506: #(#MenuItem tz@731: #label: 'New' tz@731: #value: #doNew tz@731: #activeHelpKey: #fileNew tz@506: ) tz@506: #(#MenuItem tz@731: #label: '-' tz@522: ) tz@522: #(#MenuItem tz@731: #label: 'Load...' tz@731: #translateLabel: true tz@731: #value: #doLoad tz@731: #activeHelpKey: #fileLoad tz@506: ) tz@506: #(#MenuItem tz@731: #label: '-' tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Save' tz@731: #value: #doSave tz@731: #activeHelpKey: #fileSave tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Save As...' tz@731: #value: #doSaveAs tz@731: #activeHelpKey: #fileSaveAs tz@506: ) tz@506: #(#MenuItem tz@731: #label: '-' tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Browse Class' tz@731: #value: #doBrowseClass tz@731: #activeHelpKey: #fileBrowseClass tz@731: #enabled: #hasValidClass tz@581: ) tz@581: #(#MenuItem tz@731: #label: '-' tz@581: ) tz@581: #(#MenuItem tz@731: #label: 'Exit' tz@731: #value: #closeRequest tz@731: #activeHelpKey: #fileExit tz@506: ) tz@506: ) nil tz@506: nil tz@506: ) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Edit' tz@731: #submenuChannel: #menuEdit tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Add' tz@731: #submenu: tz@522: #(#Menu tz@522: tz@522: #( tz@522: #(#MenuItem tz@731: #label: 'Child' tz@731: #value: #doCreateChild tz@731: #activeHelpKey: #addChild tz@731: #enabled: #canCreateChildChannel tz@731: #labelImage: #(#ResourceRetriever #HierarchicalListEditor #createChildIcon 'Child') tz@522: ) tz@522: #(#MenuItem tz@731: #label: 'Sister' tz@731: #value: #doCreateSister tz@731: #activeHelpKey: #addSister tz@731: #enabled: #canCreateSisterChannel tz@731: #labelImage: #(#ResourceRetriever #HierarchicalListEditor #createSisterIcon 'Sister') tz@522: ) tz@522: ) nil tz@522: nil tz@522: ) tz@522: ) tz@522: #(#MenuItem tz@747: #label: 'History' tz@747: #submenuChannel: #menuHistory tz@747: ) tz@747: #(#MenuItem tz@731: #label: 'Help' tz@731: #startGroup: #right tz@731: #submenuChannel: #menuHelp tz@546: ) tz@506: ) nil tz@506: nil tz@506: ) tz@506: ! tz@506: tz@506: menuEdit tz@736: "This resource specification was automatically generated tz@736: by the MenuEditor of ST/X." tz@506: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the MenuEditor may not be able to read the specification." tz@506: tz@506: " tz@506: MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menuEdit tz@506: (Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menuEdit)) startUp tz@506: " tz@506: tz@506: tz@506: tz@506: ^ tz@506: tz@506: #(#Menu tz@506: tz@506: #( tz@506: #(#MenuItem tz@731: #label: 'Cut' tz@731: #value: #doCut tz@731: #activeHelpKey: #editCut tz@731: #enabled: #valueOfCanCut tz@731: ) tz@731: #(#MenuItem tz@731: #label: 'Copy' tz@731: #value: #doCopy tz@731: #activeHelpKey: #editCopy tz@731: #enabled: #valueOfCanCopy tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Paste' tz@731: #value: #doPaste tz@731: #activeHelpKey: #editPaste tz@731: #enabled: #valueOfCanPaste tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Delete' tz@731: #value: #doDelete tz@731: #activeHelpKey: #editPaste tz@731: #enabled: #valueOfCanCut tz@506: ) tz@506: #(#MenuItem tz@731: #label: '-' tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move Up' tz@731: #value: #doStepUp tz@731: #activeHelpKey: #editMoveUp tz@731: #enabled: #canStepOverChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #upIcon 'Move Up') tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move Down' tz@731: #value: #doStepDown tz@731: #activeHelpKey: #editMoveDown tz@731: #enabled: #canStepOverChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #downIcon 'Move Down') tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move In' tz@731: #value: #doStepIn tz@731: #activeHelpKey: #editMoveIn tz@731: #enabled: #canStepInChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #downRightIcon 'Move In') tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move Out' tz@731: #value: #doStepOut tz@731: #activeHelpKey: #editMoveOut tz@731: #enabled: #canStepOutChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #leftDownIcon 'Move Out') tz@506: ) tz@506: ) nil tz@506: nil tz@506: ) tz@506: ! tz@506: tz@506: menuToolbar tz@736: "This resource specification was automatically generated tz@736: by the MenuEditor of ST/X." tz@506: tz@736: "Do not manually edit this!! If it is corrupted, tz@736: the MenuEditor may not be able to read the specification." tz@506: tz@506: " tz@506: MenuEditor new openOnClass:HierarchicalListEditor andSelector:#menuToolbar tz@506: (Menu new fromLiteralArrayEncoding:(HierarchicalListEditor menuToolbar)) startUp tz@506: " tz@506: tz@506: tz@506: tz@506: ^ tz@506: tz@506: #(#Menu tz@506: tz@506: #( tz@506: #(#MenuItem tz@731: #label: 'New' tz@731: #isButton: true tz@731: #value: #doNew tz@731: #activeHelpKey: #fileNew tz@882: #labelImage: #(#ResourceRetriever #Icon #newIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Load' tz@731: #isButton: true tz@731: #value: #doLoad tz@731: #activeHelpKey: #fileLoad tz@882: #labelImage: #(#ResourceRetriever #Icon #loadIcon) tz@731: ) tz@731: #(#MenuItem tz@731: #label: 'Save' tz@731: #isButton: true tz@731: #value: #doSave tz@731: #activeHelpKey: #fileSave tz@882: #labelImage: #(#ResourceRetriever #Icon #saveIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: '' tz@731: ) tz@731: #(#MenuItem tz@731: #label: 'Cut' tz@731: #isButton: true tz@731: #value: #doCut tz@731: #activeHelpKey: #editCut tz@731: #enabled: #valueOfCanCut tz@882: #labelImage: #(#ResourceRetriever #Icon #cutIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Copy' tz@731: #isButton: true tz@731: #value: #doCopy tz@731: #activeHelpKey: #editCopy tz@731: #enabled: #valueOfCanCopy tz@882: #labelImage: #(#ResourceRetriever #Icon #copyIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Paste' tz@731: #isButton: true tz@731: #value: #doPaste tz@731: #activeHelpKey: #editPaste tz@731: #enabled: #valueOfCanPaste tz@882: #labelImage: #(#ResourceRetriever #Icon #pasteIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Delete' tz@731: #isButton: true tz@731: #value: #doDelete tz@731: #activeHelpKey: #editDelete tz@731: #enabled: #valueOfCanCut tz@882: #labelImage: #(#ResourceRetriever #Icon #deleteIcon) tz@731: ) tz@731: #(#MenuItem tz@731: #label: '' tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Add Child' tz@731: #isButton: true tz@731: #value: #doCreateChild tz@731: #activeHelpKey: #addChild tz@731: #enabled: #canCreateChildChannel tz@731: #labelImage: #(#ResourceRetriever nil #createChildIcon) tz@731: ) tz@731: #(#MenuItem tz@731: #label: 'Add Sister' tz@731: #isButton: true tz@731: #value: #doCreateSister tz@731: #activeHelpKey: #addSister tz@731: #enabled: #canCreateSisterChannel tz@731: #labelImage: #(#ResourceRetriever nil #createSisterIcon) tz@731: ) tz@731: #(#MenuItem tz@731: #label: '' tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move Up' tz@731: #isButton: true tz@731: #value: #doStepUp tz@731: #activeHelpKey: #editMoveUp tz@731: #enabled: #canStepOverChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #upIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move Down' tz@731: #isButton: true tz@731: #value: #doStepDown tz@731: #activeHelpKey: #editMoveDown tz@731: #enabled: #canStepOverChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #downIcon) tz@506: ) tz@506: #(#MenuItem tz@731: #label: 'Move In' tz@731: #isButton: true tz@731: #value: #doStepIn tz@731: #activeHelpKey: #editMoveIn tz@731: #enabled: #canStepInChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #downRightIcon) tz@731: ) tz@731: #(#MenuItem tz@731: #label: 'Move Out' tz@731: #isButton: true tz@731: #value: #doStepOut tz@731: #activeHelpKey: #editMoveOut tz@731: #enabled: #canStepOutChannel tz@882: #labelImage: #(#ResourceRetriever #Icon #leftDownIcon) tz@506: ) tz@506: ) nil tz@506: nil tz@506: ) tz@506: ! ! tz@506: ca@300: !HierarchicalListEditor class methodsFor:'printing'! ca@300: ca@300: prettyPrintArray:anArray on:aStream indent:anIndent ca@300: "print a literal array in a nice format ca@300: " ca@300: |arg sol| ca@300: ca@300: sol := aStream position. ca@300: aStream spaces:anIndent. ca@300: aStream nextPutAll:'#('. ca@300: ca@300: anArray first isSymbol ifTrue:[ ca@300: arg := anArray first. ca@300: aStream nextPut:$#. ca@300: aStream nextPutAll:anArray first. ca@300: aStream cr. ca@300: anArray size == 2 ifTrue:[ ca@300: self prettyPrintArray:(anArray last) ca@300: on:aStream ca@300: indent:(anIndent + 4). ca@300: ]. ca@300: aStream spaces:anIndent. ca@300: aStream nextPut:$). ca@300: ^ self ca@300: ]. ca@300: ca@300: aStream nextPut:$'. ca@300: aStream nextPutAll:(anArray at:1). ca@300: aStream nextPut:$'. ca@300: arg := anArray at:2 ifAbsent:nil. ca@300: ca@300: arg isString ifTrue:[ ca@300: aStream spaces:((50 - (aStream position - sol)) max:4). ca@300: ca@300: arg isSymbol ifTrue:[ ca@300: aStream nextPut:$#. ca@300: ]. ca@300: aStream nextPut:$'. ca@300: aStream nextPutAll:arg. ca@300: aStream nextPut:$'. ca@300: arg := anArray at:3 ifAbsent:nil. ca@300: ]. ca@300: arg isArray ifTrue:[ ca@300: aStream nextPutAll:' #('. ca@300: aStream cr. ca@300: arg do:[:e|self prettyPrintArray:e on:aStream indent:(anIndent + 4)]. ca@300: aStream spaces:anIndent. ca@300: aStream nextPut:$). ca@300: ]. ca@300: aStream nextPut:$). ca@300: aStream cr. ca@300: ! ! ca@300: ca@300: !HierarchicalListEditor methodsFor:'aspects'! ca@300: ca@300: canCreateChildChannel ca@300: tz@423: ^builder booleanValueAspectFor:#canCreateChildChannel ca@300: ca@300: ! ca@300: ca@300: canCreateSisterChannel ca@300: tz@423: ^builder booleanValueAspectFor:#canCreateSisterChannel ca@300: ca@300: ! ca@300: ca@300: canStepInChannel ca@300: tz@423: ^builder booleanValueAspectFor:#canStepInChannel ca@300: ca@300: ! ca@300: ca@300: canStepOutChannel ca@300: tz@423: ^builder booleanValueAspectFor:#canStepOutChannel ca@300: ca@300: ! ca@300: ca@300: canStepOverChannel ca@300: tz@423: ^builder booleanValueAspectFor:#canStepOverChannel ca@300: ca@300: ! ca@300: ca@300: itemName ca@300: ca@300: |holder| ca@300: ca@300: (holder := builder bindingAt:#itemName) isNil ifTrue:[ ca@300: builder aspectAt:#itemName put:(holder := ValueHolder new). ca@300: holder addDependent:self. ca@300: ]. ca@300: ^ holder ca@300: ! ca@300: ca@300: itemValue ca@300: ca@300: |holder| ca@300: ca@300: (holder := builder bindingAt:#itemValue) isNil ifTrue:[ ca@300: builder aspectAt:#itemValue put:(holder := ValueHolder new). ca@300: holder addDependent:self. ca@300: ]. ca@300: ^ holder ca@300: ! ca@300: ca@300: treeView ca@300: tz@423: ^treeView ca@300: ! ! ca@300: tz@731: !HierarchicalListEditor methodsFor:'building'! tz@731: tz@731: buildFromClass:aClass andSelector:aSelector tz@731: "rebuild window from a class and selector" tz@731: tz@731: |cls sel anchor| ca@300: tz@731: cls := self resolveName:aClass. tz@731: specSelector := nil. tz@423: tz@731: aSelector size ~~ 0 tz@731: ifTrue: tz@731: [ tz@731: sel := aSelector asString withoutSeparators. tz@731: sel size ~~ 0 ifTrue:[specSelector := sel asSymbol] tz@731: ]. tz@731: treeView selection:nil. tz@423: tz@731: (specSelector notNil and:[cls notNil]) tz@731: ifTrue: tz@731: [ tz@731: (cls respondsTo:specSelector) tz@731: ifTrue: tz@731: [ tz@731: anchor := cls perform:specSelector. tz@731: anchor isArray ifTrue:[anchor := anchor decodeAsLiteralArray] tz@731: ]. tz@731: ]. tz@731: anchor notNil tz@731: ifTrue: [anchor expand. treeView root:anchor] tz@731: ifFalse: [treeView root isNil ifTrue: [self buildRoot]]. tz@581: tz@731: treeView selection: 1. tz@581: tz@731: self updateHistory. tz@731: self updateInfoLabel. tz@731: tz@731: tz@731: tz@731: ! tz@731: tz@736: buildFromResourceSpec: aListSpec tz@581: tz@731: treeView root: aListSpec tz@731: tz@731: ! tz@731: tz@731: buildRoot tz@731: "build just a root" tz@731: tz@731: treeView root:(TreeItem name:'Root' contents:#Anchor). tz@731: treeView selection:1. tz@581: ! ! tz@581: ca@1575: !HierarchicalListEditor methodsFor:'menu accessing'! ca@1575: ca@1575: menu ca@1575: ^ self class menu ca@1575: ! ca@1575: ca@1575: menuEdit ca@1575: ^ self class menuEdit ca@1575: ! ca@1575: ca@1575: menuToolbar ca@1575: ^ self class menuToolbar ca@1575: ! ! ca@1575: tz@423: !HierarchicalListEditor methodsFor:'private'! tz@423: tz@731: getDepthAndSistersNumberOfNode: aNode onParentNode: aParentNode tz@731: "return depth of selected node" tz@731: tz@731: |parent childNode depthAndSistersNumbers str| tz@423: tz@731: depthAndSistersNumbers := OrderedCollection new. tz@731: childNode := aNode. tz@731: parent := aParentNode. tz@731: [parent notNil] tz@731: whileTrue: tz@423: [ tz@731: depthAndSistersNumbers add: (parent children indexOf: childNode). tz@731: childNode := parent. tz@731: parent := parent parent. tz@423: ]. tz@731: depthAndSistersNumbers removeFirst; addFirst: aParentNode children size. tz@731: str := ''. tz@731: depthAndSistersNumbers reverseDo: [:n| str := str, n printString, '.']. tz@731: ^str copyFrom: 1 to: str size - 1 tz@506: ! tz@506: tz@423: newItem tz@423: "creates and returns a new default item" tz@423: tz@558: ^TreeItem name: 'Item' contents: nil tz@423: ! tz@423: tz@423: updateChannels tz@423: "update channels" tz@423: tz@423: |node parent chnStepIn chnStepOut chnStepOvr chnChild chnSister| tz@423: tz@423: chnStepIn := chnStepOut := chnStepOvr := chnChild := chnSister := false. tz@423: tz@423: (node := treeView selectedNode) notNil tz@423: ifTrue: tz@423: [ tz@731: (builder componentAt: #SpecView) beVisible. tz@423: chnChild := true. tz@423: (parent := node parent) notNil tz@423: ifTrue: tz@423: [ tz@423: chnSister := true. tz@423: chnStepOvr := parent numberOfChildren > 1. tz@423: chnStepOut := parent parent notNil. tz@423: chnStepIn := node ~~ parent lastChild tz@423: ] tz@423: ] tz@423: ifFalse: tz@423: [ tz@731: (builder componentAt: #SpecView) beInvisible tz@423: ]. tz@423: self canCreateChildChannel value:chnChild. tz@423: self canCreateSisterChannel value:chnSister. tz@423: self canStepOverChannel value:chnStepOvr. tz@423: self canStepOutChannel value:chnStepOut. tz@506: self canStepInChannel value:chnStepIn. tz@506: tz@731: self valueOfCanCut value: (treeView selection notNil tz@731: ifTrue:[(treeView isInSelection:1) not] tz@731: ifFalse: [false]). tz@506: tz@731: self valueOfCanCopy value: self valueOfCanCut value. tz@731: tz@736: self valueOfCanPaste value: treeView selectedNode notNil & self valueOfCanPaste value. tz@423: ! tz@423: tz@423: updateInputFields tz@423: "reload item value into input fields" tz@423: tz@423: |node| tz@423: tz@423: (node := treeView selectedNode) notNil tz@423: ifTrue: tz@423: [ tz@423: self itemName value:node name. tz@423: self itemValue value:node contents tz@423: ] tz@423: ifFalse: tz@423: [ tz@423: self itemName value:''. tz@423: self itemValue value:nil tz@423: ]. tz@423: self valueOfEnablingCommitButtons value: false ca@300: ! ! ca@300: tz@423: !HierarchicalListEditor methodsFor:'startup / release'! tz@423: tz@423: initialize tz@423: "setup default values" tz@423: tz@423: super initialize. tz@423: tz@423: treeView := SelectionInTreeView new. tz@423: treeView multipleSelectOk: true. tz@423: treeView showDirectoryIndicator: true. tz@423: treeView showDirectoryIndicatorForRoot: false. tz@423: treeView action:[:aNr| self updateChannels. self updateInputFields]. tz@731: treeView selectConditionBlock: [:i|self askForItemModification]. tz@423: treeView validateDoubleClickBlock: [:node| node ~~ treeView model list first]. tz@423: ! tz@423: tz@731: openModalOnTreeItem: aTreeItem tz@731: "build a tree from aTreeItem and open it modal" tz@423: tz@736: super openModalOnResourceSpec: aTreeItem tz@423: ! ! tz@423: tz@423: !HierarchicalListEditor methodsFor:'user actions'! tz@423: tz@423: accept tz@423: "invoked by button 'OK'" tz@423: tz@423: |node index| tz@423: tz@423: (index := treeView selectedIndex) ~~ 0 tz@423: ifTrue: tz@423: [ tz@423: node := treeView nodeAtIndex:index. tz@423: node name: self itemName value. tz@423: node contents: self itemValue value. tz@423: treeView redrawLine:index. tz@423: ]. tz@731: modified := true. tz@423: self valueOfEnablingCommitButtons value: false tz@423: ! tz@423: tz@423: cancel tz@423: "invoked by button 'Cancel'" tz@423: tz@423: self updateInputFields. tz@423: tz@731: modified := false. tz@423: self valueOfEnablingCommitButtons value: false tz@423: ! tz@423: tz@423: doCopy tz@423: "copy current selected nodes into copy buffer" tz@423: tz@731: self class clipboard: OrderedCollection new. tz@736: treeView selectedNodesDo:[:aNode| self class clipboard add: aNode copy]. tz@747: self updateAllToolInstances tz@423: ! ca@300: ca@300: doCreateChild tz@423: "create a child within selected parent" tz@423: tz@558: |node newItem| ca@300: tz@731: ((node := treeView selectedNode) notNil and: [self askForItemModification]) tz@423: ifTrue: tz@423: [ tz@558: treeView model add: (newItem := self newItem) afterIndex: node children size below:node. tz@558: newItem name: 'Child ', (self getDepthAndSistersNumberOfNode: newItem onParentNode: node). ca@300: treeView selectedNodeExpand:true. tz@558: treeView selectNode: newItem. ca@300: self updateChannels. tz@731: modified := true tz@423: ] ca@300: ! ca@300: ca@300: doCreateSister ca@300: "create a sister next to selected item ca@300: " tz@558: |node newItem| ca@300: tz@731: ((node := treeView selectedNode) notNil and: [self askForItemModification]) tz@423: ifTrue: tz@423: [ tz@558: newItem := self newItem. tz@423: node parent notNil tz@562: ifTrue: [treeView model add: newItem after:node] tz@558: ifFalse:[treeView model add: newItem beforeIndex:1 below:node]. tz@562: tz@558: newItem name: 'Child ', (self getDepthAndSistersNumberOfNode: newItem onParentNode: node parent). tz@558: treeView selectNode: newItem. tz@506: self updateChannels. tz@731: modified := true tz@423: ] ca@300: ! ca@300: tz@423: doCut tz@423: "cut current selected nodes" ca@300: tz@423: |selection| tz@731: (treeView hasSelection and: [self askForItemModification]) tz@423: ifTrue: tz@423: [ tz@423: self doCopy. tz@423: selection := treeView selection asSortedCollection. tz@423: treeView selectedNodesRemove. tz@423: treeView selection: selection first - 1. tz@747: self updateAllToolInstances. tz@731: modified := true tz@731: ] tz@731: ! tz@731: tz@731: doDelete tz@731: "delete current selected nodes" tz@731: tz@731: |selection| tz@731: (treeView hasSelection and: [self askForItemModification]) tz@731: ifTrue: tz@731: [ tz@731: selection := treeView selection asSortedCollection. tz@731: treeView selectedNodesRemove. tz@731: treeView selection: selection first - 1. tz@731: self updateChannels. tz@731: modified := true ca@300: ] ca@300: ! ca@300: tz@731: doNew tz@736: "first do super new; then make a build tz@736: of a resource spec containing a root" ca@300: tz@736: super doNew ifTrue: [self buildRoot] ca@300: tz@731: tz@731: ca@300: ! ca@300: tz@731: doPaste tz@731: "paste after current selected item" tz@731: tz@736: (self askForItemModification and: [self class clipboard notNil]) tz@731: ifTrue: tz@731: [ tz@731: |copiedNode| tz@731: self class clipboard do: tz@731: [:node| tz@731: copiedNode := node copy. tz@731: treeView selectedNodeAdd: copiedNode. tz@731: treeView selectNode: copiedNode. tz@731: ]. tz@731: self updateChannels. tz@731: modified := true tz@731: ] tz@731: ! tz@731: tz@731: doReload tz@731: "reload spec from current class and selector" tz@731: tz@731: self buildFrom:specClass andSelector:specSelector tz@731: tz@731: ! tz@731: tz@731: doSave tz@423: "install code" tz@423: tz@731: |cls code spec category mthd stream| ca@300: tz@423: (specClass notNil and:[specSelector notNil]) tz@423: ifFalse: tz@423: [ tz@731: ^self doSaveAs ca@300: ]. ca@300: tz@731: cls := self resolveName: specClass. ca@300: spec := (treeView nodeAtIndex:1) literalArrayEncoding. ca@300: stream := WriteStream on:String new. ca@300: self class prettyPrintArray:spec on:stream indent:4. ca@300: spec := stream contents. tz@731: category := 'list specs'. ca@300: tz@731: (mthd := cls class compiledMethodAt:specSelector) notNil tz@423: ifTrue: tz@423: [ tz@423: category := mthd category ca@300: ]. ca@300: ca@300: code := Character excla asString tz@731: , cls name , ' class methodsFor:' , category storeString ca@300: , Character excla asString , '\\' ca@300: ca@300: , specSelector , '\' tz@736: , (self class codeGenerationComment replChar:$!! withString:'!!!!') tz@736: , '\\ "\' tz@731: , ' HierarchicalListEditor openOnClass:' , cls name , ' andSelector:#' , specSelector , '\' ca@300: , ' "\'. ca@300: ca@300: code := code ca@300: , '\' ca@300: , ' \\' ca@300: , ' ^\' ca@300: , spec ca@300: , ' decodeAsLiteralArray\' ca@300: , Character excla asString ca@300: , ' ' ca@300: , Character excla asString ca@300: , '\\'. ca@300: ca@300: code := code withCRs. ca@300: (ReadStream on:code) fileIn. ca@300: tz@731: self updateHistory. tz@731: hasSaved := true. tz@731: modified := false. ca@300: ! ca@300: tz@423: doStepDown tz@423: "move selected item after next item" ca@300: tz@423: treeView selectedNodeChangeSequenceOrder:1. tz@506: self updateChannels. tz@731: modified := true tz@506: ca@300: ! ca@300: tz@423: doStepIn tz@423: "lets become the selected item a child of its next sister" ca@300: tz@423: treeView selectedNodeBecomeChildOfNext. tz@506: self updateChannels. tz@731: modified := true tz@506: tz@506: tz@506: ca@300: ! ca@300: tz@423: doStepOut tz@423: "let selected node become a sister of its current parent" ca@300: tz@423: treeView selectedNodeBecomeSisterOfParent. tz@506: self updateChannels. tz@731: modified := true tz@506: tz@506: tz@506: ca@300: ! ca@300: tz@423: doStepUp tz@423: "move selected item before previous item" ca@300: tz@423: treeView selectedNodeChangeSequenceOrder:-1. tz@506: self updateChannels. tz@731: modified := true tz@506: tz@506: tz@506: cg@1856: ! cg@1856: cg@1856: openDocumentation cg@1856: self openHTMLDocument:'tools/uipainter/HierarchicalListEditor.html'. ca@300: ! ! ca@300: ca@300: !HierarchicalListEditor class methodsFor:'documentation'! ca@300: ca@300: version ca@300: ^ '$Header$' ca@300: ! !