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

moosetechnology / MooseIDE / 19307692782

12 Nov 2025 06:23PM UTC coverage: 65.7% (+0.2%) from 65.543%
19307692782

push

github

web-flow
Merge pull request #1513 from moosetechnology/co-usage-settings

Co usage settings

412 of 438 new or added lines in 19 files covered. (94.06%)

23 existing lines in 4 files now uncovered.

21196 of 32262 relevant lines covered (65.7%)

1.31 hits per line

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

97.68
/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
                'innerBoxes',
12
                'containerBoxes',
13
                'widthScale',
14
                'settings'
15
        ],
16
        #category : 'MooseIDE-CoUsageMap-Model',
17
        #package : 'MooseIDE-CoUsageMap',
18
        #tag : 'Model'
19
}
20

21
{ #category : 'public' }
22
MiCoUsageMapModel >> allAttributesFor: aMiCoMethod [
2✔
23
        "should return a list of associations(a Bag), for each association:
2✔
24
        key is the object
2✔
25
        value is the number of uses of that object is used by aMiCoMethod"
2✔
26

2✔
27
        ^[ self settings innerBoxExtractor new innerEntitiesFor: aMiCoMethod mooseEntity ]
2✔
28
                onErrorDo: [ :ex | ex traceCr. #() ].
2✔
29
]
2✔
30

31
{ #category : 'tagging' }
32
MiCoUsageMapModel >> automaticColor [
2✔
33

2✔
34
        self changeTagsDuring: [ 
2✔
35
                self containerBoxes
2✔
36
                        do: [:met | self automaticColorForContainerBox: met ].
2✔
37
        ]
2✔
38
        
2✔
39
]
2✔
40

41
{ #category : 'tagging' }
42
MiCoUsageMapModel >> automaticColorForContainerBox: aMiContainer [
2✔
43
        "inner boxes are grouped by their tag (#groupsByTag)
2✔
44
         If there are several groups, searches for the largest (ignoring the group of untagged)
2✔
45
         then checks whether it size is >= threshold percent of all inner boxes.
2✔
46
         If so, set the tag on aMiContainer"
2✔
47

2✔
48
        | groupsByTag tag |
2✔
49

2✔
50
        groupsByTag := aMiContainer innerBoxes groupedBy: [ :att | att tag ].
2✔
51
        groupsByTag ifEmpty: [ ^ self ].
2✔
52
        
2✔
53
        tag := self largestTag: groupsByTag in: aMiContainer.
2✔
54

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

2✔
58
]
2✔
59

60
{ #category : 'tagging' }
61
MiCoUsageMapModel >> changeTagsDuring: aBlockClosure [
2✔
62
        | lastTag |
2✔
63
        lastTag := self selectedTag.
2✔
64
        aBlockClosure value.
2✔
65
        self selectedTag: lastTag
2✔
66
]
2✔
67

68
{ #category : 'accessing' }
69
MiCoUsageMapModel >> containerBoxNamed: aByteString [
2✔
70
        ^ self containerBoxes detect: [ :contr | contr name = aByteString ]
2✔
71
]
2✔
72

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

78
{ #category : 'accessing' }
79
MiCoUsageMapModel >> containerEntities [
2✔
80
        ^ containerEntities
2✔
81
]
2✔
82

83
{ #category : 'accessing' }
84
MiCoUsageMapModel >> containerEntities: aCollection [
2✔
85
        containerEntities := aCollection
2✔
86
]
2✔
87

88
{ #category : 'accessing' }
89
MiCoUsageMapModel >> entities [
2✔
90
        ^containerEntities
2✔
91
]
2✔
92

93
{ #category : 'actions' }
94
MiCoUsageMapModel >> followEntity: aCollection [
2✔
95

2✔
96
        self containerEntities: aCollection.
2✔
97
        self initializeValues.
2✔
98
        browser runVisualization
2✔
99
]
2✔
100

101
{ #category : 'accessing' }
102
MiCoUsageMapModel >> getBoxFor: object [
2✔
103
        ^(self getContainerBoxFor: object) ifNil: [ self getInnerBoxFor: object ]
2✔
104
]
2✔
105

106
{ #category : 'accessing' }
107
MiCoUsageMapModel >> getContainerBoxFor: object [
2✔
108
        ^self containerBoxes
2✔
109
                detect: [ :box | box mooseEntity = object ]
2✔
110
                ifNone: [ nil ]
2✔
111
]
2✔
112

113
{ #category : 'accessing' }
114
MiCoUsageMapModel >> getInnerBoxFor: object [
2✔
115
        ^self innerBoxes
2✔
116
                detect: [ :inner | inner mooseEntity = object ]
2✔
117
                ifNone: [ nil ]
2✔
118
]
2✔
119

120
{ #category : 'accessing' }
121
MiCoUsageMapModel >> getInnerBoxNamed: aByteString [
2✔
122
        ^ self innerBoxes detect: [ :box | box name = aByteString ]
2✔
123
]
2✔
124

125
{ #category : 'accessing' }
126
MiCoUsageMapModel >> getOrCreateInnerBoxFor: object [
2✔
127

2✔
128
        ^ (self getInnerBoxFor: object)
2✔
129
                ifNil: [ innerBoxes add: (self newInnerBoxFor: object) ]
2✔
130
]
2✔
131

132
{ #category : 'initialization' }
133
MiCoUsageMapModel >> initialize [
2✔
134
        super initialize.
2✔
135

2✔
136
        settings := MiCoUsageMapSettings new
2✔
137
]
2✔
138

139
{ #category : 'initialization' }
140
MiCoUsageMapModel >> initializeContainerBoxes [
2✔
141

2✔
142
        containerBoxes := self containerEntities 
2✔
143
                collect: [ :cont | self newContainerBoxFor: cont ]
2✔
144
                as: OrderedCollection.
2✔
145
]
2✔
146

147
{ #category : 'initialization' }
148
MiCoUsageMapModel >> initializeReferences [
2✔
149
        innerBoxes := OrderedCollection new.
2✔
150
        
2✔
151
        self containerBoxes do: [ :cont | 
2✔
152
                | bag |
2✔
153
                bag := Bag withAll: (self allAttributesFor: cont).
2✔
154
                bag doWithOccurrences: [ :innerEntity :count | | in |
2✔
155
                        count > 0 ifTrue: [ 
2✔
156
                                in := self getOrCreateInnerBoxFor: innerEntity.
2✔
157
                                cont addInnerBox: in.
2✔
158
                                in containerBox: cont numberOfUses: count.
2✔
159
                        ].
2✔
160
                ].
2✔
161
        ]
2✔
162
]
2✔
163

164
{ #category : 'initialization' }
165
MiCoUsageMapModel >> initializeScale [
2✔
166
        | allInnerUses range scaleType |
2✔
167

2✔
168
        allInnerUses := self containerBoxes flatCollect: [ :cont | 
2✔
169
                cont innerBoxes collect: [ :inner | inner numberOfUses ] ].
2✔
170
        range := self settings innerBoxRange.
2✔
171
        scaleType := self settings innerBoxScaleType.
2✔
172
        
2✔
173
        widthScale := (scaleType value: NSScale)
2✔
174
                range: {range first. range last}.
2✔
175
        allInnerUses ifEmpty: [ ^ self ].
2✔
176
        widthScale domain: {allInnerUses min. allInnerUses max}.
2✔
177
]
2✔
178

179
{ #category : 'initialization' }
180
MiCoUsageMapModel >> initializeValues [
2✔
181
        self
2✔
182
                initializeContainerBoxes;
2✔
183
                initializeReferences;
2✔
184
                initializeScale.
2✔
185
]
2✔
186

187
{ #category : 'settings' }
UNCOV
188
MiCoUsageMapModel >> innerBoxHeight [
×
UNCOV
189
        ^self settings innerBoxHeight
×
UNCOV
190
]
×
191

192
{ #category : 'accessing' }
193
MiCoUsageMapModel >> innerBoxes [
2✔
194
        ^ innerBoxes
2✔
195
]
2✔
196

197
{ #category : 'tagging' }
198
MiCoUsageMapModel >> largestTag: groupsByTag in: containerBox [
2✔
199
        "inner boxes are grouped by their tag (#groupsByTag)
2✔
200
         search the largest of these groups (ignoring the group of untagged)
2✔
201
         then checks whether it size is >= threshold percent of all inner boxes.
2✔
202
         If so, returns the tag of this group"
2✔
203

2✔
204
        | largestGroup tag |
2✔
205
        tag := nil.
2✔
206
        largestGroup := 0.
2✔
207

2✔
208
        groupsByTag keysAndValuesDo: [ :groupTag :group | 
2✔
209
                ((groupTag isNotNil) and: [group size > largestGroup ])
2✔
210
                ifTrue: [
2✔
211
                        tag := groupTag.
2✔
212
                        largestGroup := group size ] ].
2✔
213

2✔
214
        ^(largestGroup / containerBox innerBoxes size) >= self threshold 
2✔
215
                ifTrue: [ tag ]
2✔
216
                ifFalse: [ nil ]
2✔
217
]
2✔
218

219
{ #category : 'accessing' }
220
MiCoUsageMapModel >> miSelectedItem [
×
221
        ^selectedEntity
×
222
]
×
223

224
{ #category : 'instance creation' }
225
MiCoUsageMapModel >> newContainerBoxFor: anObject [
2✔
226
        "| tags |
2✔
227
        tags := anObject allTagAssociations collect: [ :asso | asso tag ].
2✔
228
        tags := tags
2✔
229
                ifEmpty: [ nil ]
2✔
230
                ifNotEmpty: [ tags anyOne ]."
2✔
231
        ^ MiCoContainerBox new
2✔
232
                mooseEntity: anObject;
2✔
233
                yourself
2✔
234
]
2✔
235

236
{ #category : 'instance creation' }
237
MiCoUsageMapModel >> newInnerBoxFor: anObject [
2✔
238
        | tags |
2✔
239
        tags := anObject allTagAssociations collect: [ :asso | asso tag ].
2✔
240
        tags := tags
2✔
241
                ifEmpty: [ nil ]
2✔
242
                ifNotEmpty: [ tags anyOne ].
2✔
243
        ^ MiCoInnerBox new
2✔
244
                mooseEntity: anObject;
2✔
245
                yourself
2✔
246
]
2✔
247

248
{ #category : 'settings' }
249
MiCoUsageMapModel >> openSettings [
2✔
250
        "note: should use default settings infrastructure"
2✔
251

2✔
252
        ^MiCoUsageMapSettingsPresenter new
2✔
253
                settings: settings ;
2✔
254
                specModel: self ;
2✔
255
                openDialog
2✔
256
]
2✔
257

258
{ #category : 'events' }
259
MiCoUsageMapModel >> quickTaggingOn: entity [ 
2✔
260

2✔
261
        self selectedTag
2✔
262
        ifNil: [ ^ self ]
2✔
263
        ifNotNil: [ :tag | self setTag: tag onInnerBox: entity ]
2✔
264

2✔
265
]
2✔
266

267
{ #category : 'actions' }
268
MiCoUsageMapModel >> refreshVisualization [
2✔
269

2✔
270
        self initializeValues.
2✔
271
        browser refresh
2✔
272
]
2✔
273

274
{ #category : 'tagging' }
275
MiCoUsageMapModel >> removeTagOn: aMooseEntity [
2✔
276
        aMooseEntity allTags
2✔
277
                detect: [ :aTag | aTag isHidden not ]
2✔
278
                ifOne: [ :aTag | aTag removeReference: aMooseEntity ]
2✔
279
                ifNone: [ "nothing" ]
2✔
280
]
2✔
281

282
{ #category : 'accessing' }
283
MiCoUsageMapModel >> selectedEntity [
2✔
284
        ^selectedEntity
2✔
285
]
2✔
286

287
{ #category : 'accessing' }
288
MiCoUsageMapModel >> selectedEntity: aMooseEntity [
2✔
289

2✔
290
        selectedEntity := aMooseEntity
2✔
291
]
2✔
292

293
{ #category : 'tagging' }
294
MiCoUsageMapModel >> setTag: aTag onInnerBox: aBox [
2✔
295

2✔
296
        self flag: #FIXME.
2✔
297
        "- #tagEntity:with: already calls #selectedTag:
2✔
298
         - #tagEntity:with: calls #getBoxFor: to find back aBox"
2✔
299

2✔
300
        self selectedTag: aTag.
2✔
301
        self tagEntity: aBox mooseEntity with: aTag
2✔
302
]
2✔
303

304
{ #category : 'settings' }
305
MiCoUsageMapModel >> settings [
2✔
306
        self flag: #FIXME.
2✔
307
        "settings should not be handled by a an other class (with only class side methods"
2✔
308

2✔
309
        ^settings
2✔
310
]
2✔
311

312
{ #category : 'sorting' }
313
MiCoUsageMapModel >> sortContainerBoxes: containerShapes [
2✔
314

2✔
315
        containerShapes sort: [:containerA :containerB || sizeA sizeB |
2✔
316
                sizeA := containerA model numberOfInnerBoxes.
2✔
317
                sizeB := containerB model numberOfInnerBoxes.
2✔
318
                sizeA = sizeB
2✔
319
                        ifTrue: [ containerA model name < containerB model name ]
2✔
320
                        ifFalse: [ sizeA > sizeB ] ].
2✔
321
]
2✔
322

323
{ #category : 'sorting' }
324
MiCoUsageMapModel >> sortInnerShapes: containerShape [
2✔
325

2✔
326
        containerShape innerBoxShapes sort: [:entityA :entityB || sizeA sizeB |
2✔
327
                        sizeA := entityA model numberOfUsesOn: containerShape model.
2✔
328
                        sizeB := entityB model numberOfUsesOn: containerShape model.
2✔
329
                        sizeA = sizeB
2✔
330
                                ifTrue: [ entityA model name < entityB model name ]
2✔
331
                                ifFalse: [ sizeA > sizeB ]
2✔
332
                ]
2✔
333
]
2✔
334

335
{ #category : 'tagging' }
336
MiCoUsageMapModel >> tagEntity: aMooseEntity with: aTag [
2✔
337
        "entites can have only one tag in this tool"
2✔
338

2✔
339
        self removeTagOn: aMooseEntity.
2✔
340

2✔
341
        super tagEntity: aMooseEntity with: aTag.
2✔
342

2✔
343
        browser updateBoxColor: (self getBoxFor: aMooseEntity) fromTags: aMooseEntity allTags.
2✔
344
        self selectedTag: aTag
2✔
345
]
2✔
346

347
{ #category : 'settings' }
348
MiCoUsageMapModel >> threshold [
2✔
349

2✔
350
        ^self settings threshold75PercentGroup/100.0
2✔
351
]
2✔
352

353
{ #category : 'accessing' }
354
MiCoUsageMapModel >> widthScale [
2✔
355
        ^ widthScale
2✔
356
]
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