-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathGtCoderModel.class.st
More file actions
278 lines (228 loc) · 7.92 KB
/
GtCoderModel.class.st
File metadata and controls
278 lines (228 loc) · 7.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
"
1. Coder
Is an abstract model of a moldable Coder - a tool for creating and manipulating code.
As a root entity in the hierarchy of coders {{gtClass:GtCoderModel}} do not make any assumptions on the way code is represented. In fact in contrast to {{gtClass:GtSourceCoder}} , it does not know anything about code.
1. # Moldability
Coder is designed to be easily adapted by the users in order to be used in various contexts through so called `add-ons` {{gtClass:GtCoderAddOns}}. Its subclasses can override {{gtMethod:GtCoderModel>>#addOnsClass}} to allow coder to have extra kinds of addons or {{gtMethod:GtCoderModel>>#initializeAddOns:}} to customize the default add-ons.
1. # Add-ons
By default there are the following types of add-ons:
1) {{gtMethod:GtCoderAddOns>>#mainActions}} that are typically added as a button at the bottom of a coder. One of such actions is usually `Save`. Main actions are usually static and should not depend on the source code or context of the coder.
2) {{gtMethod:GtCoderAddOns>>#contextActions}} appear near main actions and are usually contextual, which means they depend on the source code. One example may be a `Play` button that appears when a method is marked with `<gtExample>` pragma.
3) {{gtMethod:GtCoderAddOns>>#contextMenuActions}}is a set of actions that appear in a context menu usually triggered with a right mouse click. `Copy / Cut / Paste` are typical examples of context menu actions.
4) {{gtMethod:GtCoderAddOns>>#shortcuts}}are actions that are triggered due to a pressed key combination when a coder has focus.
"
Class {
#name : #GtCoderModel,
#superclass : #Object,
#traits : 'TGtAnnouncer',
#classTraits : 'TGtAnnouncer classTrait',
#instVars : [
'monitor',
'announcer',
'id',
'attributes',
'extraAddOns'
],
#classVars : [
'UniqueIdGenerator'
],
#category : #'GToolkit-Coder-Coders'
}
{ #category : #addons }
GtCoderModel class >> astExtensionsPragma [
^ #gtAstCoderAddOns:
]
{ #category : #accessing }
GtCoderModel class >> commonExecutionConfiguration [
^ AsyncFutureExecutionConfiguration new
customGroup: #Coder;
maxAmountOfWorkers: 2;
defaultPriority
]
{ #category : #addons }
GtCoderModel class >> contextMenuAddOnsPragma [
^ #gtCoderContextMenuAddOns
]
{ #category : #'class initialization' }
GtCoderModel class >> initialize [
UniqueIdGenerator := BlUniqueIdGenerator new
]
{ #category : #'api - addons' }
GtCoderModel >> addOns [
^ extraAddOns ifNil: [ extraAddOns := self newAddOns ]
]
{ #category : #'api - addons' }
GtCoderModel >> addOnsClass [
^ GtCoderAddOns
]
{ #category : #'api - announcer' }
GtCoderModel >> announcer [
<return: #Announcer>
^ announcer
]
{ #category : #'api - converting' }
GtCoderModel >> asNewCoderModelWithSameSubject [
"Return new coder model with same subject (e.g., package, class, method)"
<return: #GtCoderModel>
^ self subclassResponsibility
]
{ #category : #'api - attributes' }
GtCoderModel >> attributeNamed: aSymbol [
^ attributes notNil
ifTrue: [ attributes at: aSymbol ifAbsent: [ ] ]
]
{ #category : #'api - attributes' }
GtCoderModel >> attributeNamed: aSymbol ifAbsent: aBlock [
^ attributes notNil
ifTrue: [ attributes at: aSymbol ifAbsent: aBlock ]
ifFalse: [ aBlock value ]
]
{ #category : #'api - attributes' }
GtCoderModel >> attributeNamed: aSymbol ifPresent: aPresentBlock ifAbsent: anAbsentBlock [
^ attributes notNil
ifTrue: [ attributes at: aSymbol ifPresent: aPresentBlock ifAbsent: anAbsentBlock ]
ifFalse: [ anAbsentBlock value ]
]
{ #category : #'api - attributes' }
GtCoderModel >> attributeNamed: aSymbol put: anObject [
^ self attributes at: aSymbol put: anObject
]
{ #category : #'api - attributes' }
GtCoderModel >> attributes [
^ attributes ifNil: [ attributes := IdentityDictionary new ]
]
{ #category : #accessing }
GtCoderModel >> coderName [
"Return a short textual name of the coder.
For example, class coder would return a class name, package coder returns a package name."
<return: #String>
^ self class name
]
{ #category : #accessing }
GtCoderModel >> coders [
^ self attributeNamed: #coders
]
{ #category : #accessing }
GtCoderModel >> coders: aCoders [
^ self attributeNamed: #coders put: aCoders
]
{ #category : #'api - actions' }
GtCoderModel >> contextActions [
"Return a collection of contextual actions in the coder. They are renderred separately from mainActions"
<return: #Collection of: #GtCoderAction>
^ self addOns contextActions
]
{ #category : #'api - actions' }
GtCoderModel >> contextMenuActions [
<return: #Collection of: #GtCoderContextMenuAction>
^ self addOns contextMenuActions
]
{ #category : #'mutual exclusion' }
GtCoderModel >> critical: aBlock [
^ monitor critical: aBlock
]
{ #category : #accessing }
GtCoderModel >> expanded [
self deprecated: 'The expansion state was moved to the ViewModel'
]
{ #category : #accessing }
GtCoderModel >> expanded: aBoolean [
self deprecated: 'The expansion state was moved to the ViewModel'
]
{ #category : #views }
GtCoderModel >> gtSystemSubscriptionsViewFor: aView [
<gtView>
^ aView columnedList
title: 'System subscriptions';
items: [ self systemSubscriptions ];
column: 'Announcement' text: [ :each | each announcementClass ];
column: 'Action'
text: [ :each | each action ]
weight: 2
]
{ #category : #accessing }
GtCoderModel >> id [
^ id
]
{ #category : #initialization }
GtCoderModel >> initialize [
super initialize.
id := UniqueIdGenerator generateUniqueId.
monitor := Mutex new.
announcer := GtCoderAnnouncer new
]
{ #category : #initialization }
GtCoderModel >> initializeAddOns: addOns [
]
{ #category : #initialization }
GtCoderModel >> initializeAddOns: addOns viewModel: aCoderViewModel [
self initializeAddOns: addOns
]
{ #category : #initialization }
GtCoderModel >> initializeShortcuts: addOns [
]
{ #category : #subscriptions }
GtCoderModel >> isSubscribedToSystem [
^ SystemAnnouncer uniqueInstance hasSubscriber: self
]
{ #category : #'api - actions' }
GtCoderModel >> mainActions [
"Return a collection of main actions in the coder, for example save"
<return: #Collection of: #GtCoderAction>
^ self addOns mainActions
]
{ #category : #'api - addons' }
GtCoderModel >> newAddOns [
^ self addOnsClass new
]
{ #category : #private }
GtCoderModel >> pragmasNamed: aSymbol inHierarchy: aClass [
| actions |
actions := OrderedCollection new.
aClass withAllSuperclassesDo: [ :each |
actions addAll: ((Pragma allNamed: aSymbol in: each)
reject: [ :eachPragma | actions anySatisfy: [ :otherPragma |
eachPragma methodSelector = otherPragma methodSelector ] ]) ].
actions
sort: (
[ :aPragma | aPragma numArgs isZero
ifFalse: [ aPragma arguments first ]
ifTrue: [ 50 ] ] ascending,
[ :aPragma | aPragma methodSelector ] ascending).
^ actions
]
{ #category : #elements }
GtCoderModel >> previewElement [
"Return a preview element for the Spotter"
<return: #BlElement>
^ self asElement
]
{ #category : #'api - attributes' }
GtCoderModel >> removeAttributeNamed: aSymbol [
attributes isNil
ifTrue: [ ^ self ].
attributes removeKey: aSymbol ifAbsent: [ ]
]
{ #category : #'api - addons' }
GtCoderModel >> requestUpdateAddOns [
"Request addons to update due to some environmental changes (similar to requesting text to restyle).
It is a responsibility of the Coder's Element to start the actual addon update (${method:GtCoderModel>>#updateAddOnsFrom:}$) which may happen in
a background thread, that is why we can not start the update directly - we must have a reference to the element"
self announce: (GtCoderAddOnsUpdateRequest new coder: self)
]
{ #category : #subscriptions }
GtCoderModel >> subscribeToSystem [
"do nothing"
]
{ #category : #subscriptions }
GtCoderModel >> systemSubscriptions [
^ Array
streamContents: [ :aStream |
SystemAnnouncer uniqueInstance subscriptions
subscriptionsOf: self
do: [ :eachSubscription | aStream nextPut: eachSubscription ] ]
]
{ #category : #subscriptions }
GtCoderModel >> unsubscribeFromSystem [
SystemAnnouncer uniqueInstance unsubscribe: self
]