MenuEditor.st
changeset 1407 5b6ce9f1988e
parent 1400 891c5c044e33
child 1410 ec3abe12f662
equal deleted inserted replaced
1406:6de5c78f5bcd 1407:5b6ce9f1988e
    20 	classVariableNames:''
    20 	classVariableNames:''
    21 	poolDictionaries:''
    21 	poolDictionaries:''
    22 	category:'Interface-UIPainter'
    22 	category:'Interface-UIPainter'
    23 !
    23 !
    24 
    24 
    25 SelectionInTreeView subclass:#TreeView
       
    26 	instanceVariableNames:''
       
    27 	classVariableNames:''
       
    28 	poolDictionaries:''
       
    29 	privateIn:MenuEditor
       
    30 !
       
    31 
       
    32 Object subclass:#Item
    25 Object subclass:#Item
    33 	instanceVariableNames:'activeHelpKey enabled label value nameKey indication shortcutKey
    26 	instanceVariableNames:'activeHelpKey enabled label value nameKey indication shortcutKey
    34 		accessCharacterPos retriever icon iconAndLabel submenuChannel
    27 		accessCharacterPos retriever icon iconAndLabel submenuChannel
    35 		startGroup argument translateLabel isButton isVisible choice
    28 		startGroup argument translateLabel isButton isVisible choice
    36 		choiceValue auxValue hideMenuOnActivated font
    29 		choiceValue auxValue hideMenuOnActivated font
    37 		showBusyCursorWhilePerforming keepLinkedMenu'
    30 		showBusyCursorWhilePerforming keepLinkedMenu'
       
    31 	classVariableNames:''
       
    32 	poolDictionaries:''
       
    33 	privateIn:MenuEditor
       
    34 !
       
    35 
       
    36 SelectionInTreeView subclass:#TreeView
       
    37 	instanceVariableNames:''
    38 	classVariableNames:''
    38 	classVariableNames:''
    39 	poolDictionaries:''
    39 	poolDictionaries:''
    40 	privateIn:MenuEditor
    40 	privateIn:MenuEditor
    41 !
    41 !
    42 
    42 
  1946         ^ #()
  1946         ^ #()
  1947      ].
  1947      ].
  1948 
  1948 
  1949      imageMethodSelectors := OrderedCollection new.
  1949      imageMethodSelectors := OrderedCollection new.
  1950 
  1950 
  1951      iconClass withAllSuperclasses do:[:cls |
  1951      iconClass withAllSuperclassesDo:[:cls |
  1952         cls class selectorsAndMethodsDo:[:sel :m | 
  1952         cls class selectorsAndMethodsDo:[:sel :m | 
  1953             ((r := m resourceType) == #image
  1953             ((r := m resourceType) == #image
  1954             or:[r == #programImage]) ifTrue:[
  1954             or:[r == #programImage]) ifTrue:[
  1955                 imageMethodSelectors add:sel
  1955                 imageMethodSelectors add:sel
  1956             ]
  1956             ]
  2689 doStepUp
  2689 doStepUp
  2690     "shift selected menu item one step up"
  2690     "shift selected menu item one step up"
  2691 
  2691 
  2692     treeView selectedNodeChangeSequenceOrder:-1.
  2692     treeView selectedNodeChangeSequenceOrder:-1.
  2693     modified := true.
  2693     modified := true.
  2694 ! !
       
  2695 
       
  2696 !MenuEditor::TreeView class methodsFor:'documentation'!
       
  2697 
       
  2698 documentation
       
  2699 "
       
  2700     This tree view class provides a hierarchical representation
       
  2701     of the components of a menu.
       
  2702 
       
  2703     [see also:]
       
  2704         SelectionInTreeView
       
  2705         SelectionInTree
       
  2706         TreeItem
       
  2707 
       
  2708     [author:]
       
  2709         Claus Atzkern
       
  2710 "
       
  2711 ! !
       
  2712 
       
  2713 !MenuEditor::TreeView methodsFor:'accessing'!
       
  2714 
       
  2715 canTab
       
  2716     ^ true
       
  2717 !
       
  2718 
       
  2719 selectorName
       
  2720     "get the selector of the menu spec"
       
  2721 
       
  2722     ^(listOfNodes first contents label) asSymbol
       
  2723 !
       
  2724 
       
  2725 selectorName: aSymbol
       
  2726     "set the selector for the menu spec"
       
  2727 
       
  2728     listOfNodes first contents label: aSymbol
       
  2729 ! !
       
  2730 
       
  2731 !MenuEditor::TreeView methodsFor:'building'!
       
  2732 
       
  2733 buildFromClass:aClass andSelector:aSelector
       
  2734     "read a menu spec from aClass and aSelector and put 
       
  2735      the encoded menu into the tree view"
       
  2736 
       
  2737     |spec cls menu firstNode firstNodeLabel|
       
  2738 
       
  2739     "if opened on a menu"
       
  2740     (aClass isNil and: [aSelector isNil and: [listOfNodes size > 0]]) ifTrue: [^nil].
       
  2741 
       
  2742     self selection:nil.
       
  2743 
       
  2744     (aClass notNil and:[aSelector notNil]) ifTrue:[
       
  2745         cls := self application resolveName:aClass.
       
  2746 
       
  2747         (cls respondsTo:aSelector) ifTrue:[
       
  2748             spec := cls perform:aSelector
       
  2749         ]
       
  2750     ].
       
  2751 
       
  2752     spec isNil ifFalse:[
       
  2753         (spec isMemberOf:Menu) ifFalse:[
       
  2754             menu := Menu new fromLiteralArrayEncoding:spec.
       
  2755         ] ifTrue:[
       
  2756             menu := spec.
       
  2757         ].
       
  2758         firstNode := self nodeLabel:(aSelector asString).
       
  2759         self subMenu:menu parent:firstNode.
       
  2760     ] ifTrue:[
       
  2761         (aClass notNil and: [aSelector isNil and: [listOfNodes size > 0]])
       
  2762         ifTrue:
       
  2763         [
       
  2764             firstNode := listOfNodes first
       
  2765         ]
       
  2766         ifFalse:
       
  2767         [
       
  2768             aSelector notNil ifTrue:[firstNodeLabel := aSelector asString]
       
  2769                         ifFalse:[firstNodeLabel := 'menu'].
       
  2770             firstNode := self nodeLabel:firstNodeLabel.
       
  2771         ]
       
  2772     ].
       
  2773 
       
  2774     firstNode expand.
       
  2775     model root: firstNode.
       
  2776 
       
  2777     firstNode hasChildren ifFalse:[
       
  2778         model add:(self nodeLabel:'Item 1') below:firstNode
       
  2779     ].
       
  2780 
       
  2781 
       
  2782 !
       
  2783 
       
  2784 buildFromMenu:aMenu
       
  2785     "put aMenu into the tree view"
       
  2786 
       
  2787     |node|
       
  2788 
       
  2789     self selection:nil.
       
  2790 
       
  2791     node := self nodeLabel:'menu'.
       
  2792     self subMenu:aMenu parent:node.
       
  2793 
       
  2794     node hasChildren ifFalse:[
       
  2795         node add:(self nodeLabel:'Item 1')
       
  2796     ].
       
  2797     node expand.
       
  2798     model root:node.
       
  2799 !
       
  2800 
       
  2801 menuItem:anItem
       
  2802 
       
  2803     |node|
       
  2804 
       
  2805     node := self nodeLabel: anItem label.
       
  2806     node contents buildFromMenuItem:anItem.
       
  2807     self subMenu: anItem submenu parent:node.
       
  2808     ^node.
       
  2809 
       
  2810 
       
  2811 !
       
  2812 
       
  2813 subMenu:aMenu parent:aParent
       
  2814 
       
  2815     |idx grp|
       
  2816 
       
  2817     aMenu isNil ifFalse:[
       
  2818         grp := aMenu groupSizes.
       
  2819         aMenu itemsDo:[:i| aParent add:(self menuItem:i)].
       
  2820 
       
  2821         grp notNil ifTrue:[
       
  2822             idx := 0.
       
  2823 
       
  2824             grp do:[:i|
       
  2825                 idx := idx + i + 1.
       
  2826                 aParent add:(self nodeLabel:nil) beforeIndex:idx.
       
  2827             ]
       
  2828         ]
       
  2829     ]
       
  2830 ! !
       
  2831 
       
  2832 !MenuEditor::TreeView methodsFor:'conversion'!
       
  2833 
       
  2834 asMenu
       
  2835     |menu root|
       
  2836 
       
  2837     root := self root.
       
  2838 
       
  2839     root hasChildren ifTrue:[
       
  2840         menu := Menu new.
       
  2841         root children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
       
  2842     ].
       
  2843   ^ menu
       
  2844 !
       
  2845 
       
  2846 asMenuItem:aNode
       
  2847 
       
  2848     |menu item|
       
  2849 
       
  2850     item := aNode contents asMenuItem.
       
  2851 
       
  2852     aNode hasChildren ifTrue:[
       
  2853         menu := Menu new.
       
  2854         aNode children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
       
  2855         item submenu:menu
       
  2856     ].
       
  2857   ^ item
       
  2858 
       
  2859 ! !
       
  2860 
       
  2861 !MenuEditor::TreeView methodsFor:'drawing basics'!
       
  2862 
       
  2863 redrawLabelAt:x y:yTop index:anIndex
       
  2864     "draw text label assigned to a node at x y( center)"
       
  2865 
       
  2866     |isSelected y0 x0 x1 w type item|
       
  2867 
       
  2868     item := (listOfNodes at:anIndex) contents.
       
  2869     type := item separatorType.
       
  2870 
       
  2871     type isNil ifTrue:[
       
  2872         ^ super redrawLabelAt:x y:yTop index:anIndex
       
  2873     ].
       
  2874     isSelected := self isInSelection:anIndex.
       
  2875     x0 := x.
       
  2876 
       
  2877     highlightMode == #label ifTrue:[
       
  2878         x0 := x + 4.
       
  2879 
       
  2880         isSelected ifTrue:[
       
  2881             w  := 80 + 8.
       
  2882             self paint:hilightBgColor.
       
  2883             self fillRectangleX:x y:yTop width:w height:fontHeight.
       
  2884         ]
       
  2885     ] ifFalse:[
       
  2886         w := 0.
       
  2887     ].
       
  2888     type == #blank ifFalse:[
       
  2889         isSelected ifTrue:[self paint:hilightFgColor]
       
  2890                   ifFalse:[self paint:fgColor].
       
  2891 
       
  2892         x1 := x0 + 80.
       
  2893         y0 := yTop - 1 + (fontHeight // 2).
       
  2894         self displayLineFromX:x0 y:y0 toX:x1 y:y0.
       
  2895 
       
  2896         type == #double ifTrue:[
       
  2897             y0 := y0 + 2.
       
  2898             self displayLineFromX:x0 y:y0 toX:x1 y:y0.
       
  2899         ]    
       
  2900     ].
       
  2901 
       
  2902     (isSelected and:[highlightMode == #label]) ifTrue:[
       
  2903         self redrawSelFrameAtX:x y:yTop toX:(x + w)
       
  2904     ].
       
  2905 
       
  2906 ! !
       
  2907 
       
  2908 !MenuEditor::TreeView methodsFor:'event handling'!
       
  2909 
       
  2910 keyPress:key x:x y:y
       
  2911     "invoked if any key was pressed"
       
  2912 
       
  2913     <resource: #keyboard (#Delete #BackSpace #Cut #Copy #Paste)>
       
  2914 
       
  2915     (key == #Delete or:[key == #BackSpace]) ifTrue: [^self doDelete].
       
  2916     key == #Cut   ifTrue:[^self doCut].
       
  2917     key == #Copy  ifTrue:[^self doCopy].
       
  2918     key == #Paste ifTrue:[^self doPaste].
       
  2919 
       
  2920     super keyPress:key x:x y:y
       
  2921 
       
  2922 ! !
       
  2923 
       
  2924 !MenuEditor::TreeView methodsFor:'initialization'!
       
  2925 
       
  2926 initialize
       
  2927     "initialize the tree view of the menu components"
       
  2928 
       
  2929     super initialize.
       
  2930 
       
  2931     self multipleSelectOk:true.
       
  2932     self showDirectoryIndicator: true.
       
  2933     self showDirectoryIndicatorForRoot: false.
       
  2934     self selectConditionBlock: [:i|self application askForItemModification]. 
       
  2935     self validateDoubleClickBlock: [:node| node ~~ listOfNodes first].
       
  2936     self model iconAction: [:aNode| aNode contents iconFor: aNode].
       
  2937     self model labelAction: [:aNode| aNode contents treeViewLabel]
       
  2938 ! !
       
  2939 
       
  2940 !MenuEditor::TreeView methodsFor:'menus'!
       
  2941 
       
  2942 XXdoDeleteSelectionBuffered:aBool
       
  2943     |appl idx|
       
  2944 
       
  2945     appl := self topView application.
       
  2946 
       
  2947     (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
       
  2948         ^ self
       
  2949     ].
       
  2950     aBool ifTrue:[
       
  2951         self doCopy
       
  2952     ].
       
  2953 
       
  2954     idx := 10000.
       
  2955     self selection do:[:aNumber| idx := idx min:aNumber ].
       
  2956 
       
  2957     self selectedNodesRemove.
       
  2958     self selection:(idx min:(self list size)).
       
  2959     self setModified.
       
  2960 
       
  2961     aBool ifTrue:[
       
  2962         "/ must update copy&paste indication
       
  2963         appl updateAllToolInstances.
       
  2964     ]
       
  2965 !
       
  2966 
       
  2967 doCopy
       
  2968     |clip|
       
  2969 
       
  2970     self hasSelection ifTrue:[
       
  2971         self application clipboard:(clip := OrderedCollection new).
       
  2972         self selectionDo:[:i | clip add:((listOfNodes at:i) copy)].
       
  2973         self topView application updateAllToolInstances.
       
  2974     ]
       
  2975 !
       
  2976 
       
  2977 doCreateItem
       
  2978 
       
  2979     self addElement: (self nodeLabel:'Item')
       
  2980 !
       
  2981 
       
  2982 doCreateLink
       
  2983 
       
  2984     |node item|
       
  2985 
       
  2986     node := self nodeLabel:'Submenu Link'.
       
  2987     item := node contents.
       
  2988     item submenuChannel:#menuDefaultLink.
       
  2989     self addElement:node.
       
  2990     self setModified.
       
  2991 
       
  2992 
       
  2993 !
       
  2994 
       
  2995 doCreateMenu
       
  2996 
       
  2997     |node|
       
  2998     node := self nodeLabel:'Submenu'.
       
  2999     node parent: self selectedNode.        
       
  3000     node add:(self nodeLabel:'Item 1').
       
  3001     self addElement:node
       
  3002 !
       
  3003 
       
  3004 doCreateSep
       
  3005 
       
  3006     self addElement:(self nodeLabel:nil)
       
  3007 !
       
  3008 
       
  3009 doCreateStandardEditMenu
       
  3010 
       
  3011     |node|
       
  3012     node := self nodeLabel:'Edit'.
       
  3013     node parent: self selectedNode.        
       
  3014     node add:(self nodeLabel:'Copy'  selector:#copySelection).
       
  3015     node add:(self nodeLabel:'Cut'   selector:#cutSelection).
       
  3016     node add:(self nodeLabel:'Paste' selector:#paste).
       
  3017     self addElement:node
       
  3018 
       
  3019     "Created: / 23.8.1998 / 15:52:16 / cg"
       
  3020     "Modified: / 23.8.1998 / 15:59:36 / cg"
       
  3021 !
       
  3022 
       
  3023 doCreateStandardFileMenu
       
  3024 
       
  3025     |node|
       
  3026     node := self nodeLabel:'File'.
       
  3027     node parent: self selectedNode.        
       
  3028     node add:(self nodeLabel:'New'        selector:#menuNew).
       
  3029     node add:(self nodeLabel:'-'          ).
       
  3030     node add:(self nodeLabel:'Open...'    selector:#menuOpen).
       
  3031     node add:(self nodeLabel:'-'          ).
       
  3032     node add:(self nodeLabel:'Save'       selector:#menuSave).
       
  3033     node add:(self nodeLabel:'Save As...' selector:#menuSaveAs).
       
  3034     node add:(self nodeLabel:'-'          ).
       
  3035     node add:(self nodeLabel:'Exit'       selector:#closeRequest).
       
  3036     self addElement:node
       
  3037 
       
  3038     "Created: / 23.8.1998 / 15:51:55 / cg"
       
  3039     "Modified: / 23.8.1998 / 16:04:24 / cg"
       
  3040 !
       
  3041 
       
  3042 doCreateStandardHelpMenu
       
  3043 
       
  3044     |node|
       
  3045     node := self nodeLabel:'Help'.
       
  3046     node parent: self selectedNode.        
       
  3047     node contents startGroup:#right.
       
  3048     node add:(self nodeLabel:'Documentation'          selector:#openDocumentation).
       
  3049     node add:(self nodeLabel:'-').
       
  3050     node add:(self nodeLabel:'About this Application' selector:#openAboutThisApplication).
       
  3051     self addElement:node
       
  3052 
       
  3053     "Created: / 23.8.1998 / 15:52:46 / cg"
       
  3054     "Modified: / 23.8.1998 / 17:30:12 / cg"
       
  3055 !
       
  3056 
       
  3057 doCut
       
  3058     ^ self doDeleteSelectionBuffered:true
       
  3059 !
       
  3060 
       
  3061 doDelete
       
  3062     ^ self doDeleteSelectionBuffered:false
       
  3063 !
       
  3064 
       
  3065 doDeleteSelectionBuffered:aBool
       
  3066     |appl nsel list item prnt|
       
  3067 
       
  3068     appl := self topView application.
       
  3069 
       
  3070     (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
       
  3071         ^ self
       
  3072     ].
       
  3073     aBool ifTrue:[
       
  3074         self doCopy
       
  3075     ].
       
  3076     list := self list.
       
  3077     nsel := list size.
       
  3078     self selection do:[:aNumber| nsel := nsel min:aNumber ].
       
  3079 
       
  3080     (     (item := list at:nsel ifAbsent:nil) notNil
       
  3081      and:[(prnt := item parent) notNil
       
  3082      and:[prnt children last == item]]
       
  3083     ) ifTrue:[
       
  3084         nsel := nsel - 1
       
  3085     ].
       
  3086 
       
  3087     self selectedNodesRemove.
       
  3088     self selection:(nsel min:(list size)).
       
  3089     self setModified.
       
  3090 
       
  3091     aBool ifTrue:[
       
  3092         "/ must update copy&paste indication
       
  3093         appl updateAllToolInstances.
       
  3094     ]
       
  3095 !
       
  3096 
       
  3097 doPaste
       
  3098     |clip|
       
  3099 
       
  3100     clip := self application clipboard.
       
  3101     (clip notNil and:[self selectedNode notNil]) ifTrue:[
       
  3102         self addElement:(clip collect:[:el| el copy])
       
  3103     ].
       
  3104 ! !
       
  3105 
       
  3106 !MenuEditor::TreeView methodsFor:'private'!
       
  3107 
       
  3108 addElement: aNode
       
  3109     "add something after selection"
       
  3110 
       
  3111     |label sel|     
       
  3112 
       
  3113     self askForItemModification ifTrue:[   
       
  3114         self selectedNodeAdd:aNode.
       
  3115         (aNode isCollection not 
       
  3116         and: [aNode name = 'Item']) 
       
  3117         ifTrue:[
       
  3118             sel := self selectedNode.
       
  3119             label := aNode name , ' ',
       
  3120                 (sel parent notNil 
       
  3121                 ifTrue:
       
  3122                     [
       
  3123                         (((sel children size = 0 
       
  3124                             ifTrue: [sel parent children] 
       
  3125                             ifFalse: [sel children]) 
       
  3126                         select:[:node| 
       
  3127                             |lab| 
       
  3128                             lab := node contents label. 
       
  3129                             ((node children size = 0) & 
       
  3130                             node contents submenuChannel isNil &
       
  3131                             (lab ~= '-') & (lab ~= '=') & (lab ~= ''))
       
  3132                         ]) size) printString
       
  3133                     ] 
       
  3134                 ifFalse: ['1']).  
       
  3135 
       
  3136             aNode name: label string asBoldText.
       
  3137             aNode contents label: label string.
       
  3138         ].    
       
  3139         aNode isCollection ifFalse: [self selectNode: aNode] ifTrue: [self selection: (aNode collect: [:node| self indexOfNode: node])].
       
  3140         self setModified.
       
  3141     ]
       
  3142 !
       
  3143 
       
  3144 askForItemModification
       
  3145 
       
  3146     ^self topView application askForItemModification
       
  3147 !
       
  3148 
       
  3149 nodeLabel:aLabel
       
  3150 
       
  3151     ^TreeItem new contents: ((MenuEditor::Item new label:aLabel) translateLabel:true)
       
  3152 
       
  3153     "Modified: / 6.6.1998 / 17:22:35 / cg"
       
  3154 !
       
  3155 
       
  3156 nodeLabel:aLabel selector:aSelector
       
  3157 
       
  3158     ^TreeItem new contents: (((MenuEditor::Item new label:aLabel) value:aSelector) translateLabel:true)
       
  3159 
       
  3160     "Modified: / 6.6.1998 / 17:22:35 / cg"
       
  3161     "Created: / 23.8.1998 / 15:58:59 / cg"
       
  3162 !
       
  3163 
       
  3164 selectedNodeAdd:something
       
  3165 
       
  3166     |node numChildren|
       
  3167 
       
  3168     something notNil ifTrue:[
       
  3169         (node := self selectedNode) notNil ifTrue:[
       
  3170             numChildren := node children size.
       
  3171 
       
  3172             node parent notNil ifTrue:[
       
  3173                 node isCollapsable ifTrue:[
       
  3174                     model add:something afterIndex:numChildren below:node
       
  3175                 ] ifFalse:[
       
  3176                     model add:something after:node
       
  3177                 ]
       
  3178             ] ifFalse:[
       
  3179                 model add:something afterIndex:numChildren below:(self root)
       
  3180             ]
       
  3181         ]
       
  3182     ]
       
  3183 
       
  3184 
       
  3185 !
       
  3186 
       
  3187 setModified 
       
  3188     |app|
       
  3189 
       
  3190     (app := self topView application) modified: true.
       
  3191     app updateChannels
       
  3192 ! !
  2694 ! !
  3193 
  2695 
  3194 !MenuEditor::Item class methodsFor:'constants'!
  2696 !MenuEditor::Item class methodsFor:'constants'!
  3195 
  2697 
  3196 separatorList
  2698 separatorList
  3540 
  3042 
  3541 
  3043 
  3542 "
  3044 "
  3543 ! !
  3045 ! !
  3544 
  3046 
       
  3047 !MenuEditor::TreeView class methodsFor:'documentation'!
       
  3048 
       
  3049 documentation
       
  3050 "
       
  3051     This tree view class provides a hierarchical representation
       
  3052     of the components of a menu.
       
  3053 
       
  3054     [see also:]
       
  3055         SelectionInTreeView
       
  3056         SelectionInTree
       
  3057         TreeItem
       
  3058 
       
  3059     [author:]
       
  3060         Claus Atzkern
       
  3061 "
       
  3062 ! !
       
  3063 
       
  3064 !MenuEditor::TreeView methodsFor:'accessing'!
       
  3065 
       
  3066 canTab
       
  3067     ^ true
       
  3068 !
       
  3069 
       
  3070 selectorName
       
  3071     "get the selector of the menu spec"
       
  3072 
       
  3073     ^(listOfNodes first contents label) asSymbol
       
  3074 !
       
  3075 
       
  3076 selectorName: aSymbol
       
  3077     "set the selector for the menu spec"
       
  3078 
       
  3079     listOfNodes first contents label: aSymbol
       
  3080 ! !
       
  3081 
       
  3082 !MenuEditor::TreeView methodsFor:'building'!
       
  3083 
       
  3084 buildFromClass:aClass andSelector:aSelector
       
  3085     "read a menu spec from aClass and aSelector and put 
       
  3086      the encoded menu into the tree view"
       
  3087 
       
  3088     |spec cls menu firstNode firstNodeLabel|
       
  3089 
       
  3090     "if opened on a menu"
       
  3091     (aClass isNil and: [aSelector isNil and: [listOfNodes size > 0]]) ifTrue: [^nil].
       
  3092 
       
  3093     self selection:nil.
       
  3094 
       
  3095     (aClass notNil and:[aSelector notNil]) ifTrue:[
       
  3096         cls := self application resolveName:aClass.
       
  3097 
       
  3098         (cls respondsTo:aSelector) ifTrue:[
       
  3099             spec := cls perform:aSelector
       
  3100         ]
       
  3101     ].
       
  3102 
       
  3103     spec isNil ifFalse:[
       
  3104         (spec isMemberOf:Menu) ifFalse:[
       
  3105             menu := Menu new fromLiteralArrayEncoding:spec.
       
  3106         ] ifTrue:[
       
  3107             menu := spec.
       
  3108         ].
       
  3109         firstNode := self nodeLabel:(aSelector asString).
       
  3110         self subMenu:menu parent:firstNode.
       
  3111     ] ifTrue:[
       
  3112         (aClass notNil and: [aSelector isNil and: [listOfNodes size > 0]])
       
  3113         ifTrue:
       
  3114         [
       
  3115             firstNode := listOfNodes first
       
  3116         ]
       
  3117         ifFalse:
       
  3118         [
       
  3119             aSelector notNil ifTrue:[firstNodeLabel := aSelector asString]
       
  3120                         ifFalse:[firstNodeLabel := 'menu'].
       
  3121             firstNode := self nodeLabel:firstNodeLabel.
       
  3122         ]
       
  3123     ].
       
  3124 
       
  3125     firstNode expand.
       
  3126     model root: firstNode.
       
  3127 
       
  3128     firstNode hasChildren ifFalse:[
       
  3129         model add:(self nodeLabel:'Item 1') below:firstNode
       
  3130     ].
       
  3131 
       
  3132 
       
  3133 !
       
  3134 
       
  3135 buildFromMenu:aMenu
       
  3136     "put aMenu into the tree view"
       
  3137 
       
  3138     |node|
       
  3139 
       
  3140     self selection:nil.
       
  3141 
       
  3142     node := self nodeLabel:'menu'.
       
  3143     self subMenu:aMenu parent:node.
       
  3144 
       
  3145     node hasChildren ifFalse:[
       
  3146         node add:(self nodeLabel:'Item 1')
       
  3147     ].
       
  3148     node expand.
       
  3149     model root:node.
       
  3150 !
       
  3151 
       
  3152 menuItem:anItem
       
  3153 
       
  3154     |node|
       
  3155 
       
  3156     node := self nodeLabel: anItem label.
       
  3157     node contents buildFromMenuItem:anItem.
       
  3158     self subMenu: anItem submenu parent:node.
       
  3159     ^node.
       
  3160 
       
  3161 
       
  3162 !
       
  3163 
       
  3164 subMenu:aMenu parent:aParent
       
  3165 
       
  3166     |idx grp|
       
  3167 
       
  3168     aMenu isNil ifFalse:[
       
  3169         grp := aMenu groupSizes.
       
  3170         aMenu itemsDo:[:i| aParent add:(self menuItem:i)].
       
  3171 
       
  3172         grp notNil ifTrue:[
       
  3173             idx := 0.
       
  3174 
       
  3175             grp do:[:i|
       
  3176                 idx := idx + i + 1.
       
  3177                 aParent add:(self nodeLabel:nil) beforeIndex:idx.
       
  3178             ]
       
  3179         ]
       
  3180     ]
       
  3181 ! !
       
  3182 
       
  3183 !MenuEditor::TreeView methodsFor:'conversion'!
       
  3184 
       
  3185 asMenu
       
  3186     |menu root|
       
  3187 
       
  3188     root := self root.
       
  3189 
       
  3190     root hasChildren ifTrue:[
       
  3191         menu := Menu new.
       
  3192         root children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
       
  3193     ].
       
  3194   ^ menu
       
  3195 !
       
  3196 
       
  3197 asMenuItem:aNode
       
  3198 
       
  3199     |menu item|
       
  3200 
       
  3201     item := aNode contents asMenuItem.
       
  3202 
       
  3203     aNode hasChildren ifTrue:[
       
  3204         menu := Menu new.
       
  3205         aNode children do:[:aChild| menu addItem:(self asMenuItem:aChild)].
       
  3206         item submenu:menu
       
  3207     ].
       
  3208   ^ item
       
  3209 
       
  3210 ! !
       
  3211 
       
  3212 !MenuEditor::TreeView methodsFor:'drawing basics'!
       
  3213 
       
  3214 redrawLabelAt:x y:yTop index:anIndex
       
  3215     "draw text label assigned to a node at x y( center)"
       
  3216 
       
  3217     |isSelected y0 x0 x1 w type item|
       
  3218 
       
  3219     item := (listOfNodes at:anIndex) contents.
       
  3220     type := item separatorType.
       
  3221 
       
  3222     type isNil ifTrue:[
       
  3223         ^ super redrawLabelAt:x y:yTop index:anIndex
       
  3224     ].
       
  3225     isSelected := self isInSelection:anIndex.
       
  3226     x0 := x.
       
  3227 
       
  3228     highlightMode == #label ifTrue:[
       
  3229         x0 := x + 4.
       
  3230 
       
  3231         isSelected ifTrue:[
       
  3232             w  := 80 + 8.
       
  3233             self paint:hilightBgColor.
       
  3234             self fillRectangleX:x y:yTop width:w height:fontHeight.
       
  3235         ]
       
  3236     ] ifFalse:[
       
  3237         w := 0.
       
  3238     ].
       
  3239     type == #blank ifFalse:[
       
  3240         isSelected ifTrue:[self paint:hilightFgColor]
       
  3241                   ifFalse:[self paint:fgColor].
       
  3242 
       
  3243         x1 := x0 + 80.
       
  3244         y0 := yTop - 1 + (fontHeight // 2).
       
  3245         self displayLineFromX:x0 y:y0 toX:x1 y:y0.
       
  3246 
       
  3247         type == #double ifTrue:[
       
  3248             y0 := y0 + 2.
       
  3249             self displayLineFromX:x0 y:y0 toX:x1 y:y0.
       
  3250         ]    
       
  3251     ].
       
  3252 
       
  3253     (isSelected and:[highlightMode == #label]) ifTrue:[
       
  3254         self redrawSelFrameAtX:x y:yTop toX:(x + w)
       
  3255     ].
       
  3256 
       
  3257 ! !
       
  3258 
       
  3259 !MenuEditor::TreeView methodsFor:'event handling'!
       
  3260 
       
  3261 keyPress:key x:x y:y
       
  3262     "invoked if any key was pressed"
       
  3263 
       
  3264     <resource: #keyboard (#Delete #BackSpace #Cut #Copy #Paste)>
       
  3265 
       
  3266     (key == #Delete or:[key == #BackSpace]) ifTrue: [^self doDelete].
       
  3267     key == #Cut   ifTrue:[^self doCut].
       
  3268     key == #Copy  ifTrue:[^self doCopy].
       
  3269     key == #Paste ifTrue:[^self doPaste].
       
  3270 
       
  3271     super keyPress:key x:x y:y
       
  3272 
       
  3273 ! !
       
  3274 
       
  3275 !MenuEditor::TreeView methodsFor:'initialization'!
       
  3276 
       
  3277 initialize
       
  3278     "initialize the tree view of the menu components"
       
  3279 
       
  3280     super initialize.
       
  3281 
       
  3282     self multipleSelectOk:true.
       
  3283     self showDirectoryIndicator: true.
       
  3284     self showDirectoryIndicatorForRoot: false.
       
  3285     self selectConditionBlock: [:i|self application askForItemModification]. 
       
  3286     self validateDoubleClickBlock: [:node| node ~~ listOfNodes first].
       
  3287     self model iconAction: [:aNode| aNode contents iconFor: aNode].
       
  3288     self model labelAction: [:aNode| aNode contents treeViewLabel]
       
  3289 ! !
       
  3290 
       
  3291 !MenuEditor::TreeView methodsFor:'menus'!
       
  3292 
       
  3293 XXdoDeleteSelectionBuffered:aBool
       
  3294     |appl idx|
       
  3295 
       
  3296     appl := self topView application.
       
  3297 
       
  3298     (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
       
  3299         ^ self
       
  3300     ].
       
  3301     aBool ifTrue:[
       
  3302         self doCopy
       
  3303     ].
       
  3304 
       
  3305     idx := 10000.
       
  3306     self selection do:[:aNumber| idx := idx min:aNumber ].
       
  3307 
       
  3308     self selectedNodesRemove.
       
  3309     self selection:(idx min:(self list size)).
       
  3310     self setModified.
       
  3311 
       
  3312     aBool ifTrue:[
       
  3313         "/ must update copy&paste indication
       
  3314         appl updateAllToolInstances.
       
  3315     ]
       
  3316 !
       
  3317 
       
  3318 doCopy
       
  3319     |clip|
       
  3320 
       
  3321     self hasSelection ifTrue:[
       
  3322         self application clipboard:(clip := OrderedCollection new).
       
  3323         self selectionDo:[:i | clip add:((listOfNodes at:i) copy)].
       
  3324         self topView application updateAllToolInstances.
       
  3325     ]
       
  3326 !
       
  3327 
       
  3328 doCreateItem
       
  3329 
       
  3330     self addElement: (self nodeLabel:'Item')
       
  3331 !
       
  3332 
       
  3333 doCreateLink
       
  3334 
       
  3335     |node item|
       
  3336 
       
  3337     node := self nodeLabel:'Submenu Link'.
       
  3338     item := node contents.
       
  3339     item submenuChannel:#menuDefaultLink.
       
  3340     self addElement:node.
       
  3341     self setModified.
       
  3342 
       
  3343 
       
  3344 !
       
  3345 
       
  3346 doCreateMenu
       
  3347 
       
  3348     |node|
       
  3349     node := self nodeLabel:'Submenu'.
       
  3350     node parent: self selectedNode.        
       
  3351     node add:(self nodeLabel:'Item 1').
       
  3352     self addElement:node
       
  3353 !
       
  3354 
       
  3355 doCreateSep
       
  3356 
       
  3357     self addElement:(self nodeLabel:nil)
       
  3358 !
       
  3359 
       
  3360 doCreateStandardEditMenu
       
  3361 
       
  3362     |node|
       
  3363     node := self nodeLabel:'Edit'.
       
  3364     node parent: self selectedNode.        
       
  3365     node add:(self nodeLabel:'Copy'  selector:#copySelection).
       
  3366     node add:(self nodeLabel:'Cut'   selector:#cutSelection).
       
  3367     node add:(self nodeLabel:'Paste' selector:#paste).
       
  3368     self addElement:node
       
  3369 
       
  3370     "Created: / 23.8.1998 / 15:52:16 / cg"
       
  3371     "Modified: / 23.8.1998 / 15:59:36 / cg"
       
  3372 !
       
  3373 
       
  3374 doCreateStandardFileMenu
       
  3375 
       
  3376     |node|
       
  3377     node := self nodeLabel:'File'.
       
  3378     node parent: self selectedNode.        
       
  3379     node add:(self nodeLabel:'New'        selector:#menuNew).
       
  3380     node add:(self nodeLabel:'-'          ).
       
  3381     node add:(self nodeLabel:'Open...'    selector:#menuOpen).
       
  3382     node add:(self nodeLabel:'-'          ).
       
  3383     node add:(self nodeLabel:'Save'       selector:#menuSave).
       
  3384     node add:(self nodeLabel:'Save As...' selector:#menuSaveAs).
       
  3385     node add:(self nodeLabel:'-'          ).
       
  3386     node add:(self nodeLabel:'Exit'       selector:#closeRequest).
       
  3387     self addElement:node
       
  3388 
       
  3389     "Created: / 23.8.1998 / 15:51:55 / cg"
       
  3390     "Modified: / 23.8.1998 / 16:04:24 / cg"
       
  3391 !
       
  3392 
       
  3393 doCreateStandardHelpMenu
       
  3394 
       
  3395     |node|
       
  3396     node := self nodeLabel:'Help'.
       
  3397     node parent: self selectedNode.        
       
  3398     node contents startGroup:#right.
       
  3399     node add:(self nodeLabel:'Documentation'          selector:#openDocumentation).
       
  3400     node add:(self nodeLabel:'-').
       
  3401     node add:(self nodeLabel:'About this Application' selector:#openAboutThisApplication).
       
  3402     self addElement:node
       
  3403 
       
  3404     "Created: / 23.8.1998 / 15:52:46 / cg"
       
  3405     "Modified: / 23.8.1998 / 17:30:12 / cg"
       
  3406 !
       
  3407 
       
  3408 doCut
       
  3409     ^ self doDeleteSelectionBuffered:true
       
  3410 !
       
  3411 
       
  3412 doDelete
       
  3413     ^ self doDeleteSelectionBuffered:false
       
  3414 !
       
  3415 
       
  3416 doDeleteSelectionBuffered:aBool
       
  3417     |appl nsel list item prnt|
       
  3418 
       
  3419     appl := self topView application.
       
  3420 
       
  3421     (appl hasValidSelection value and: [self askForItemModification]) ifFalse:[
       
  3422         ^ self
       
  3423     ].
       
  3424     aBool ifTrue:[
       
  3425         self doCopy
       
  3426     ].
       
  3427     list := self list.
       
  3428     nsel := list size.
       
  3429     self selection do:[:aNumber| nsel := nsel min:aNumber ].
       
  3430 
       
  3431     (     (item := list at:nsel ifAbsent:nil) notNil
       
  3432      and:[(prnt := item parent) notNil
       
  3433      and:[prnt children last == item]]
       
  3434     ) ifTrue:[
       
  3435         nsel := nsel - 1
       
  3436     ].
       
  3437 
       
  3438     self selectedNodesRemove.
       
  3439     self selection:(nsel min:(list size)).
       
  3440     self setModified.
       
  3441 
       
  3442     aBool ifTrue:[
       
  3443         "/ must update copy&paste indication
       
  3444         appl updateAllToolInstances.
       
  3445     ]
       
  3446 !
       
  3447 
       
  3448 doPaste
       
  3449     |clip|
       
  3450 
       
  3451     clip := self application clipboard.
       
  3452     (clip notNil and:[self selectedNode notNil]) ifTrue:[
       
  3453         self addElement:(clip collect:[:el| el copy])
       
  3454     ].
       
  3455 ! !
       
  3456 
       
  3457 !MenuEditor::TreeView methodsFor:'private'!
       
  3458 
       
  3459 addElement: aNode
       
  3460     "add something after selection"
       
  3461 
       
  3462     |label sel|     
       
  3463 
       
  3464     self askForItemModification ifTrue:[   
       
  3465         self selectedNodeAdd:aNode.
       
  3466         (aNode isCollection not 
       
  3467         and: [aNode name = 'Item']) 
       
  3468         ifTrue:[
       
  3469             sel := self selectedNode.
       
  3470             label := aNode name , ' ',
       
  3471                 (sel parent notNil 
       
  3472                 ifTrue:
       
  3473                     [
       
  3474                         (((sel children size = 0 
       
  3475                             ifTrue: [sel parent children] 
       
  3476                             ifFalse: [sel children]) 
       
  3477                         select:[:node| 
       
  3478                             |lab| 
       
  3479                             lab := node contents label. 
       
  3480                             ((node children size = 0) & 
       
  3481                             node contents submenuChannel isNil &
       
  3482                             (lab ~= '-') & (lab ~= '=') & (lab ~= ''))
       
  3483                         ]) size) printString
       
  3484                     ] 
       
  3485                 ifFalse: ['1']).  
       
  3486 
       
  3487             aNode name: label string asBoldText.
       
  3488             aNode contents label: label string.
       
  3489         ].    
       
  3490         aNode isCollection ifFalse: [self selectNode: aNode] ifTrue: [self selection: (aNode collect: [:node| self indexOfNode: node])].
       
  3491         self setModified.
       
  3492     ]
       
  3493 !
       
  3494 
       
  3495 askForItemModification
       
  3496 
       
  3497     ^self topView application askForItemModification
       
  3498 !
       
  3499 
       
  3500 nodeLabel:aLabel
       
  3501 
       
  3502     ^TreeItem new contents: ((MenuEditor::Item new label:aLabel) translateLabel:true)
       
  3503 
       
  3504     "Modified: / 6.6.1998 / 17:22:35 / cg"
       
  3505 !
       
  3506 
       
  3507 nodeLabel:aLabel selector:aSelector
       
  3508 
       
  3509     ^TreeItem new contents: (((MenuEditor::Item new label:aLabel) value:aSelector) translateLabel:true)
       
  3510 
       
  3511     "Modified: / 6.6.1998 / 17:22:35 / cg"
       
  3512     "Created: / 23.8.1998 / 15:58:59 / cg"
       
  3513 !
       
  3514 
       
  3515 selectedNodeAdd:something
       
  3516 
       
  3517     |node numChildren|
       
  3518 
       
  3519     something notNil ifTrue:[
       
  3520         (node := self selectedNode) notNil ifTrue:[
       
  3521             numChildren := node children size.
       
  3522 
       
  3523             node parent notNil ifTrue:[
       
  3524                 node isCollapsable ifTrue:[
       
  3525                     model add:something afterIndex:numChildren below:node
       
  3526                 ] ifFalse:[
       
  3527                     model add:something after:node
       
  3528                 ]
       
  3529             ] ifFalse:[
       
  3530                 model add:something afterIndex:numChildren below:(self root)
       
  3531             ]
       
  3532         ]
       
  3533     ]
       
  3534 
       
  3535 
       
  3536 !
       
  3537 
       
  3538 setModified 
       
  3539     |app|
       
  3540 
       
  3541     (app := self topView application) modified: true.
       
  3542     app updateChannels
       
  3543 ! !
       
  3544 
  3545 !MenuEditor class methodsFor:'documentation'!
  3545 !MenuEditor class methodsFor:'documentation'!
  3546 
  3546 
  3547 version
  3547 version
  3548     ^ '$Header$'
  3548     ^ '$Header$'
  3549 ! !
  3549 ! !