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