• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moosetechnology / MooseIDE / 19034933842

03 Nov 2025 12:38PM UTC coverage: 65.609% (+0.03%) from 65.581%
19034933842

push

github

web-flow
Update README for Moose image instructions

20970 of 31962 relevant lines covered (65.61%)

1.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.44
/src/MooseIDE-CoUsageMap/MiCoUsageMapModel.class.st
1
"
2
A model for the CoUsageMap browser
3
"
4
Class {
5
        #name : 'MiCoUsageMapModel',
6
        #superclass : 'MiAbstractModel',
7
        #instVars : [
8
                'settingsWindow',
9
                'containerEntities',
10
                'selectedEntity',
11
                'methodAttributeCounter',
12
                'innerBoxes',
13
                'containerBoxes',
14
                'widthScale'
15
        ],
16
        #category : 'MooseIDE-CoUsageMap-Model',
17
        #package : 'MooseIDE-CoUsageMap',
18
        #tag : 'Model'
19
}
20

21
{ #category : 'tagging' }
22
MiCoUsageMapModel >> automaticColor [
2✔
23

2✔
24
        self changeTagsDuring: [ 
2✔
25
                self containerBoxes
2✔
26
                        do: [:met | self automaticColorForContainerBox: met ].
2✔
27
        ]
2✔
28
        
2✔
29
]
2✔
30

31
{ #category : 'tagging' }
32
MiCoUsageMapModel >> automaticColorForContainerBox: aMiContainer [
2✔
33
        "inner boxes are grouped by their tag (#groupsByTag)
2✔
34
         If there are several groups, searches for the largest (ignoring the group of untagged)
2✔
35
         then checks whether it size is >= threshold percent of all inner boxes.
2✔
36
         If so, set the tag on aMiContainer"
2✔
37

2✔
38
        | groupsByTag tag |
2✔
39

2✔
40
        groupsByTag := aMiContainer innerBoxes groupedBy: [ :att | att tag ].
2✔
41
        groupsByTag ifEmpty: [ ^ self ].
2✔
42
        
2✔
43
        tag := self largestTag: groupsByTag in: aMiContainer.
2✔
44

2✔
45
        "note: tag could be nil here if we did not find a large enough group"
2✔
46
        self setTag: tag onInnerBox: aMiContainer.
2✔
47

2✔
48
]
2✔
49

50
{ #category : 'tagging' }
51
MiCoUsageMapModel >> changeTagsDuring: aBlockClosure [
2✔
52
        | lastTag |
2✔
53
        lastTag := self selectedTag.
2✔
54
        aBlockClosure value.
2✔
55
        self selectedTag: lastTag
2✔
56
]
2✔
57

58
{ #category : 'private - for tests' }
59
MiCoUsageMapModel >> closeSettings [
×
60
        "used only for closing settings opened in tests"
×
61
        settingsWindow ifNotNil: [ settingsWindow close ]
×
62
]
×
63

64
{ #category : 'accessing' }
65
MiCoUsageMapModel >> containerBoxNamed: aByteString [
2✔
66
        ^ self containerBoxes detect: [ :contr | contr name = aByteString ]
2✔
67
]
2✔
68

69
{ #category : 'accessing' }
70
MiCoUsageMapModel >> containerBoxes [
2✔
71
        ^containerBoxes
2✔
72
]
2✔
73

74
{ #category : 'accessing' }
75
MiCoUsageMapModel >> containerEntities [
2✔
76
        ^ containerEntities
2✔
77
]
2✔
78

79
{ #category : 'accessing' }
80
MiCoUsageMapModel >> containerEntities: aCollection [
2✔
81
        containerEntities := aCollection
2✔
82
]
2✔
83

84
{ #category : 'accessing' }
85
MiCoUsageMapModel >> containerInnerCounter [
2✔
86

2✔
87
        ^ methodAttributeCounter
2✔
88
]
2✔
89

90
{ #category : 'accessing' }
91
MiCoUsageMapModel >> containerInnerCounter: aMiCoMethodAttributeCounter [
2✔
92
        methodAttributeCounter := aMiCoMethodAttributeCounter
2✔
93
]
2✔
94

95
{ #category : 'settings' }
96
MiCoUsageMapModel >> defaultInnerSortBlock [
×
97
        ^ [ :inner1 :inner2 :containr | inner1 name < inner2 name ].
×
98
]
×
99

100
{ #category : 'settings' }
101
MiCoUsageMapModel >> defaultSettings [
×
102
        ^ MiCoUsageMapSettings
×
103
]
×
104

105
{ #category : 'settings' }
106
MiCoUsageMapModel >> defaultSortBlock [
2✔
107
        ^ [ :container1 :container2 | 
2✔
108
                | size1 size2 |
2✔
109
                size1 := container1 innerBoxes size.
2✔
110
                size2 := container2 innerBoxes size.
2✔
111
                size1 = size2 
2✔
112
                        ifTrue: [ container1 name < container2 name ]
2✔
113
                        ifFalse: [ size1 > size2 ]
2✔
114
                 ].
2✔
115
]
2✔
116

117
{ #category : 'settings' }
118
MiCoUsageMapModel >> defaultTester [
2✔
119
        ^ MiCoFromSettingsMethodAttributeTester new
2✔
120
]
2✔
121

122
{ #category : 'accessing' }
123
MiCoUsageMapModel >> entities [
2✔
124
        ^containerEntities
2✔
125
]
2✔
126

127
{ #category : 'actions' }
128
MiCoUsageMapModel >> followEntity: aCollection [
2✔
129

2✔
130
        self containerEntities: aCollection.
2✔
131
        self initializeValues.
2✔
132
        browser runVisualization
2✔
133
]
2✔
134

135
{ #category : 'accessing' }
136
MiCoUsageMapModel >> getBoxFor: object [
2✔
137
        ^(self getContainerBoxFor: object) ifNil: [ self getInnerBoxFor: object ]
2✔
138
]
2✔
139

140
{ #category : 'accessing' }
141
MiCoUsageMapModel >> getContainerBoxFor: object [
2✔
142
        ^self containerBoxes
2✔
143
                detect: [ :box | box mooseEntity = object ]
2✔
144
                ifNone: [ nil ]
2✔
145
]
2✔
146

147
{ #category : 'accessing' }
148
MiCoUsageMapModel >> getInnerBoxFor: object [
2✔
149
        ^self innerBoxes
2✔
150
                detect: [ :inner | inner mooseEntity = object ]
2✔
151
                ifNone: [ nil ]
2✔
152
]
2✔
153

154
{ #category : 'accessing' }
155
MiCoUsageMapModel >> getInnerBoxNamed: aByteString [
2✔
156
        ^ self innerBoxes detect: [ :box | box name = aByteString ]
2✔
157
]
2✔
158

159
{ #category : 'accessing' }
160
MiCoUsageMapModel >> getOrCreateInnerBoxFor: object [
2✔
161

2✔
162
        ^ (self getInnerBoxFor: object)
2✔
163
                ifNil: [ innerBoxes add: (self newInnerBoxFor: object) ]
2✔
164
]
2✔
165

166
{ #category : 'initialization' }
167
MiCoUsageMapModel >> initialize [
2✔
168
        super initialize.
2✔
169

2✔
170
        self containerInnerCounter: self defaultTester
2✔
171
]
2✔
172

173
{ #category : 'initialization' }
174
MiCoUsageMapModel >> initializeContainerBoxes [
2✔
175

2✔
176
        containerBoxes := self containerEntities 
2✔
177
                collect: [ :cont | self newContainerBoxFor: cont ]
2✔
178
                as: OrderedCollection.
2✔
179
]
2✔
180

181
{ #category : 'initialization' }
182
MiCoUsageMapModel >> initializeReferences [
2✔
183
        innerBoxes := OrderedCollection new.
2✔
184

2✔
185
        self containerInnerCounter settings: self settings.
2✔
186
        
2✔
187
        self containerBoxes do: [ :cont | 
2✔
188
                | bag |
2✔
189
                bag := Bag withAll: (self containerInnerCounter allAttributesFor: cont).
2✔
190
                bag doWithOccurrences: [ :innerEntity :count | | in |
2✔
191
                        count > 0 ifTrue: [ 
2✔
192
                                in := self getOrCreateInnerBoxFor: innerEntity.
2✔
193
                                cont addInnerBox: in.
2✔
194
                                in containerBox: cont numberOfUses: count.
2✔
195
                        ].
2✔
196
                ].
2✔
197
        ]
2✔
198
]
2✔
199

200
{ #category : 'initialization' }
201
MiCoUsageMapModel >> initializeScale [
2✔
202
        | allInnerUses range scaleType cls |
2✔
203

2✔
204
        allInnerUses := self containerBoxes flatCollect: [ :cont | 
2✔
205
                cont innerBoxes collect: [ :inner | inner numberOfUses ] ].
2✔
206
        cls := MiCoUsageMapSettings.
2✔
207
        range := cls innerBoxRange.
2✔
208
        scaleType := cls innerBoxScaleType.
2✔
209
        
2✔
210
        widthScale := (scaleType value: NSScale)
2✔
211
                range: {range first. range last}.
2✔
212
        allInnerUses ifEmpty: [ ^ self ].
2✔
213
        widthScale domain: {allInnerUses min. allInnerUses max}.
2✔
214
]
2✔
215

216
{ #category : 'initialization' }
217
MiCoUsageMapModel >> initializeValues [
2✔
218
        self
2✔
219
                initializeContainerBoxes;
2✔
220
                initializeReferences;
2✔
221
                initializeScale.
2✔
222
]
2✔
223

224
{ #category : 'settings' }
225
MiCoUsageMapModel >> innerBoxHeight [
2✔
226
        ^self settings innerBoxHeight
2✔
227
]
2✔
228

229
{ #category : 'settings' }
230
MiCoUsageMapModel >> innerBoxSortBlockCompiled [
2✔
231
        ^self settings innerBoxSortBlockCompiled
2✔
232
]
2✔
233

234
{ #category : 'accessing' }
235
MiCoUsageMapModel >> innerBoxes [
2✔
236
        ^ innerBoxes
2✔
237
]
2✔
238

239
{ #category : 'tagging' }
240
MiCoUsageMapModel >> largestTag: groupsByTag in: containerBox [
2✔
241
        "inner boxes are grouped by their tag (#groupsByTag)
2✔
242
         search the largest of these groups (ignoring the group of untagged)
2✔
243
         then checks whether it size is >= threshold percent of all inner boxes.
2✔
244
         If so, returns the tag of this group"
2✔
245

2✔
246
        | largestGroup tag |
2✔
247
        tag := nil.
2✔
248
        largestGroup := 0.
2✔
249

2✔
250
        groupsByTag keysAndValuesDo: [ :groupTag :group | 
2✔
251
                ((groupTag isNotNil) and: [group size > largestGroup ])
2✔
252
                ifTrue: [
2✔
253
                        tag := groupTag.
2✔
254
                        largestGroup := group size ] ].
2✔
255

2✔
256
        ^(largestGroup / containerBox innerBoxes size) >= self threshold 
2✔
257
                ifTrue: [ tag ]
2✔
258
                ifFalse: [ nil ]
2✔
259
]
2✔
260

261
{ #category : 'accessing' }
262
MiCoUsageMapModel >> miSelectedItem [
×
263
        ^selectedEntity
×
264
]
×
265

266
{ #category : 'instance creation' }
267
MiCoUsageMapModel >> newContainerBoxFor: anObject [
2✔
268
        "| tags |
2✔
269
        tags := anObject allTagAssociations collect: [ :asso | asso tag ].
2✔
270
        tags := tags
2✔
271
                ifEmpty: [ nil ]
2✔
272
                ifNotEmpty: [ tags anyOne ]."
2✔
273
        ^ MiCoContainerBox new
2✔
274
                mooseEntity: anObject;
2✔
275
                yourself
2✔
276
]
2✔
277

278
{ #category : 'instance creation' }
279
MiCoUsageMapModel >> newInnerBoxFor: anObject [
2✔
280
        | tags |
2✔
281
        tags := anObject allTagAssociations collect: [ :asso | asso tag ].
2✔
282
        tags := tags
2✔
283
                ifEmpty: [ nil ]
2✔
284
                ifNotEmpty: [ tags anyOne ].
2✔
285
        ^ MiCoInnerBox new
2✔
286
                mooseEntity: anObject;
2✔
287
                yourself
2✔
288
]
2✔
289

290
{ #category : 'settings' }
291
MiCoUsageMapModel >> openSettings [
2✔
292
        "For now, we handle settings here:
2✔
293
         - create the window 
2✔
294
         - subscribe to be informed when any window is closed closed
2✔
295
         - if this is the setting window that is closed
2✔
296
            - unsubscribe to ALL announcements
2✔
297
            - update the visualization"
2✔
298

2✔
299
        | settingBrowser |
2✔
300
        settingBrowser := SettingBrowser new.
2✔
301
        settingBrowser changePackageSet: (OrderedCollection with:
2✔
302
                         (self packageOrganizer packageNamed:
2✔
303
                                  MiCoUsageMapSettings package name)).
2✔
304
        settingsWindow := settingBrowser open.
2✔
305
        settingsWindow position:
2✔
306
                self currentWorld extent - settingsWindow extent // 2.
2✔
307
        settingBrowser expandAll.
2✔
308

2✔
309
        self currentWorld announcer
2✔
310
                when: WindowClosed
2✔
311
                do: [ :annoucement |
2✔
312
                                annoucement window = settingsWindow ifTrue: [
2✔
313
                                                self currentWorld announcer unsubscribe: self.
2✔
314
                                                browser runVisualization ] ]
2✔
315
                for: self.
2✔
316
        ^ settingsWindow
2✔
317
]
2✔
318

319
{ #category : 'settings' }
320
MiCoUsageMapModel >> outerBoxSortBlockCompiled [
2✔
321
        ^self settings outerBoxSortBlockCompiled
2✔
322
]
2✔
323

324
{ #category : 'events' }
325
MiCoUsageMapModel >> quickTaggingOn: entity [ 
2✔
326

2✔
327
        self selectedTag
2✔
328
        ifNil: [ ^ self ]
2✔
329
        ifNotNil: [ :tag | self setTag: tag onInnerBox: entity ]
2✔
330

2✔
331
]
2✔
332

333
{ #category : 'tagging' }
334
MiCoUsageMapModel >> removeTagOn: aMooseEntity [
2✔
335
        aMooseEntity allTags
2✔
336
                detect: [ :aTag | aTag isHidden not ]
2✔
337
                ifOne: [ :aTag | aTag removeReference: aMooseEntity ]
2✔
338
                ifNone: [ "nothing" ]
2✔
339
]
2✔
340

341
{ #category : 'accessing' }
342
MiCoUsageMapModel >> selectedEntity [
2✔
343
        ^selectedEntity
2✔
344
]
2✔
345

346
{ #category : 'accessing' }
347
MiCoUsageMapModel >> selectedEntity: aMooseEntity [
2✔
348

2✔
349
        selectedEntity := aMooseEntity
2✔
350
]
2✔
351

352
{ #category : 'tagging' }
353
MiCoUsageMapModel >> setTag: aTag onInnerBox: aBox [
2✔
354

2✔
355
        self flag: #FIXME.
2✔
356
        "- #tagEntity:with: already calls #selectedTag:
2✔
357
         - #tagEntity:with: calls #getBoxFor: to find back aBox"
2✔
358

2✔
359
        self selectedTag: aTag.
2✔
360
        self tagEntity: aBox mooseEntity with: aTag
2✔
361
]
2✔
362

363
{ #category : 'settings' }
364
MiCoUsageMapModel >> settings [
2✔
365
        self flag: #FIXME.
2✔
366
        "settings should not be handled by a an other class (with only class side methods"
2✔
367

2✔
368
        ^MiCoUsageMapSettings
2✔
369
]
2✔
370

371
{ #category : 'tagging' }
372
MiCoUsageMapModel >> tagEntity: aMooseEntity with: aTag [
2✔
373
        "entites can have only one tag in this tool"
2✔
374

2✔
375
        self removeTagOn: aMooseEntity.
2✔
376

2✔
377
        super tagEntity: aMooseEntity with: aTag.
2✔
378

2✔
379
        browser updateBoxColor: (self getBoxFor: aMooseEntity) fromTags: aMooseEntity allTags.
2✔
380
        self selectedTag: aTag
2✔
381
]
2✔
382

383
{ #category : 'settings' }
384
MiCoUsageMapModel >> threshold [
2✔
385

2✔
386
        ^self settings threshold75PercentGroup/100.0
2✔
387
]
2✔
388

389
{ #category : 'accessing' }
390
MiCoUsageMapModel >> widthScale [
2✔
391
        ^ widthScale
2✔
392
]
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc