Skip to content

Commit 258f67c

Browse files
committed
define class context menu using phlow actions [feenkcom/gtoolkit#4725]
1 parent 2ba1923 commit 258f67c

File tree

5 files changed

+214
-82
lines changed

5 files changed

+214
-82
lines changed

src/GToolkit-Coder-UI/Class.extension.st

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,28 @@ Class >> gtCoderSidebarIndexBrowseClasses: someClasses referencesFrom: aGtCoderC
3838
action: [ aGtCoderClassesTreeElement browseSeveralReferencesTo: someClasses ]
3939
]
4040

41+
{ #category : #'*GToolkit-Coder-UI' }
42+
Class >> gtCoderSidebarIndexBrowseClassesReferencesFor: anAction context: aPhlowContext [
43+
<gtAction>
44+
aPhlowContext coderSelectedClasses ifEmpty: [ ^ anAction noAction ].
45+
46+
^ anAction button
47+
priority: 2;
48+
target: GtCoderClassesTarget;
49+
icon: BrGlamorousVectorIcons empty;
50+
label: 'Browse references';
51+
menuItemPreview: ('{1} classes' format: {aPhlowContext coderSelectedClasses size});
52+
menuItemGroup: BrMenuItemGroupConfiguration navigation;
53+
action: [ :aButton |
54+
| someClasses aFilter |
55+
someClasses := aPhlowContext coderSelectedClasses.
56+
aFilter := someClasses allButFirst
57+
inject: someClasses first gtReferences
58+
into: [ :aSumFilter :aClass | aSumFilter | aClass gtReferences ].
59+
60+
aButton phlow spawnObject: aFilter ]
61+
]
62+
4163
{ #category : #'*GToolkit-Coder-UI' }
4264
Class >> gtCoderSidebarIndexBrowseReferencesFor: anAction [
4365
<gtAction>
@@ -128,7 +150,7 @@ Class >> gtCoderSidebarIndexNewSubclassFor: anAction [
128150
icon: BrGlamorousVectorIcons add;
129151
label: 'New subclass';
130152
menuItemPreview: self name;
131-
menuItemGroup: BrMenuItemGroupConfiguration default;
153+
menuItemGroup: BrMenuItemGroupConfiguration modification;
132154
action: [ :aButton :aHostElement |
133155
"TODO: We should replace this with a dedicated wish event."
134156
aHostElement
@@ -163,11 +185,11 @@ Class >> gtCoderSidebarIndexRemoveClassFor: anAction [
163185
icon: BrGlamorousVectorIcons remove;
164186
label: 'Remove class';
165187
menuItemPreview: self name;
166-
menuItemGroup: BrMenuItemGroupConfiguration refactoring;
188+
menuItemGroup: BrMenuItemGroupConfiguration removal;
167189
menuItemPinSubmenu;
168190
content: [ :anActionElement :aTargetElement :anExplicitMenu |
169191
GtCoderRemoveClassPreviewStencil new
170-
classToRemove: self;
192+
classToRemove: self instanceSide;
171193
menuModel: anExplicitMenu;
172194
asElement ]
173195
]
@@ -193,6 +215,27 @@ Class >> gtCoderSidebarIndexRemoveClasses: someClasses from: aGtCoderClassesTree
193215
submenu: (aGtCoderClassesTreeElement removeSeveralClassesSubmenuFor: someClasses)
194216
]
195217

218+
{ #category : #'*GToolkit-Coder-UI' }
219+
Class >> gtCoderSidebarIndexRemoveClassesFor: anAction context: aPhlowContext [
220+
<gtAction>
221+
aPhlowContext coderSelectedClasses ifEmpty: [ ^ anAction noAction ].
222+
223+
^ anAction dropdown
224+
priority: 5;
225+
target: GtCoderClassesTarget;
226+
icon: BrGlamorousVectorIcons empty;
227+
label: 'Remove classes';
228+
menuItemPreview: ('{1} classes' format: {aPhlowContext coderSelectedClasses size});
229+
menuItemGroup: BrMenuItemGroupConfiguration removal;
230+
content: [ :anActionElement :aTargetElement :anExplicitMenu |
231+
| someClasses |
232+
someClasses := aPhlowContext coderSelectedClasses.
233+
GtCoderRemoveClassesPreviewStencil new
234+
classesToRemove: someClasses;
235+
menuModel: anExplicitMenu;
236+
asElement ]
237+
]
238+
196239
{ #category : #'*GToolkit-Coder-UI' }
197240
Class >> gtCoderSidebarIndexRenameClassFor: anAction [
198241
<gtAction>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"
2+
I represent a target for several selected classes, e.g., in the coder sidebar class list.
3+
{{gtClass:GtPhlowAction}} can access the list of classes using {{gtMethod:GtPhlowContext>>#coderSelectedClasses}}.
4+
5+
"
6+
Class {
7+
#name : #GtCoderClassesTarget,
8+
#superclass : #GtPhlowActionUniqueTarget,
9+
#category : #'GToolkit-Coder-UI-Phlow Targets'
10+
}

src/GToolkit-Coder-UI/GtCoderClassesTreeElement.class.st

Lines changed: 58 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,32 @@ Class {
1414
#instVars : [
1515
'classesTree'
1616
],
17+
#classVars : [
18+
'UsePhlowActions'
19+
],
1720
#category : #'GToolkit-Coder-UI-Navigation - Helpers'
1821
}
1922

23+
{ #category : #settings }
24+
GtCoderClassesTreeElement class >> dontUsePhlowActions [
25+
UsePhlowActions := false
26+
]
27+
2028
{ #category : #'instance creation' }
2129
GtCoderClassesTreeElement class >> fromClasses: aCollectionOfClasses [
2230
^ self new initializeWithClasses: aCollectionOfClasses
2331
]
2432

33+
{ #category : #settings }
34+
GtCoderClassesTreeElement class >> isUsePhlowAction [
35+
^ UsePhlowActions ifNil: [ false ]
36+
]
37+
38+
{ #category : #settings }
39+
GtCoderClassesTreeElement class >> usePhlowActions [
40+
UsePhlowActions := true
41+
]
42+
2543
{ #category : #'private - context menu' }
2644
GtCoderClassesTreeElement >> addPreviewButtonFor: refactoring to: elem cancelSelector: cancelSelector [
2745
| button |
@@ -104,35 +122,38 @@ GtCoderClassesTreeElement >> contextMenuFor: aClass [
104122

105123
{ #category : #initialization }
106124
GtCoderClassesTreeElement >> contextMenuForOneItem: aClass [
107-
| aMenuItems |
108-
aMenuItems := BrMenuItems new.
109-
GtCoderClassTarget
110-
actionsForObject: aClass
111-
collect: [ :eachAction |
112-
eachAction
113-
asMenuItem: [ :aMenuItem | aMenuItems addItem: aMenuItem ]
114-
withHostElement: self ].
115-
116-
true ifTrue: [ ^ aMenuItems ].
117-
118-
^ BrMenuItemsPragmaBuilder new
119-
object: aClass;
120-
upToSuperclass: Behavior;
121-
pragma: #gtCoderSidebarIndexOneSubjectContextMenuItem:;
122-
methodArguments: {self};
123-
sortByFirstPragmaArgument;
124-
build
125+
<return: #BrMenuItems>
126+
^ self isContextMenuFromPhlowActions
127+
ifTrue: [ GtCoderClassTarget menuItemsForObject: aClass hostElement: self ]
128+
ifFalse: [ BrMenuItemsPragmaBuilder new
129+
object: aClass;
130+
upToSuperclass: Behavior;
131+
pragma: #gtCoderSidebarIndexOneSubjectContextMenuItem:;
132+
methodArguments: {self};
133+
sortByFirstPragmaArgument;
134+
build ]
125135
]
126136

127137
{ #category : #initialization }
128138
GtCoderClassesTreeElement >> contextMenuForSeveralItems: someClasses [
129-
^ BrMenuItemsPragmaBuilder new
130-
object: Class;
131-
upToSuperclass: Behavior;
132-
pragma: #gtCoderSidebarIndexSeveralSubjectsContextMenuItem:;
133-
methodArguments: {someClasses. self};
134-
sortByFirstPragmaArgument;
135-
build
139+
<return: #BrMenuItems>
140+
^ self isContextMenuFromPhlowActions
141+
ifTrue: [
142+
| aPhlowContext |
143+
aPhlowContext := GtPhlowContext new coderSelectedClasses: someClasses.
144+
GtCoderClassesTarget
145+
menuItemsForObject: someClasses anyOne
146+
inContext: aPhlowContext
147+
hostElement: self ]
148+
ifFalse: [
149+
BrMenuItemsPragmaBuilder new
150+
object: Class;
151+
upToSuperclass: Behavior;
152+
pragma: #gtCoderSidebarIndexSeveralSubjectsContextMenuItem:;
153+
methodArguments: {someClasses.
154+
self};
155+
sortByFirstPragmaArgument;
156+
build ]
136157
]
137158

138159
{ #category : #'private - drag and drop' }
@@ -270,6 +291,11 @@ GtCoderClassesTreeElement >> initializeWithHierachyForClass: aClass [
270291
^ self ] ]
271292
]
272293

294+
{ #category : #testing }
295+
GtCoderClassesTreeElement >> isContextMenuFromPhlowActions [
296+
^ self class isUsePhlowAction
297+
]
298+
273299
{ #category : #'private - context menu' }
274300
GtCoderClassesTreeElement >> newSubclassOf: aClass [
275301
| dropdown tabGroup |
@@ -320,66 +346,19 @@ GtCoderClassesTreeElement >> removeClassSubmenuFor: aClass [
320346
^ BrMenuExplicit new
321347
stencil: [ :anExplicitMenu |
322348
GtCoderRemoveClassPreviewStencil new
323-
classToRemove: self;
349+
classToRemove: aClass;
324350
menuModel: anExplicitMenu;
325351
asElement ]
326352
]
327353

328354
{ #category : #initialization }
329355
GtCoderClassesTreeElement >> removeSeveralClassesSubmenuFor: someClasses [
330-
| submenu |
331-
submenu := BrMenuExplicit new.
332-
^ submenu
333-
stencil: [ | element change button |
334-
element := BrVerticalPane new fitContent.
335-
element
336-
addChild: ((self buildRemoveSeveralClassesLabelFor: someClasses)
337-
margin: (BlInsets
338-
top: 10
339-
bottom: 0
340-
left: 10
341-
right: 10)).
342-
element
343-
addChild: (BrAsyncWidget new
344-
fitContent;
345-
stencil: [ | pane references subclasses |
346-
references := someClasses sumNumbers: [ :eachClass | (GtPharoIndex current
347-
globalVariableReferencesTo: eachClass binding) size ].
348-
subclasses := someClasses sumNumbers: [ :eachClass | (eachClass allSubclasses difference: someClasses) size ].
349-
pane := BrVerticalPane new.
350-
pane fitContent.
351-
references > 0
352-
ifTrue: [ pane
353-
addChild: (BrLabel new
354-
margin: (BlInsets left: 10 right: 10);
355-
aptitude: BrGlamorousLabelAptitude new glamorousRegularFont thin;
356-
text: (references printString , ' reference'
357-
, (references > 1 ifTrue: [ 's' ] ifFalse: [ '' ])) asRopedText) ].
358-
subclasses > 0
359-
ifTrue: [ pane
360-
addChild: (BrLabel new
361-
margin: (BlInsets left: 10 right: 10);
362-
aptitude: BrGlamorousLabelAptitude new glamorousRegularFont thin;
363-
text: (subclasses printString , ' subclass'
364-
, (subclasses > 1 ifTrue: [ 'es' ] ifFalse: [ '' ])) asRopedText) ].
365-
pane ]).
366-
change := RBCompositeRefactoryChange new
367-
name: ('Remove {1} classes' format: { someClasses size });
368-
changes: (someClasses collect: [ :eachClass | RBRemoveClassChange remove: eachClass ]).
369-
button := BrButton new
370-
aptitude: BrGlamorousButtonWithIconAptitude;
371-
beSmallSize;
372-
margin: (BlInsets
373-
top: 10
374-
bottom: 10
375-
left: 10
376-
right: 10);
377-
icon: BrGlamorousVectorIcons remove;
378-
label: 'Remove';
379-
action: [ submenu hideAll.
380-
change execute ].
381-
element addChild: button as: #removeButton.
382-
element ]
356+
^ BrMenuExplicit new
357+
stencil: [ :aMenuExplicit |
358+
GtCoderRemoveClassesPreviewStencil new
359+
classesToRemove: someClasses;
360+
menuModel: aMenuExplicit;
361+
asElement ]
383362
]
384363

385364
{ #category : #initialization }
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Class {
2+
#name : #GtCoderRemoveClassesPreviewStencil,
3+
#superclass : #BrStencil,
4+
#instVars : [
5+
'classesToRemove',
6+
'menuModel'
7+
],
8+
#category : #'GToolkit-Coder-UI-Navigation - Helpers'
9+
}
10+
11+
{ #category : #accessing }
12+
GtCoderRemoveClassesPreviewStencil >> classesToRemove [
13+
^ classesToRemove
14+
]
15+
16+
{ #category : #accessing }
17+
GtCoderRemoveClassesPreviewStencil >> classesToRemove: anObject [
18+
classesToRemove := anObject
19+
]
20+
21+
{ #category : #'as yet unclassified' }
22+
GtCoderRemoveClassesPreviewStencil >> create [
23+
| element change button |
24+
element := BrVerticalPane new fitContent.
25+
element
26+
addChild: (self newRemoveSeveralClassesLabel
27+
margin: (BlInsets
28+
top: 10
29+
bottom: 0
30+
left: 10
31+
right: 10)).
32+
element
33+
addChild: (BrAsyncWidget new
34+
fitContent;
35+
stencil: [ | pane references subclasses |
36+
references := self classesToRemove
37+
sumNumbers: [ :eachClass | (GtPharoIndex current globalVariableReferencesTo: eachClass binding) size ].
38+
subclasses := self classesToRemove
39+
sumNumbers: [ :eachClass | (eachClass allSubclasses difference: self classesToRemove) size ].
40+
pane := BrVerticalPane new.
41+
pane fitContent.
42+
references > 0
43+
ifTrue: [ pane
44+
addChild: (BrLabel new
45+
margin: (BlInsets left: 10 right: 10);
46+
aptitude: BrGlamorousLabelAptitude new glamorousRegularFont thin;
47+
text: (references printString , ' reference'
48+
, (references > 1 ifTrue: [ 's' ] ifFalse: [ '' ])) asRopedText) ].
49+
subclasses > 0
50+
ifTrue: [ pane
51+
addChild: (BrLabel new
52+
margin: (BlInsets left: 10 right: 10);
53+
aptitude: BrGlamorousLabelAptitude new glamorousRegularFont thin;
54+
text: (subclasses printString , ' subclass'
55+
, (subclasses > 1 ifTrue: [ 'es' ] ifFalse: [ '' ])) asRopedText) ].
56+
pane ]).
57+
change := RBCompositeRefactoryChange new
58+
name: ('Remove {1} classes' format: {self classesToRemove size});
59+
changes: (self classesToRemove
60+
collect: [ :eachClass | RBRemoveClassChange remove: eachClass ]).
61+
button := BrButton new
62+
aptitude: BrGlamorousButtonWithIconAptitude;
63+
beSmallSize;
64+
margin: (BlInsets
65+
top: 10
66+
bottom: 10
67+
left: 10
68+
right: 10);
69+
icon: BrGlamorousVectorIcons remove;
70+
label: 'Remove';
71+
action: [ self menuModel ifNotNil: #hideAll.
72+
change execute ].
73+
element addChild: button as: #removeButton.
74+
^ element
75+
]
76+
77+
{ #category : #accessing }
78+
GtCoderRemoveClassesPreviewStencil >> menuModel [
79+
^ menuModel
80+
]
81+
82+
{ #category : #accessing }
83+
GtCoderRemoveClassesPreviewStencil >> menuModel: anObject [
84+
menuModel := anObject
85+
]
86+
87+
{ #category : #private }
88+
GtCoderRemoveClassesPreviewStencil >> newRemoveSeveralClassesLabel [
89+
| labelText |
90+
labelText := 'Remove {1} classes' format: {self classesToRemove size}.
91+
^ BrLabel new
92+
margin: (BlInsets all: 10);
93+
aptitude: BrGlamorousLabelAptitude new glamorousRegularFont;
94+
text: labelText asRopedText
95+
]

src/GToolkit-Coder/GtPhlowContext.extension.st

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
Extension { #name : #GtPhlowContext }
22

3+
{ #category : #'*GToolkit-Coder-UI\t' }
4+
GtPhlowContext >> coderSelectedClasses [
5+
^ self optionAt: #coderSelectedClasses ifAbsent: [ #() ]
6+
]
7+
38
{ #category : #'*GToolkit-Coder' }
49
GtPhlowContext >> hasPackageCoder [
510
^ self hasOptionAt: #packageCoder

0 commit comments

Comments
 (0)