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

moosetechnology / MooseIDE / 19175383782

07 Nov 2025 05:00PM UTC coverage: 65.887% (+0.07%) from 65.821%
19175383782

push

github

web-flow
Merge pull request #1512 from moosetechnology/cousage-refactor

refactor of co-usage map settings
From class-side methods to instance-side
Also from system settings infrastructure to co-usage specific settings presenter

189 of 203 new or added lines in 7 files covered. (93.1%)

40 existing lines in 3 files now uncovered.

21211 of 32193 relevant lines covered (65.89%)

1.32 hits per line

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

96.18
/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
                'settings'
16
        ],
17
        #category : 'MooseIDE-CoUsageMap-Model',
18
        #package : 'MooseIDE-CoUsageMap',
19
        #tag : 'Model'
20
}
21

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

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

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

2✔
39
        | groupsByTag tag |
2✔
40

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

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

2✔
49
]
2✔
50

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

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

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

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

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

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

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

2✔
88
        ^ methodAttributeCounter
2✔
89
]
2✔
90

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

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

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

113
{ #category : 'settings' }
114
MiCoUsageMapModel >> defaultTester [
2✔
115
        ^ MiCoFromSettingsMethodAttributeTester new
2✔
116
]
2✔
117

118
{ #category : 'accessing' }
119
MiCoUsageMapModel >> entities [
2✔
120
        ^containerEntities
2✔
121
]
2✔
122

123
{ #category : 'actions' }
124
MiCoUsageMapModel >> followEntity: aCollection [
2✔
125

2✔
126
        self containerEntities: aCollection.
2✔
127
        self initializeValues.
2✔
128
        browser runVisualization
2✔
129
]
2✔
130

131
{ #category : 'accessing' }
132
MiCoUsageMapModel >> getBoxFor: object [
2✔
133
        ^(self getContainerBoxFor: object) ifNil: [ self getInnerBoxFor: object ]
2✔
134
]
2✔
135

136
{ #category : 'accessing' }
137
MiCoUsageMapModel >> getContainerBoxFor: object [
2✔
138
        ^self containerBoxes
2✔
139
                detect: [ :box | box mooseEntity = object ]
2✔
140
                ifNone: [ nil ]
2✔
141
]
2✔
142

143
{ #category : 'accessing' }
144
MiCoUsageMapModel >> getInnerBoxFor: object [
2✔
145
        ^self innerBoxes
2✔
146
                detect: [ :inner | inner mooseEntity = object ]
2✔
147
                ifNone: [ nil ]
2✔
148
]
2✔
149

150
{ #category : 'accessing' }
151
MiCoUsageMapModel >> getInnerBoxNamed: aByteString [
2✔
152
        ^ self innerBoxes detect: [ :box | box name = aByteString ]
2✔
153
]
2✔
154

155
{ #category : 'accessing' }
156
MiCoUsageMapModel >> getOrCreateInnerBoxFor: object [
2✔
157

2✔
158
        ^ (self getInnerBoxFor: object)
2✔
159
                ifNil: [ innerBoxes add: (self newInnerBoxFor: object) ]
2✔
160
]
2✔
161

162
{ #category : 'initialization' }
163
MiCoUsageMapModel >> initialize [
2✔
164
        super initialize.
2✔
165

2✔
166
        settings := MiCoUsageMapSettings new.
2✔
167
        self containerInnerCounter: self defaultTester
2✔
168
]
2✔
169

170
{ #category : 'initialization' }
171
MiCoUsageMapModel >> initializeContainerBoxes [
2✔
172

2✔
173
        containerBoxes := self containerEntities 
2✔
174
                collect: [ :cont | self newContainerBoxFor: cont ]
2✔
175
                as: OrderedCollection.
2✔
176
]
2✔
177

178
{ #category : 'initialization' }
179
MiCoUsageMapModel >> initializeReferences [
2✔
180
        innerBoxes := OrderedCollection new.
2✔
181

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

197
{ #category : 'initialization' }
198
MiCoUsageMapModel >> initializeScale [
2✔
199
        | allInnerUses range scaleType |
2✔
200

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

212
{ #category : 'initialization' }
213
MiCoUsageMapModel >> initializeValues [
2✔
214
        self
2✔
215
                initializeContainerBoxes;
2✔
216
                initializeReferences;
2✔
217
                initializeScale.
2✔
218
]
2✔
219

220
{ #category : 'settings' }
221
MiCoUsageMapModel >> innerBoxHeight [
2✔
222
        ^self settings innerBoxHeight
2✔
223
]
2✔
224

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

230
{ #category : 'accessing' }
231
MiCoUsageMapModel >> innerBoxes [
2✔
232
        ^ innerBoxes
2✔
233
]
2✔
234

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

2✔
242
        | largestGroup tag |
2✔
243
        tag := nil.
2✔
244
        largestGroup := 0.
2✔
245

2✔
246
        groupsByTag keysAndValuesDo: [ :groupTag :group | 
2✔
247
                ((groupTag isNotNil) and: [group size > largestGroup ])
2✔
248
                ifTrue: [
2✔
249
                        tag := groupTag.
2✔
250
                        largestGroup := group size ] ].
2✔
251

2✔
252
        ^(largestGroup / containerBox innerBoxes size) >= self threshold 
2✔
253
                ifTrue: [ tag ]
2✔
254
                ifFalse: [ nil ]
2✔
255
]
2✔
256

257
{ #category : 'accessing' }
258
MiCoUsageMapModel >> miSelectedItem [
×
259
        ^selectedEntity
×
260
]
×
261

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

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

286
{ #category : 'settings' }
287
MiCoUsageMapModel >> openSettings [
2✔
288
        "note: should use default settings infrastructure"
2✔
289

2✔
290
        ^MiCoUsageMapGeneralSettingsPresenter new
2✔
291
                settings: settings ;
2✔
292
                openDialog
2✔
293
]
2✔
294

295
{ #category : 'settings' }
296
MiCoUsageMapModel >> outerBoxSortBlockCompiled [
2✔
297
        ^self settings outerBoxSortBlockCompiled
2✔
298
]
2✔
299

300
{ #category : 'events' }
301
MiCoUsageMapModel >> quickTaggingOn: entity [ 
2✔
302

2✔
303
        self selectedTag
2✔
304
        ifNil: [ ^ self ]
2✔
305
        ifNotNil: [ :tag | self setTag: tag onInnerBox: entity ]
2✔
306

2✔
307
]
2✔
308

309
{ #category : 'tagging' }
310
MiCoUsageMapModel >> removeTagOn: aMooseEntity [
2✔
311
        aMooseEntity allTags
2✔
312
                detect: [ :aTag | aTag isHidden not ]
2✔
313
                ifOne: [ :aTag | aTag removeReference: aMooseEntity ]
2✔
314
                ifNone: [ "nothing" ]
2✔
315
]
2✔
316

317
{ #category : 'accessing' }
318
MiCoUsageMapModel >> selectedEntity [
2✔
319
        ^selectedEntity
2✔
320
]
2✔
321

322
{ #category : 'accessing' }
323
MiCoUsageMapModel >> selectedEntity: aMooseEntity [
2✔
324

2✔
325
        selectedEntity := aMooseEntity
2✔
326
]
2✔
327

328
{ #category : 'tagging' }
329
MiCoUsageMapModel >> setTag: aTag onInnerBox: aBox [
2✔
330

2✔
331
        self flag: #FIXME.
2✔
332
        "- #tagEntity:with: already calls #selectedTag:
2✔
333
         - #tagEntity:with: calls #getBoxFor: to find back aBox"
2✔
334

2✔
335
        self selectedTag: aTag.
2✔
336
        self tagEntity: aBox mooseEntity with: aTag
2✔
337
]
2✔
338

339
{ #category : 'settings' }
340
MiCoUsageMapModel >> settings [
2✔
341
        self flag: #FIXME.
2✔
342
        "settings should not be handled by a an other class (with only class side methods"
2✔
343

2✔
344
        ^settings
2✔
345
]
2✔
346

347
{ #category : 'tagging' }
348
MiCoUsageMapModel >> tagEntity: aMooseEntity with: aTag [
2✔
349
        "entites can have only one tag in this tool"
2✔
350

2✔
351
        self removeTagOn: aMooseEntity.
2✔
352

2✔
353
        super tagEntity: aMooseEntity with: aTag.
2✔
354

2✔
355
        browser updateBoxColor: (self getBoxFor: aMooseEntity) fromTags: aMooseEntity allTags.
2✔
356
        self selectedTag: aTag
2✔
357
]
2✔
358

359
{ #category : 'settings' }
360
MiCoUsageMapModel >> threshold [
2✔
361

2✔
362
        ^self settings threshold75PercentGroup/100.0
2✔
363
]
2✔
364

365
{ #category : 'accessing' }
366
MiCoUsageMapModel >> widthScale [
2✔
367
        ^ widthScale
2✔
368
]
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