changeset 52 | 7b48409ae088 |
parent 49 | 6fe62433cfa3 |
child 53 | 2fc78a0165e7 |
51:57c1ccc3d7e0 | 52:7b48409ae088 |
---|---|
1 "{ Package: 'Programming Tools' }" |
|
2 |
|
3 " |
1 " |
4 COPYRIGHT (c) 1989 by Claus Gittinger |
2 COPYRIGHT (c) 1989 by Claus Gittinger |
5 All Rights Reserved |
3 All Rights Reserved |
6 |
4 |
7 This software is furnished under a license and may be used |
5 This software is furnished under a license and may be used |
10 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
11 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
12 hereby transferred. |
10 hereby transferred. |
13 " |
11 " |
14 |
12 |
13 'From Smalltalk/X, Version:2.10.4 on 7-nov-1994 at 14:56:27'! |
|
14 |
|
15 StandardSystemView subclass:#SystemBrowser |
15 StandardSystemView subclass:#SystemBrowser |
16 instanceVariableNames:'classCategoryListView classListView |
16 instanceVariableNames:'classCategoryListView classListView methodCategoryListView |
17 methodCategoryListView methodListView |
17 methodListView classMethodListView codeView classToggle |
18 classMethodListView |
18 instanceToggle currentClassCategory currentClassHierarchy |
19 codeView classToggle instanceToggle |
19 currentClass currentMethodCategory currentMethod currentSelector |
20 currentClassCategory currentClassHierarchy |
20 showInstance actualClass fullClass lastMethodCategory aspect |
21 currentClass |
21 variableListView fullProtocol lockUpdates autoSearch myLabel' |
22 currentMethodCategory currentMethod |
22 classVariableNames:'CheckForInstancesWhenRemovingClasses' |
23 showInstance actualClass fullClass |
23 poolDictionaries:'' |
24 lastMethodCategory aspect variableListView' |
24 category:'Interface-Browsers' |
25 classVariableNames:'' |
|
26 poolDictionaries:'' |
|
27 category:'Interface-Browsers' |
|
28 ! |
25 ! |
29 |
26 |
30 SystemBrowser comment:' |
27 SystemBrowser comment:' |
31 COPYRIGHT (c) 1989 by Claus Gittinger |
28 COPYRIGHT (c) 1989 by Claus Gittinger |
32 All Rights Reserved |
29 All Rights Reserved |
33 |
30 |
34 $Header: /cvs/stx/stx/libtool/Attic/SBrowser.st,v 1.14 1994-10-28 03:29:32 claus Exp $ |
31 $Header: /cvs/stx/stx/libtool/Attic/SBrowser.st,v 1.15 1994-11-17 14:47:02 claus Exp $ |
35 '! |
32 '! |
36 |
33 |
37 !SystemBrowser class methodsFor:'documentation'! |
34 !SystemBrowser class methodsFor:'documentation'! |
38 |
35 |
39 copyright |
36 copyright |
50 " |
47 " |
51 ! |
48 ! |
52 |
49 |
53 version |
50 version |
54 " |
51 " |
55 $Header: /cvs/stx/stx/libtool/Attic/SBrowser.st,v 1.14 1994-10-28 03:29:32 claus Exp $ |
52 $Header: /cvs/stx/stx/libtool/Attic/SBrowser.st,v 1.15 1994-11-17 14:47:02 claus Exp $ |
56 " |
53 " |
57 ! |
54 ! |
58 |
55 |
59 documentation |
56 documentation |
60 " |
57 " |
61 this class implements all kinds of class browsers. |
58 this class implements all kinds of class browsers. |
62 Stypically, it is started with SystemBrowser open, but there are many other startup |
59 Typically, it is started with 'SystemBrowser open', but there are many other |
63 messages, to launch special browsers. |
60 startup messages, to launch special browsers. |
64 See the extra document 'doc/misc/sbrowser.doc' for how to use this browser. |
61 See the categories 'startup' and 'special search startup' in the classes |
62 protocol. |
|
63 |
|
64 Alse, see the extra document 'doc/misc/sbrowser.doc' or the HTML online doc |
|
65 for how to use the browser. |
|
65 |
66 |
66 written winter 89 by claus |
67 written winter 89 by claus |
67 " |
68 " |
68 ! ! |
69 ! ! |
69 |
70 |
70 !SystemBrowser class methodsFor:'general startup'! |
71 !SystemBrowser class methodsFor:'initialization'! |
71 |
72 |
72 open |
73 initialize |
73 "launch a standard browser" |
74 "SystemBrowser configuration; |
74 |
75 (values can be changed from your private startup file)" |
75 ^ self openOnDisplay:Display |
76 |
76 |
77 " |
77 "SystemBrowser open" |
78 setting this to false, the removeClass function will remove |
78 ! |
79 classes WITHOUT checking for instances. Otherwise, |
79 |
80 it will check and let you confirm in case there are instances. |
80 openOnDisplay:aDisplay |
81 Checking for instances may be a bit time consuming, though. |
81 "launch a standard browser on another display. |
82 The default is true - therefore, it will check |
82 Does not work currently - still being developped." |
83 " |
83 |
84 CheckForInstancesWhenRemovingClasses := true |
84 ^ self newWithLabel:(self classResources string:'System Browser') |
85 |
85 setupBlock:[:browser | browser setupForAll] |
86 " |
86 on:aDisplay |
87 CheckForInstancesWhenRemovingClasses := true |
87 |
88 CheckForInstancesWhenRemovingClasses := false |
88 " |
|
89 SystemBrowser openOnDisplay:(XWorkstation new initializeFor:'porty:0') |
|
90 " |
89 " |
91 ! ! |
90 ! ! |
92 |
91 |
93 !SystemBrowser class methodsFor:'startup'! |
92 !SystemBrowser class methodsFor:'startup'! |
94 |
93 |
95 browseFullClasses |
|
96 "launch a browser showing all methods at once" |
|
97 |
|
98 ^ self newWithLabel:'Full Class Browser' |
|
99 setupBlock:[:browser | browser setupForFullClass] |
|
100 |
|
101 "SystemBrowser browseFullClasses" |
|
102 ! |
|
103 |
|
104 browseClassCategory:aClassCategory |
|
105 "launch a browser for all classes under aCategory" |
|
106 |
|
107 ^ self newWithLabel:aClassCategory |
|
108 setupBlock:[:browser | browser setupForClassCategory:aClassCategory] |
|
109 |
|
110 "SystemBrowser browseClassCategory:'Kernel-Objects'" |
|
111 ! |
|
112 |
|
113 browseClass:aClass |
|
114 "launch a browser for aClass" |
|
115 |
|
116 ^ self newWithLabel:aClass name |
|
117 setupBlock:[:browser | browser setupForClass:aClass] |
|
118 |
|
119 "SystemBrowser browseClass:Object" |
|
120 ! |
|
121 |
|
122 browseClassHierarchy:aClass |
|
123 "launch a browser for aClass and all its superclasses" |
|
124 |
|
125 ^ self newWithLabel:(aClass name , '-' , 'hierarchy') |
|
126 setupBlock:[:browser | browser setupForClassHierarchy:aClass] |
|
127 |
|
128 "SystemBrowser browseClassHierarchy:Number" |
|
129 ! |
|
130 |
|
131 browseClasses:aList title:title |
|
132 "launch a browser for all classes in aList" |
|
133 |
|
134 ^ self newWithLabel:title |
|
135 setupBlock:[:browser | browser setupForClassList:aList] |
|
136 |
|
137 " |
|
138 SystemBrowser browseClasses:(Array with:Object |
|
139 with:Float) |
|
140 title:'two classes' |
|
141 " |
|
142 ! |
|
143 |
|
144 browseClass:aClass methodCategory:aCategory |
|
145 "launch a browser for all methods under aCategory in aClass" |
|
146 |
|
147 ^ self newWithLabel:(aClass name , ' ' , aCategory) |
|
148 setupBlock:[:browser | browser setupForClass:aClass methodCategory:aCategory] |
|
149 |
|
150 "SystemBrowser browseClass:String methodCategory:'copying'" |
|
151 ! |
|
152 |
|
153 browseClass:aClass selector:selector |
|
154 "launch a browser for the method at selector in aClass" |
|
155 |
|
156 ^ self newWithLabel:(aClass name , ' ' , selector) |
|
157 setupBlock:[:browser | browser setupForClass:aClass selector:selector] |
|
158 |
|
159 "SystemBrowser browseClass:Object selector:#printString" |
|
160 ! |
|
161 |
|
162 browseMethods:aList title:aString |
94 browseMethods:aList title:aString |
163 "launch a browser for an explicit list of class/selectors" |
95 "launch a browser for an explicit list of class/selectors. |
96 Each entry in the list must consist of the classes name and the selector, |
|
97 separated by spaces. For class methods, the string 'class' must be |
|
98 appended to the classname." |
|
164 |
99 |
165 (aList size == 0) ifTrue:[ |
100 (aList size == 0) ifTrue:[ |
166 self showNoneFound:aString. |
101 self showNoneFound:aString. |
167 ^ nil |
102 ^ nil |
168 ]. |
103 ]. |
173 " |
108 " |
174 SystemBrowser browseMethods:#('Object printOn:' |
109 SystemBrowser browseMethods:#('Object printOn:' |
175 'Collection add:') |
110 'Collection add:') |
176 title:'some methods' |
111 title:'some methods' |
177 " |
112 " |
178 ! |
113 " |
179 |
114 SystemBrowser browseMethods:#('Behavior new:' |
180 browseMethodCategory:aCategory |
115 'Setclass new:') |
181 "launch a browser for all methods where category = aCategory" |
116 title:'some new: methods' |
182 |
117 " |
183 |searchBlock| |
118 |
184 |
|
185 aCategory includesMatchCharacters ifTrue:[ |
|
186 searchBlock := [:c :m :s | aCategory match:m category]. |
|
187 ] ifFalse:[ |
|
188 searchBlock := [:c :m :s | m category = aCategory] |
|
189 ]. |
|
190 |
|
191 self browseMethodsWhere:searchBlock title:('all methods with category of ' , aCategory) |
|
192 |
|
193 " |
|
194 SystemBrowser browseMethodCategory:'printing & storing' |
|
195 SystemBrowser browseMethodCategory:'print*' |
|
196 " |
|
197 ! |
|
198 |
|
199 browseAllSelect:aBlock |
|
200 "launch a browser for all methods where aBlock returns true. |
|
201 The block is called with 3 arguments, class, method and seelctor." |
|
202 |
|
203 ^ self browseMethodsWhere:aBlock title:'selected messages' |
|
204 ! |
|
205 |
|
206 browseMethodsWhere:aBlock title:title |
|
207 "launch a browser for all methods where aBlock returns true. |
|
208 The block is called with 3 arguments, class, method and seelctor." |
|
209 |
|
210 ^ self browseMethodsIn:(Smalltalk allClasses) where:aBlock title:title |
|
211 ! |
|
212 |
|
213 browseMethodsOf:aClass where:aBlock title:title |
|
214 "launch a browser for all instance- and classmethods in aClass |
|
215 where aBlock evaluates to true. |
|
216 The block is called with 3 arguments, class, method and seelctor." |
|
217 |
|
218 ^ self browseMethodsIn:(Array with:aClass) where:aBlock title:title |
|
219 ! |
|
220 |
|
221 browseMethodsFrom:aClass where:aBlock title:title |
|
222 "launch a browser for all instance- and classmethods in aClass |
|
223 and all its subclasses where aBlock evaluates to true. |
|
224 The block is called with 3 arguments, class, method and seelctor." |
|
225 |
|
226 ^ self browseMethodsIn:(aClass withAllSubclasses) where:aBlock title:title |
|
227 ! |
|
228 |
|
229 browseMethodsIn:aCollectionOfClasses where:aBlock title:title |
|
230 "launch a browser for all instance- and classmethods from |
|
231 all classes in aCollectionOfClasses where aBlock evaluates to true. |
|
232 The block is called with 3 arguments, class, method and seelctor." |
|
233 |
|
234 ^ self browseMethodsIn:aCollectionOfClasses inst:true class:true where:aBlock title:title |
|
235 ! |
119 ! |
236 |
120 |
237 browseMethodsIn:aCollectionOfClasses inst:wantInst class:wantClass where:aBlock title:title |
121 browseMethodsIn:aCollectionOfClasses inst:wantInst class:wantClass where:aBlock title:title |
238 "launch a browser for all instance- (if wantInst is true) and/or |
122 "launch a browser for all instance- (if wantInst is true) and/or |
239 classmethods (if wantClass is true) from classes in aCollectionOfClasses, |
123 classmethods (if wantClass is true) from classes in aCollectionOfClasses, |
270 checkedClasses add:cls. |
154 checkedClasses add:cls. |
271 ] |
155 ] |
272 ]. |
156 ]. |
273 |
157 |
274 aCollectionOfClasses do:[:aClass | |
158 aCollectionOfClasses do:[:aClass | |
159 " |
|
160 output disabled - it slows down things too much (when searching for |
|
161 implementors or senders) |
|
162 " |
|
275 "/ Transcript show:'searching '; show:aClass name; showCr:' ...'; endEntry. |
163 "/ Transcript show:'searching '; show:aClass name; showCr:' ...'; endEntry. |
276 wantInst ifTrue:[checkBlock value:aClass]. |
164 wantInst ifTrue:[checkBlock value:aClass]. |
277 wantClass ifTrue:[checkBlock value:(aClass class)]. |
165 wantClass ifTrue:[checkBlock value:(aClass class)]. |
278 Processor yield |
166 Processor yield |
279 ] |
167 ] |
280 ]. |
168 ]. |
281 |
169 |
282 ^ self browseMethods:list title:title |
170 ^ self browseMethods:list title:title |
283 ! |
171 ! |
284 |
172 |
173 browseMethodsIn:aCollectionOfClasses where:aBlock title:title |
|
174 "launch a browser for all instance- and classmethods from |
|
175 all classes in aCollectionOfClasses where aBlock evaluates to true. |
|
176 The block is called with 3 arguments, class, method and seelctor." |
|
177 |
|
178 ^ self browseMethodsIn:aCollectionOfClasses inst:true class:true where:aBlock title:title |
|
179 ! |
|
180 |
|
181 browseClassCategory:aClassCategory |
|
182 "launch a browser for all classes under aCategory" |
|
183 |
|
184 ^ self newWithLabel:aClassCategory |
|
185 setupBlock:[:browser | browser setupForClassCategory:aClassCategory] |
|
186 |
|
187 "SystemBrowser browseClassCategory:'Kernel-Objects'" |
|
188 ! |
|
189 |
|
190 browseFullClasses |
|
191 "launch a browser showing all methods at once" |
|
192 |
|
193 ^ self newWithLabel:'Full Class Browser' |
|
194 setupBlock:[:browser | browser setupForFullClass] |
|
195 |
|
196 "SystemBrowser browseFullClasses" |
|
197 ! |
|
198 |
|
199 browseClass:aClass |
|
200 "launch a browser for aClass" |
|
201 |
|
202 ^ self newWithLabel:aClass name |
|
203 setupBlock:[:browser | browser setupForClass:aClass] |
|
204 |
|
205 "SystemBrowser browseClass:Object" |
|
206 ! |
|
207 |
|
208 browseClass:aClass selector:selector |
|
209 "launch a browser for the method at selector in aClass" |
|
210 |
|
211 ^ self |
|
212 newWithLabel:(aClass name , ' ' , selector , ' ' , selector) |
|
213 setupBlock:[:browser | browser setupForClass:aClass selector:selector] |
|
214 |
|
215 " |
|
216 SystemBrowser browseClass:Object selector:#printString |
|
217 " |
|
218 ! |
|
219 |
|
220 browseClassHierarchy:aClass |
|
221 "launch a browser for aClass and all its superclasses. |
|
222 this is different from the fullProtocol browser." |
|
223 |
|
224 ^ self newWithLabel:(aClass name , '-' , 'hierarchy') |
|
225 setupBlock:[:browser | browser setupForClassHierarchy:aClass] |
|
226 |
|
227 " |
|
228 SystemBrowser browseClassHierarchy:Number |
|
229 " |
|
230 ! |
|
231 |
|
232 browseFullClassProtocol:aClass |
|
233 "launch a browser for aClasses full protocol. |
|
234 This is different from hierarchy browsing." |
|
235 |
|
236 ^ self newWithLabel:(aClass name , '-' , 'full protocol') |
|
237 setupBlock:[:browser | browser setupForFullClassProtocol:aClass] |
|
238 |
|
239 " |
|
240 SystemBrowser browseFullClassProtocol:Number |
|
241 " |
|
242 ! |
|
243 |
|
244 browseClasses:aList title:title |
|
245 "launch a browser for all classes in aList" |
|
246 |
|
247 ^ self newWithLabel:title |
|
248 setupBlock:[:browser | browser setupForClassList:aList] |
|
249 |
|
250 " |
|
251 SystemBrowser browseClasses:(Array with:Object |
|
252 with:Float) |
|
253 title:'two classes' |
|
254 " |
|
255 ! |
|
256 |
|
257 browseClass:aClass methodCategory:aCategory |
|
258 "launch a browser for all methods under aCategory in aClass" |
|
259 |
|
260 ^ self newWithLabel:(aClass name , ' ' , aCategory) |
|
261 setupBlock:[:browser | browser setupForClass:aClass methodCategory:aCategory] |
|
262 |
|
263 "SystemBrowser browseClass:String methodCategory:'copying'" |
|
264 ! |
|
265 |
|
266 browseMethodCategory:aCategory |
|
267 "launch a browser for all methods where category = aCategory" |
|
268 |
|
269 |searchBlock| |
|
270 |
|
271 aCategory includesMatchCharacters ifTrue:[ |
|
272 searchBlock := [:c :m :s | aCategory match:m category]. |
|
273 ] ifFalse:[ |
|
274 searchBlock := [:c :m :s | m category = aCategory] |
|
275 ]. |
|
276 |
|
277 self browseMethodsWhere:searchBlock title:('all methods with category of ' , aCategory) |
|
278 |
|
279 " |
|
280 SystemBrowser browseMethodCategory:'printing & storing' |
|
281 SystemBrowser browseMethodCategory:'print*' |
|
282 " |
|
283 ! |
|
284 |
|
285 browseAllSelect:aBlock |
|
286 "launch a browser for all methods where aBlock returns true. |
|
287 The block is called with 3 arguments, class, method and seelctor." |
|
288 |
|
289 ^ self browseMethodsWhere:aBlock title:'selected messages' |
|
290 |
|
291 " |
|
292 SystemBrowser browseAllSelect:[:aClass :aMethod :selector | selector numArgs == 3] |
|
293 " |
|
294 ! |
|
295 |
|
296 browseMethodsWhere:aBlock title:title |
|
297 "launch a browser for all methods where aBlock returns true. |
|
298 The block is called with 3 arguments, class, method and seelctor." |
|
299 |
|
300 ^ self browseMethodsIn:(Smalltalk allClasses) where:aBlock title:title |
|
301 ! |
|
302 |
|
303 browseMethodsOf:aClass where:aBlock title:title |
|
304 "launch a browser for all instance- and classmethods in aClass |
|
305 where aBlock evaluates to true. |
|
306 The block is called with 3 arguments, class, method and seelctor." |
|
307 |
|
308 ^ self browseMethodsIn:(Array with:aClass) where:aBlock title:title |
|
309 ! |
|
310 |
|
311 browseMethodsFrom:aClass where:aBlock title:title |
|
312 "launch a browser for all instance- and classmethods in aClass |
|
313 and all its subclasses where aBlock evaluates to true. |
|
314 The block is called with 3 arguments, class, method and seelctor." |
|
315 |
|
316 ^ self browseMethodsIn:(aClass withAllSubclasses) where:aBlock title:title |
|
317 ! |
|
318 |
|
285 browseInstMethodsOf:aClass where:aBlock title:title |
319 browseInstMethodsOf:aClass where:aBlock title:title |
286 "launch a browser for all instance methods in aClass |
320 "launch a browser for all instance methods in aClass |
287 where aBlock evaluates to true" |
321 where aBlock evaluates to true" |
288 |
322 |
289 ^ self browseMethodsIn:(Array with:aClass) inst:true class:false where:aBlock title:title |
323 ^ self browseMethodsIn:(Array with:aClass) inst:true class:false where:aBlock title:title |
290 ! |
324 ! |
291 |
325 |
326 browseInstMethodsIn:aCollectionOfClasses where:aBlock title:title |
|
327 "launch a browser for all instance methods of all classes in |
|
328 aCollectionOfClasses where aBlock evaluates to true" |
|
329 |
|
330 ^ self browseMethodsIn:aCollectionOfClasses inst:true class:false |
|
331 where:aBlock title:title |
|
332 ! |
|
333 |
|
292 browseInstMethodsFrom:aClass where:aBlock title:title |
334 browseInstMethodsFrom:aClass where:aBlock title:title |
293 "launch a browser for all instance methods in aClass and all subclasses |
335 "launch a browser for all instance methods in aClass and all subclasses |
294 where aBlock evaluates to true" |
336 where aBlock evaluates to true" |
295 |
337 |
296 ^ self browseMethodsIn:(aClass withAllSubclasses) inst:true class:false where:aBlock title:title |
338 ^ self browseMethodsIn:(aClass withAllSubclasses) inst:true class:false where:aBlock title:title |
297 ! |
339 ! |
298 |
340 |
299 browseInstMethodsIn:aCollectionOfClasses where:aBlock title:title |
341 browseFullClassHierarchy:aClass |
300 "launch a browser for all instance methods of all classes in |
342 "launch a browser for aClass and all its superclasses" |
301 aCollectionOfClasses where aBlock evaluates to true" |
343 |
302 |
344 ^ self newWithLabel:(aClass name , '-' , 'full protocol') |
303 ^ self browseMethodsIn:aCollectionOfClasses inst:true class:false |
345 setupBlock:[:browser | browser setupForFullClassHierarchy:aClass] |
304 where:aBlock title:title |
346 |
347 " |
|
348 SystemBrowser browseFullClassHierarchy:Number |
|
349 " |
|
305 ! ! |
350 ! ! |
306 |
351 |
307 !SystemBrowser class methodsFor:'special search startup'! |
352 !SystemBrowser class methodsFor:'special search startup'! |
308 |
|
309 browseImplementorsOf:aSelectorString in:aCollectionOfClasses title:title |
|
310 "launch a browser for all implementors of aSelector in |
|
311 the classes contained in aCollectionOfClasses and its metaclasses" |
|
312 |
|
313 |list sel| |
|
314 |
|
315 list := OrderedCollection new. |
|
316 |
|
317 ((aSelectorString ~= '*') and:[aSelectorString includesMatchCharacters]) ifTrue:[ |
|
318 "a matchString" |
|
319 |
|
320 aCollectionOfClasses do:[:aClass | |
|
321 aClass selectorArray do:[:aSelector | |
|
322 (aSelectorString match:aSelector) ifTrue:[ |
|
323 list add:(aClass name , ' ' , aSelector) |
|
324 ] |
|
325 ]. |
|
326 aClass class selectorArray do:[:aSelector | |
|
327 (aSelectorString match:aSelector) ifTrue:[ |
|
328 list add:(aClass name , 'class ' , aSelector) |
|
329 ] |
|
330 ] |
|
331 ] |
|
332 ] ifFalse:[ |
|
333 "can do a faster search" |
|
334 |
|
335 aSelectorString knownAsSymbol ifFalse:[ |
|
336 self showNoneFound:title. |
|
337 ^ nil |
|
338 ]. |
|
339 |
|
340 sel := aSelectorString asSymbol. |
|
341 aCollectionOfClasses do:[:aClass | |
|
342 (aClass implements:sel) ifTrue:[ |
|
343 list add:(aClass name , ' ' , aSelectorString) |
|
344 ]. |
|
345 (aClass class implements:sel) ifTrue:[ |
|
346 list add:(aClass name , 'class ' , aSelectorString) |
|
347 ] |
|
348 ] |
|
349 ]. |
|
350 ^ self browseMethods:list title:title |
|
351 |
|
352 " |
|
353 SystemBrowser browseImplementorsOf:#+ |
|
354 in:(Array with:Number |
|
355 with:Float |
|
356 with:SmallInteger) |
|
357 title:'some implementors of +' |
|
358 " |
|
359 ! |
|
360 |
|
361 browseImplementorsOf:aSelectorString |
|
362 "launch a browser for all implementors of aSelector" |
|
363 |
|
364 ^ self browseImplementorsOf:aSelectorString |
|
365 in:(Smalltalk allClasses) |
|
366 title:('implementors of: ' , aSelectorString) |
|
367 |
|
368 " |
|
369 SystemBrowser browseImplementorsOf:#+ |
|
370 " |
|
371 ! |
|
372 |
|
373 browseImplementorsOf:aSelectorString under:aClass |
|
374 "launch a browser for all implementors of aSelector in aClass |
|
375 and its subclasses" |
|
376 |
|
377 ^ self browseImplementorsOf:aSelectorString |
|
378 in:(aClass withAllSubclasses) |
|
379 title:('implementors of: ' , |
|
380 aSelectorString , |
|
381 ' (in or below ' , aClass name , ')') |
|
382 |
|
383 " |
|
384 SystemBrowser browseImplementorsOf:#+ under:Integer |
|
385 " |
|
386 ! |
|
387 |
353 |
388 browseAllCallsOn:aSelectorString in:aCollectionOfClasses title:title |
354 browseAllCallsOn:aSelectorString in:aCollectionOfClasses title:title |
389 "launch a browser for all senders of aSelector in aCollectionOfClasses" |
355 "launch a browser for all senders of aSelector in aCollectionOfClasses" |
390 |
356 |
391 |sel browser searchBlock| |
357 |sel browser searchBlock| |
424 where:[:class :method :s | method sends:sel] |
390 where:[:class :method :s | method sends:sel] |
425 title:title |
391 title:title |
426 ]. |
392 ]. |
427 |
393 |
428 browser notNil ifTrue:[ |
394 browser notNil ifTrue:[ |
429 browser setSearchPattern:aSelectorString |
395 |s| |
396 |
|
397 " |
|
398 kludge for now, if its a multipart selector, |
|
399 no easy search is (as yet) possible |
|
400 " |
|
401 s := aSelectorString. |
|
402 (s includes:$:) ifTrue:[ |
|
403 s := s copyTo:(s indexOf:$:) |
|
404 ]. |
|
405 browser autoSearch:s |
|
430 ]. |
406 ]. |
431 ^ browser |
407 ^ browser |
408 ! |
|
409 |
|
410 browseImplementorsOf:aSelectorString |
|
411 "launch a browser for all implementors of aSelector" |
|
412 |
|
413 ^ self browseImplementorsOf:aSelectorString |
|
414 in:(Smalltalk allClasses) |
|
415 title:('implementors of: ' , aSelectorString) |
|
416 |
|
417 " |
|
418 SystemBrowser browseImplementorsOf:#+ |
|
419 " |
|
420 ! |
|
421 |
|
422 browseImplementorsOf:aSelectorString in:aCollectionOfClasses title:title |
|
423 "launch a browser for all implementors of aSelector in |
|
424 the classes contained in aCollectionOfClasses and its metaclasses" |
|
425 |
|
426 |list sel| |
|
427 |
|
428 list := OrderedCollection new. |
|
429 |
|
430 ((aSelectorString ~= '*') and:[aSelectorString includesMatchCharacters]) ifTrue:[ |
|
431 "a matchString" |
|
432 |
|
433 aCollectionOfClasses do:[:aClass | |
|
434 aClass selectorArray do:[:aSelector | |
|
435 (aSelectorString match:aSelector) ifTrue:[ |
|
436 list add:(aClass name , ' ' , aSelector) |
|
437 ] |
|
438 ]. |
|
439 aClass class selectorArray do:[:aSelector | |
|
440 (aSelectorString match:aSelector) ifTrue:[ |
|
441 list add:(aClass name , 'class ' , aSelector) |
|
442 ] |
|
443 ] |
|
444 ] |
|
445 ] ifFalse:[ |
|
446 "can do a faster search" |
|
447 |
|
448 aSelectorString knownAsSymbol ifFalse:[ |
|
449 self showNoneFound:title. |
|
450 ^ nil |
|
451 ]. |
|
452 |
|
453 sel := aSelectorString asSymbol. |
|
454 aCollectionOfClasses do:[:aClass | |
|
455 (aClass implements:sel) ifTrue:[ |
|
456 list add:(aClass name , ' ' , aSelectorString) |
|
457 ]. |
|
458 (aClass class implements:sel) ifTrue:[ |
|
459 list add:(aClass name , 'class ' , aSelectorString) |
|
460 ] |
|
461 ] |
|
462 ]. |
|
463 ^ self browseMethods:list title:title |
|
464 |
|
465 " |
|
466 SystemBrowser browseImplementorsOf:#+ |
|
467 in:(Array with:Number |
|
468 with:Float |
|
469 with:SmallInteger) |
|
470 title:'some implementors of +' |
|
471 " |
|
432 ! |
472 ! |
433 |
473 |
434 browseAllCallsOn:aSelectorString |
474 browseAllCallsOn:aSelectorString |
435 "launch a browser for all senders of aSelector" |
475 "launch a browser for all senders of aSelector" |
436 |
476 |
452 aSelectorString , |
492 aSelectorString , |
453 ' (in or below ' , aClass name , ')') |
493 ' (in or below ' , aClass name , ')') |
454 |
494 |
455 " |
495 " |
456 SystemBrowser browseAllCallsOn:#+ under:Number |
496 SystemBrowser browseAllCallsOn:#+ under:Number |
497 " |
|
498 ! |
|
499 |
|
500 browseImplementorsOf:aSelectorString under:aClass |
|
501 "launch a browser for all implementors of aSelector in aClass |
|
502 and its subclasses" |
|
503 |
|
504 ^ self browseImplementorsOf:aSelectorString |
|
505 in:(aClass withAllSubclasses) |
|
506 title:('implementors of: ' , |
|
507 aSelectorString , |
|
508 ' (in or below ' , aClass name , ')') |
|
509 |
|
510 " |
|
511 SystemBrowser browseImplementorsOf:#+ under:Integer |
|
457 " |
512 " |
458 ! |
513 ! |
459 |
514 |
460 browseForSymbol:aSymbol title:title warnIfNone:doWarn |
515 browseForSymbol:aSymbol title:title warnIfNone:doWarn |
461 "launch a browser for all methods referencing aSymbol" |
516 "launch a browser for all methods referencing aSymbol" |
505 found |
560 found |
506 ]. |
561 ]. |
507 ]. |
562 ]. |
508 browser := self browseMethodsWhere:[:c :m :s | searchBlock value:(m literals)] title:title. |
563 browser := self browseMethodsWhere:[:c :m :s | searchBlock value:(m literals)] title:title. |
509 browser notNil ifTrue:[ |
564 browser notNil ifTrue:[ |
510 browser setSearchPattern:aSymbol |
565 browser autoSearch:aSymbol |
511 ]. |
566 ]. |
512 ^ browser |
567 ^ browser |
513 ! |
568 ! |
514 |
569 |
515 browseForSymbol:aSymbol |
570 filterToSearchInstRefsTo:varName modificationsOnly:modsOnly |
516 "launch a browser for all methods referencing aSymbol" |
571 "return a block to search for instvar accesses" |
517 |
572 |
518 ^ self browseForSymbol:aSymbol title:('users of ' , aSymbol) warnIfNone:true |
573 |searchBlock| |
519 ! |
|
520 |
|
521 browseReferendsOf:aGlobalName warnIfNone:doWarn |
|
522 "launch a browser for all methods referencing a global |
|
523 named aGlobalName. |
|
524 " |
|
525 |
|
526 ^ self browseForSymbol:aGlobalName title:('users of: ' , aGlobalName) warnIfNone:doWarn |
|
527 ! |
|
528 |
|
529 browseReferendsOf:aGlobalName |
|
530 "launch a browser for all methods referencing a global |
|
531 named aGlobalName. |
|
532 " |
|
533 |
|
534 ^ self browseReferendsOf:aGlobalName warnIfNone:true |
|
535 |
|
536 " |
|
537 Browser browseReferendsOf:#Transcript |
|
538 " |
|
539 ! |
|
540 |
|
541 browseForString:aString in:aCollectionOfClasses |
|
542 "launch a browser for all methods in aCollectionOfClasses |
|
543 containing a string-constant" |
|
544 |
|
545 |browser searchBlock title| |
|
546 |
|
547 title := 'methods containing: ' , aString displayString. |
|
548 |
|
549 (aString includesMatchCharacters) ifTrue:[ |
|
550 "a matchString" |
|
551 searchBlock := [:lits | |
|
552 |found| |
|
553 |
|
554 found := false. |
|
555 lits notNil ifTrue:[ |
|
556 lits do:[:aLiteral | |
|
557 found ifFalse:[ |
|
558 (aLiteral isMemberOf:String) ifTrue:[ |
|
559 found := (aString match:aLiteral) |
|
560 ] |
|
561 ] |
|
562 ] |
|
563 ]. |
|
564 found |
|
565 ]. |
|
566 ] ifFalse:[ |
|
567 searchBlock := [:lits | |
|
568 |found| |
|
569 |
|
570 found := false. |
|
571 lits notNil ifTrue:[ |
|
572 lits do:[:aLiteral | |
|
573 found ifFalse:[ |
|
574 (aLiteral isMemberOf:String) ifTrue:[ |
|
575 found := (aLiteral = aString) |
|
576 ] |
|
577 ] |
|
578 ] |
|
579 ]. |
|
580 found |
|
581 ]. |
|
582 ]. |
|
583 browser := self browseMethodsIn:aCollectionOfClasses |
|
584 where:[:c :m :s | searchBlock value:(m literals)] |
|
585 title:title. |
|
586 |
|
587 browser notNil ifTrue:[ |
|
588 browser setSearchPattern:aString |
|
589 ]. |
|
590 ^ browser |
|
591 |
|
592 "SystemBrowser browseForString:'*all*'" |
|
593 "SystemBrowser browseForString:'*should*'" |
|
594 "SystemBrowser browseForString:'*[eE]rror*'" |
|
595 ! |
|
596 |
|
597 browseForString:aString |
|
598 "launch a browser for all methods containing a string" |
|
599 |
|
600 ^ self browseForString:aString in:(Smalltalk allClasses) |
|
601 ! |
|
602 |
|
603 aproposSearch:aString in:aCollectionOfClasses |
|
604 "browse all methods, which have aString in their selector or |
|
605 in the methods comment. |
|
606 This is relatively slow, since all source must be processed." |
|
607 |
|
608 |matchString list| |
|
609 |
|
610 matchString := '*' , aString , '*'. |
|
611 |
|
612 list := OrderedCollection new. |
|
613 |
|
614 ^ self browseMethodsIn:aCollectionOfClasses |
|
615 where:[:class :method :sel | |
|
616 (matchString match:sel) ifTrue:[ |
|
617 list add:(class name , '>>' , sel) |
|
618 ] ifFalse:[ |
|
619 (matchString match:(method comment)) ifTrue:[ |
|
620 list add:(class name , '>>' , sel) |
|
621 ] |
|
622 ]. |
|
623 Processor yield. |
|
624 ] |
|
625 title:('apropos: ' , aString) |
|
626 |
|
627 "SystemBrowser aproposSearch:'append'" |
|
628 "SystemBrowser aproposSearch:'add'" |
|
629 "SystemBrowser aproposSearch:'sort'" |
|
630 ! |
|
631 |
|
632 aproposSearch:aString |
|
633 "browse all methods, which have aString in their selector or |
|
634 in the methods comment. |
|
635 This is relatively slow, since all source must be processed." |
|
636 |
|
637 ^ self aproposSearch:aString in:(Smalltalk allClasses) |
|
638 ! |
|
639 |
|
640 browseInstRefsTo:varName in:aCollectionOfClasses modificationsOnly:modsOnly title:title |
|
641 "launch a browser for all methods in aClass where the instVar named |
|
642 varName is referenced; if modsOnly is true, browse only methods where the |
|
643 instvar is modified" |
|
644 |
|
645 |searchBlock browser needMatch| |
|
646 |
|
647 needMatch := varName includesMatchCharacters. |
|
648 |
574 |
649 searchBlock := [:c :m :s | |
575 searchBlock := [:c :m :s | |
650 |src result parser instvars| |
576 |src result parser instvars needMatch| |
577 |
|
578 needMatch := varName includesMatchCharacters. |
|
651 |
579 |
652 src := m source. |
580 src := m source. |
653 src isNil ifTrue:[ |
581 src isNil ifTrue:[ |
654 result := false |
582 result := false |
655 ] ifFalse:[ |
583 ] ifFalse:[ |
684 ]. |
612 ]. |
685 ]. |
613 ]. |
686 Processor yield. |
614 Processor yield. |
687 result |
615 result |
688 ]. |
616 ]. |
689 browser := self browseInstMethodsIn:aCollectionOfClasses where:searchBlock title:title. |
617 ^ searchBlock |
618 ! |
|
619 |
|
620 browseForSymbol:aSymbol |
|
621 "launch a browser for all methods referencing aSymbol" |
|
622 |
|
623 ^ self browseForSymbol:aSymbol title:('users of ' , aSymbol) warnIfNone:true |
|
624 ! |
|
625 |
|
626 browseReferendsOf:aGlobalName warnIfNone:doWarn |
|
627 "launch a browser for all methods referencing a global |
|
628 named aGlobalName. |
|
629 " |
|
630 |
|
631 ^ self browseForSymbol:aGlobalName title:('users of: ' , aGlobalName) warnIfNone:doWarn |
|
632 ! |
|
633 |
|
634 browseReferendsOf:aGlobalName |
|
635 "launch a browser for all methods referencing a global |
|
636 named aGlobalName. |
|
637 " |
|
638 |
|
639 ^ self browseReferendsOf:aGlobalName warnIfNone:true |
|
640 |
|
641 " |
|
642 Browser browseReferendsOf:#Transcript |
|
643 " |
|
644 ! |
|
645 |
|
646 browseUsesOf:aClass |
|
647 |dict owners offsets |
|
648 sz "{ Class: SmallInteger }" |
|
649 n "{ Class: SmallInteger }" |
|
650 removeSet newDict| |
|
651 |
|
652 owners := ObjectMemory whoReferencesInstancesOf:aClass. |
|
653 |
|
654 " |
|
655 collect set of offsets in dict; key is class |
|
656 " |
|
657 dict := IdentityDictionary new. |
|
658 owners do:[:someObject | |
|
659 |cls create| |
|
660 |
|
661 someObject isContext ifFalse:[ |
|
662 " |
|
663 someObject refers to an instance of aClass; |
|
664 find out, which instVar(s) |
|
665 " |
|
666 cls := someObject class. |
|
667 cls ~~ Array ifTrue:[ |
|
668 n := cls instSize. |
|
669 create := [|s| s := Set new. dict at:cls put:s. s]. |
|
670 |
|
671 1 to:n do:[:i | |
|
672 |ref| |
|
673 |
|
674 ref := someObject instVarAt:i. |
|
675 (ref isMemberOf:aClass) ifTrue:[ |
|
676 offsets := dict at:cls ifAbsent:create. |
|
677 offsets add:i. |
|
678 ] |
|
679 ]. |
|
680 cls isVariable ifTrue:[ |
|
681 cls isPointers ifTrue:[ |
|
682 | idx "{ Class: SmallInteger }" | |
|
683 |
|
684 sz := someObject basicSize. |
|
685 idx := 1. |
|
686 [idx <= sz] whileTrue:[ |
|
687 |ref| |
|
688 |
|
689 ref := someObject basicAt:idx. |
|
690 (ref isMemberOf:aClass) ifTrue:[ |
|
691 offsets := dict at:cls ifAbsent:create. |
|
692 offsets add:0. |
|
693 idx := sz |
|
694 ]. |
|
695 idx := idx + 1 |
|
696 ] |
|
697 ] |
|
698 ] |
|
699 ] |
|
700 ] |
|
701 ]. |
|
702 |
|
703 " |
|
704 merge with superclass refs |
|
705 " |
|
706 dict keysAndValuesDo:[:cls :set | |
|
707 cls allSuperclasses do:[:aSuperclass | |
|
708 |superSet| |
|
709 |
|
710 superSet := dict at:aSuperclass ifAbsent:[]. |
|
711 superSet notNil ifTrue:[ |
|
712 |removeSet| |
|
713 |
|
714 superSet := dict at:aSuperclass. |
|
715 removeSet := Set new. |
|
716 set do:[:offset | |
|
717 (superSet includes:offset) ifTrue:[ |
|
718 removeSet add:offset |
|
719 ] |
|
720 ]. |
|
721 set removeAll:removeSet |
|
722 ] |
|
723 ] |
|
724 ]. |
|
725 |
|
726 " |
|
727 remove empty ones |
|
728 " |
|
729 removeSet := Set new. |
|
730 dict keysAndValuesDo:[:cls :set | |
|
731 set isEmpty ifTrue:[ |
|
732 removeSet add:cls |
|
733 ] |
|
734 ]. |
|
735 removeSet do:[:cls | |
|
736 dict removeKey:cls |
|
737 ]. |
|
738 |
|
739 " |
|
740 replace the indices by real names |
|
741 " |
|
742 newDict := IdentityDictionary new. |
|
743 dict keysAndValuesDo:[:cls :set | |
|
744 |newSet names| |
|
745 |
|
746 names := cls allInstVarNames. |
|
747 newSet := set collect:[:index | |
|
748 index == 0 ifTrue:['*indexed*'] ifFalse:[names at:index]. |
|
749 ]. |
|
750 newDict at:cls put:newSet |
|
751 ]. |
|
752 |
|
753 newDict inspect |
|
754 |
|
755 ! |
|
756 |
|
757 browseForString:aString in:aCollectionOfClasses |
|
758 "launch a browser for all methods in aCollectionOfClasses |
|
759 containing a string-constant" |
|
760 |
|
761 |browser searchBlock title| |
|
762 |
|
763 title := 'methods containing: ' , aString displayString. |
|
764 |
|
765 (aString includesMatchCharacters) ifTrue:[ |
|
766 "a matchString" |
|
767 searchBlock := [:lits | |
|
768 |found| |
|
769 |
|
770 found := false. |
|
771 lits notNil ifTrue:[ |
|
772 lits do:[:aLiteral | |
|
773 found ifFalse:[ |
|
774 (aLiteral isMemberOf:String) ifTrue:[ |
|
775 found := (aString match:aLiteral) |
|
776 ] |
|
777 ] |
|
778 ] |
|
779 ]. |
|
780 found |
|
781 ]. |
|
782 ] ifFalse:[ |
|
783 searchBlock := [:lits | |
|
784 |found| |
|
785 |
|
786 found := false. |
|
787 lits notNil ifTrue:[ |
|
788 lits do:[:aLiteral | |
|
789 found ifFalse:[ |
|
790 (aLiteral isMemberOf:String) ifTrue:[ |
|
791 found := (aLiteral = aString) |
|
792 ] |
|
793 ] |
|
794 ] |
|
795 ]. |
|
796 found |
|
797 ]. |
|
798 ]. |
|
799 browser := self browseMethodsIn:aCollectionOfClasses |
|
800 where:[:c :m :s | searchBlock value:(m literals)] |
|
801 title:title. |
|
690 |
802 |
691 browser notNil ifTrue:[ |
803 browser notNil ifTrue:[ |
692 browser setSearchPattern:varName |
804 browser autoSearch:aString |
693 ]. |
805 ]. |
694 ^ browser |
806 ^ browser |
807 |
|
808 "SystemBrowser browseForString:'*all*'" |
|
809 "SystemBrowser browseForString:'*should*'" |
|
810 "SystemBrowser browseForString:'*[eE]rror*'" |
|
811 ! |
|
812 |
|
813 browseForString:aString |
|
814 "launch a browser for all methods containing a string" |
|
815 |
|
816 ^ self browseForString:aString in:(Smalltalk allClasses) |
|
817 ! |
|
818 |
|
819 browseInstRefsTo:varName in:aCollectionOfClasses modificationsOnly:modsOnly title:title |
|
820 "launch a browser for all methods in aClass where the instVar named |
|
821 varName is referenced; if modsOnly is true, browse only methods where the |
|
822 instvar is modified" |
|
823 |
|
824 |filter browser| |
|
825 |
|
826 filter := self filterToSearchInstRefsTo:varName modificationsOnly:modsOnly. |
|
827 browser := self browseInstMethodsIn:aCollectionOfClasses where:filter title:title. |
|
828 |
|
829 browser notNil ifTrue:[ |
|
830 browser autoSearch:varName |
|
831 ]. |
|
832 ^ browser |
|
833 ! |
|
834 |
|
835 aproposSearch:aString in:aCollectionOfClasses |
|
836 "browse all methods, which have aString in their selector or |
|
837 in the methods comment. |
|
838 This is relatively slow, since all source must be processed." |
|
839 |
|
840 |matchString list| |
|
841 |
|
842 matchString := '*' , aString , '*'. |
|
843 |
|
844 list := OrderedCollection new. |
|
845 |
|
846 ^ self browseMethodsIn:aCollectionOfClasses |
|
847 where:[:class :method :sel | |
|
848 (matchString match:sel) ifTrue:[ |
|
849 list add:(class name , '>>' , sel) |
|
850 ] ifFalse:[ |
|
851 (matchString match:(method comment)) ifTrue:[ |
|
852 list add:(class name , '>>' , sel) |
|
853 ] |
|
854 ]. |
|
855 Processor yield. |
|
856 ] |
|
857 title:('apropos: ' , aString) |
|
858 |
|
859 "SystemBrowser aproposSearch:'append'" |
|
860 "SystemBrowser aproposSearch:'add'" |
|
861 "SystemBrowser aproposSearch:'sort'" |
|
695 ! |
862 ! |
696 |
863 |
697 browseInstRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly |
864 browseInstRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly |
698 "launch a browser for all methods in aClass where the instVar named |
865 "launch a browser for all methods in aClass where the instVar named |
699 aString is referenced; if modsOnly is true, browse only methods where the |
866 aString is referenced; if modsOnly is true, browse only methods where the |
710 in:aCollectionOfClasses |
877 in:aCollectionOfClasses |
711 modificationsOnly:modsOnly |
878 modificationsOnly:modsOnly |
712 title:(title , aString) |
879 title:(title , aString) |
713 ! |
880 ! |
714 |
881 |
882 aproposSearch:aString |
|
883 "browse all methods, which have aString in their selector or |
|
884 in the methods comment. |
|
885 This is relatively slow, since all source must be processed." |
|
886 |
|
887 ^ self aproposSearch:aString in:(Smalltalk allClasses) |
|
888 ! |
|
889 |
|
715 browseInstRefsTo:aString under:aClass modificationsOnly:modsOnly |
890 browseInstRefsTo:aString under:aClass modificationsOnly:modsOnly |
716 "launch a browser for all methods in aClass and subclasses |
891 "launch a browser for all methods in aClass and subclasses |
717 where the instVar named aString is referenced; |
892 where the instVar named aString is referenced; |
718 if modsOnly is true, browse only methods where the instvar is modified" |
893 if modsOnly is true, browse only methods where the instvar is modified" |
719 |
894 |
723 browseClassRefsTo:varName in:aCollectionOfClasses modificationsOnly:modsOnly title:title |
898 browseClassRefsTo:varName in:aCollectionOfClasses modificationsOnly:modsOnly title:title |
724 "launch a browser for all methods in aCollectionOfClasses, |
899 "launch a browser for all methods in aCollectionOfClasses, |
725 where the classVar named aString is referenced; |
900 where the classVar named aString is referenced; |
726 if modsOnly is true, browse only methods where the classvar is modified" |
901 if modsOnly is true, browse only methods where the classvar is modified" |
727 |
902 |
728 |needMatch searchBlock browser| |
903 |searchBlock browser| |
729 |
904 |
730 needMatch := varName includesMatchCharacters. |
905 searchBlock := self filterToSearchClassRefsTo:varName modificationsOnly:modsOnly. |
906 browser := self browseMethodsIn:aCollectionOfClasses where:searchBlock title:title. |
|
907 |
|
908 browser notNil ifTrue:[ |
|
909 browser autoSearch:varName |
|
910 ]. |
|
911 ^ browser |
|
912 ! |
|
913 |
|
914 browseClassRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly |
|
915 "launch a browser for all methods in aClass where the classVar named |
|
916 aString is referenced; if modsOnly is true, browse only methods where the |
|
917 classvar is modified" |
|
918 |
|
919 |title| |
|
920 |
|
921 modsOnly ifTrue:[ |
|
922 title := 'modifications of ' |
|
923 ] ifFalse:[ |
|
924 title := 'references to ' |
|
925 ]. |
|
926 ^ self browseClassRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly title:(title , aString) |
|
927 ! |
|
928 |
|
929 browseClassRefsTo:aString under:aClass modificationsOnly:modsOnly |
|
930 "launch a browser for all methods in aClass and subclasses |
|
931 where the classVar named aString is referenced; |
|
932 if modsOnly is true, browse only methods where the classvar is modified" |
|
933 |
|
934 ^ self browseClassRefsTo:aString in:(aClass withAllSubclasses) modificationsOnly:modsOnly |
|
935 ! |
|
936 |
|
937 filterToSearchClassRefsTo:varName modificationsOnly:modsOnly |
|
938 "return a searchblock for class variable references" |
|
939 |
|
940 |searchBlock| |
|
731 |
941 |
732 searchBlock := [:c :m :s | |
942 searchBlock := [:c :m :s | |
733 |src result parser classvars| |
943 |src result parser classvars needMatch| |
944 |
|
945 needMatch := varName includesMatchCharacters. |
|
734 |
946 |
735 src := m source. |
947 src := m source. |
736 src isNil ifTrue:[ |
948 src isNil ifTrue:[ |
737 result := false |
949 result := false |
738 ] ifFalse:[ |
950 ] ifFalse:[ |
767 ]. |
979 ]. |
768 ]. |
980 ]. |
769 Processor yield. |
981 Processor yield. |
770 result |
982 result |
771 ]. |
983 ]. |
772 browser := self browseMethodsIn:aCollectionOfClasses where:searchBlock title:title. |
984 ^ searchBlock |
773 |
|
774 browser notNil ifTrue:[ |
|
775 browser setSearchPattern:varName |
|
776 ]. |
|
777 ^ browser |
|
778 ! |
|
779 |
|
780 browseClassRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly |
|
781 "launch a browser for all methods in aClass where the classVar named |
|
782 aString is referenced; if modsOnly is true, browse only methods where the |
|
783 classvar is modified" |
|
784 |
|
785 |title| |
|
786 |
|
787 modsOnly ifTrue:[ |
|
788 title := 'modifications of ' |
|
789 ] ifFalse:[ |
|
790 title := 'references to ' |
|
791 ]. |
|
792 ^ self browseClassRefsTo:aString in:aCollectionOfClasses modificationsOnly:modsOnly title:(title , aString) |
|
793 ! |
|
794 |
|
795 browseClassRefsTo:aString under:aClass modificationsOnly:modsOnly |
|
796 "launch a browser for all methods in aClass and subclasses |
|
797 where the classVar named aString is referenced; |
|
798 if modsOnly is true, browse only methods where the classvar is modified" |
|
799 |
|
800 ^ self browseClassRefsTo:aString in:(aClass withAllSubclasses) modificationsOnly:modsOnly |
|
801 ! ! |
985 ! ! |
802 |
986 |
803 !SystemBrowser class methodsFor:'private'! |
987 !SystemBrowser class methodsFor:'private'! |
988 |
|
989 newWithLabel:aString setupBlock:aBlock on:aWorkstation |
|
990 "common helper method for all creation methods" |
|
991 |
|
992 |newBrowser| |
|
993 |
|
994 newBrowser := self on:aWorkstation. |
|
995 newBrowser title:aString. |
|
996 aBlock value:newBrowser. |
|
997 |
|
998 newBrowser open. |
|
999 ^ newBrowser |
|
1000 ! |
|
1001 |
|
1002 newWithLabel:aString setupBlock:aBlock |
|
1003 "common helper method for all creation methods" |
|
1004 |
|
1005 ^ self newWithLabel:aString setupBlock:aBlock on:Display |
|
1006 ! |
|
804 |
1007 |
805 showNoneFound:what |
1008 showNoneFound:what |
806 "/ DialogView warn:(self classResources string:('no ' , what , ' found')). |
1009 "/ DialogView warn:(self classResources string:('no ' , what , ' found')). |
807 self showNoneFound |
1010 self showNoneFound |
808 ! |
1011 ! |
809 |
1012 |
810 showNoneFound |
1013 showNoneFound |
811 DialogView warn:(self classResources string:'None found'). |
1014 DialogView warn:(self classResources string:'None found'). |
812 ! |
1015 ! ! |
813 |
1016 |
814 newWithLabel:aString setupBlock:aBlock on:aWorkstation |
1017 !SystemBrowser class methodsFor:'general startup'! |
815 "common helper method for all creation methods" |
1018 |
816 |
1019 openOnDisplay:aDisplay |
817 |newBrowser| |
1020 "launch a standard browser on another display. |
818 |
1021 Does not work currently - still being developped." |
819 newBrowser := self on:aWorkstation. |
1022 |
820 newBrowser label:aString. |
1023 ^ self newWithLabel:(self classResources string:'System Browser') |
821 aBlock value:newBrowser. |
1024 setupBlock:[:browser | browser setupForAll] |
822 |
1025 on:aDisplay |
823 newBrowser open. |
1026 |
824 ^ newBrowser |
1027 " |
825 ! |
1028 SystemBrowser openOnDisplay:(XWorkstation new initializeFor:'porty:0') |
826 |
1029 " |
827 newWithLabel:aString setupBlock:aBlock |
1030 ! |
828 "common helper method for all creation methods" |
1031 |
829 |
1032 open |
830 ^ self newWithLabel:aString setupBlock:aBlock on:Display |
1033 "launch a standard browser" |
1034 |
|
1035 ^ self openOnDisplay:Display |
|
1036 |
|
1037 "SystemBrowser open" |
|
1038 ! ! |
|
1039 |
|
1040 !SystemBrowser methodsFor:'dependencies'! |
|
1041 |
|
1042 update:something with:someArgument from:changedObject |
|
1043 |
|
1044 " |
|
1045 avoid update/warn after my own changes |
|
1046 " |
|
1047 lockUpdates == true ifTrue:[ |
|
1048 "/ 'ignored my change' printNL. |
|
1049 ^ self |
|
1050 ]. |
|
1051 |
|
1052 "/ changedObject print. ' ' print. someArgument print. ' ' print. |
|
1053 "/ something printNL. |
|
1054 |
|
1055 (changedObject == Smalltalk) ifTrue:[ |
|
1056 something == #newClass ifTrue:[ |
|
1057 ((someArgument category = currentClassCategory) |
|
1058 or:[currentClassCategory notNil |
|
1059 and:[currentClassCategory startsWith:'*']]) ifTrue:[ |
|
1060 self updateClassListWithScroll:false. |
|
1061 ]. |
|
1062 |
|
1063 someArgument category ~= currentClassCategory ifTrue:[ |
|
1064 " |
|
1065 category new ? |
|
1066 " |
|
1067 (classCategoryListView notNil |
|
1068 and:[classCategoryListView list notNil |
|
1069 and:[(classCategoryListView list includes:someArgument category) not]]) |
|
1070 ifTrue:[ |
|
1071 self updateClassCategoryListWithScroll:false. |
|
1072 ] |
|
1073 ]. |
|
1074 ^ self |
|
1075 ]. |
|
1076 |
|
1077 something == #classRemove ifTrue:[ |
|
1078 someArgument = currentClass ifTrue:[ |
|
1079 self warnLabel:'the selected class was removed'. |
|
1080 ^ self |
|
1081 ]. |
|
1082 " fall into general update " |
|
1083 ]. |
|
1084 |
|
1085 " |
|
1086 any other (unknown) change |
|
1087 with the Smalltalk dictionary ... |
|
1088 " |
|
1089 self updateClassCategoryListWithScroll:false. |
|
1090 self updateClassListWithScroll:false. |
|
1091 ^ self |
|
1092 ]. |
|
1093 |
|
1094 changedObject isBehavior ifTrue:[ |
|
1095 " |
|
1096 its a class, that has changed |
|
1097 " |
|
1098 (currentClass notNil |
|
1099 and:[changedObject name = currentClass name]) ifTrue:[ |
|
1100 " |
|
1101 its the current class that has changed |
|
1102 " |
|
1103 something == #methodDictionary ifTrue:[ |
|
1104 (someArgument isSymbol) ifTrue:[ |
|
1105 |changedMethod| |
|
1106 |
|
1107 " |
|
1108 the method with selector someArgument was changed or removed |
|
1109 " |
|
1110 self updateMethodCategoryListWithScroll:false. |
|
1111 self updateMethodListWithScroll:false. |
|
1112 |
|
1113 someArgument == currentSelector ifTrue:[ |
|
1114 " |
|
1115 special care here: the currently shown method has been |
|
1116 changed somehow in another browser (or via fileIn) |
|
1117 " |
|
1118 changedMethod := currentClass compiledMethodAt:currentSelector. |
|
1119 changedMethod isNil ifTrue:[ |
|
1120 self warnLabel:'the method shown was removed'. |
|
1121 ^ self |
|
1122 ]. |
|
1123 "compare the source codes" |
|
1124 self warnLabel:'the code shown may not up to date'. |
|
1125 ^ self |
|
1126 ]. |
|
1127 ^ self |
|
1128 ] |
|
1129 ]. |
|
1130 |
|
1131 something == #comment ifTrue:[ |
|
1132 " |
|
1133 the class has changed its comment; we dont care, except if |
|
1134 currently showing the comment |
|
1135 " |
|
1136 aspect == #comment ifTrue:[ |
|
1137 self warnLabel:'the comment shown may not up to date'. |
|
1138 ]. |
|
1139 ^ self |
|
1140 ]. |
|
1141 something == #definition ifTrue:[ |
|
1142 " |
|
1143 the class has changed its definition. |
|
1144 Warn, except if showing a method. |
|
1145 " |
|
1146 aspect notNil ifTrue:[ |
|
1147 self warnLabel:'the classes definition has changed'. |
|
1148 ]. |
|
1149 ^ self |
|
1150 ]. |
|
1151 |
|
1152 " |
|
1153 get the class again - in case of a changed class definition, |
|
1154 we are otherwise refering to the obsolete old class |
|
1155 " |
|
1156 currentClass := Smalltalk at:(currentClass name asSymbol). |
|
1157 showInstance ifTrue:[ |
|
1158 actualClass := currentClass |
|
1159 ] ifFalse:[ |
|
1160 actualClass := currentClass class |
|
1161 ]. |
|
1162 |
|
1163 self updateMethodCategoryListWithScroll:false. |
|
1164 |
|
1165 "dont update codeView ...." |
|
1166 "self update" |
|
1167 ^ self |
|
1168 ]. |
|
1169 |
|
1170 " |
|
1171 any other class has changed (but not its organization, since |
|
1172 that is cought in the above case). |
|
1173 We are not interrested in it - except, if showing fullProtocol |
|
1174 or hierarchy ... |
|
1175 " |
|
1176 currentClassHierarchy notNil ifTrue:[ |
|
1177 fullProtocol ifTrue:[ |
|
1178 (currentClass isSubclassOf:changedObject) ifTrue:[ |
|
1179 ] |
|
1180 ] ifFalse:[ |
|
1181 ((currentClass isSubclassOf:changedObject) |
|
1182 or:[changedObject isSubclassOf:currentClass]) ifTrue:[ |
|
1183 ] |
|
1184 ] |
|
1185 ]. |
|
1186 |
|
1187 ^ self |
|
1188 ]. |
|
1189 |
|
1190 (changedObject isKindOf:Method) ifTrue:[ |
|
1191 |
|
1192 ] |
|
1193 ! ! |
|
1194 |
|
1195 !SystemBrowser methodsFor:'private'! |
|
1196 |
|
1197 normalLabel |
|
1198 "set the normal (inactive) window- and icon labels" |
|
1199 |
|
1200 |l il sel| |
|
1201 |
|
1202 myLabel notNil ifTrue:[ |
|
1203 l := il := myLabel |
|
1204 ] ifFalse:[ |
|
1205 l := resources string:'System Browser'. |
|
1206 |
|
1207 currentClass notNil ifTrue:[ |
|
1208 l := l, ': ', currentClass name. |
|
1209 classListView isNil ifTrue:[ |
|
1210 currentSelector notNil ifTrue:[ |
|
1211 l := l , ' ' , currentSelector |
|
1212 ] |
|
1213 ]. |
|
1214 il := currentClass name |
|
1215 ] ifFalse:[ |
|
1216 il := l. |
|
1217 ] |
|
1218 ]. |
|
1219 self label:l. |
|
1220 self iconLabel:il. |
|
1221 |
|
1222 ! |
|
1223 |
|
1224 setAcceptAndExplainActionsForMethod |
|
1225 "tell the codeView what to do on accept and explain" |
|
1226 |
|
1227 codeView acceptAction:[:theCode | |
|
1228 |cat| |
|
1229 |
|
1230 codeView cursor:Cursor execute. |
|
1231 |
|
1232 (cat := currentMethodCategory) = '* all *' ifTrue:[ |
|
1233 "must check from which category this code came from ... |
|
1234 ... thanks to Arno for pointing this out" |
|
1235 |
|
1236 cat := self askForMethodCategory. |
|
1237 ]. |
|
1238 (cat notNil and:[cat notEmpty]) ifTrue:[ |
|
1239 Object abortSignal catch:[ |
|
1240 lockUpdates := true. |
|
1241 |
|
1242 actualClass compiler |
|
1243 compile:theCode asString |
|
1244 forClass:actualClass |
|
1245 inCategory:cat |
|
1246 notifying:codeView. |
|
1247 |
|
1248 codeView modified:false. |
|
1249 self updateMethodListWithScroll:false. |
|
1250 ]. |
|
1251 lockUpdates := false. |
|
1252 ]. |
|
1253 codeView cursor:Cursor normal. |
|
1254 ]. |
|
1255 |
|
1256 codeView explainAction:[:theCode :theSelection | |
|
1257 self showExplanation:(Explainer |
|
1258 explain:theSelection |
|
1259 in:theCode |
|
1260 forClass:actualClass) |
|
1261 ]. |
|
1262 ! |
|
1263 |
|
1264 checkSelectionChangeAllowed |
|
1265 "return true, if selection change is ok; |
|
1266 its not ok, if code has been changed. |
|
1267 in this case, return the result of a user query" |
|
1268 |
|
1269 |box| |
|
1270 |
|
1271 codeView modified ifFalse:[ |
|
1272 ^ true |
|
1273 ]. |
|
1274 "/ fullProtocol ifTrue:[^ true]. |
|
1275 box := YesNoBox |
|
1276 title:(resources at:'contents in codeview has not been accepted.\\Modifications will be lost when continuing.') withCRs |
|
1277 yesText:(resources at:'continue') |
|
1278 noText:(resources at:'abort'). |
|
1279 ^ box confirm |
|
1280 ! |
|
1281 |
|
1282 selectorToSearchFor |
|
1283 "look in codeView and methodListView for a search-string when searching for selectors" |
|
1284 |
|
1285 |sel t| |
|
1286 |
|
1287 sel := codeView selection. |
|
1288 sel notNil ifTrue:[ |
|
1289 sel := sel asString. |
|
1290 t := Parser selectorInExpression:sel. |
|
1291 t notNil ifTrue:[ |
|
1292 sel := t |
|
1293 ]. |
|
1294 sel := sel withoutSpaces. |
|
1295 sel == #>> ifTrue:[ |
|
1296 "oops - thats probably not what we want here ..." |
|
1297 self extractClassAndSelectorFromSelectionInto:[:c :s :m | |
|
1298 sel := s |
|
1299 ] |
|
1300 ] |
|
1301 ] ifFalse:[ |
|
1302 methodListView notNil ifTrue:[ |
|
1303 sel := methodListView selectionValue |
|
1304 ] ifFalse:[ |
|
1305 classMethodListView notNil ifTrue:[ |
|
1306 sel := classMethodListView selectionValue. |
|
1307 sel notNil ifTrue:[ |
|
1308 sel := self selectorFromClassMethodString:sel |
|
1309 ] |
|
1310 ] |
|
1311 ]. |
|
1312 sel notNil ifTrue:[ |
|
1313 sel := sel withoutSpaces |
|
1314 ] ifFalse:[ |
|
1315 sel := '' |
|
1316 ] |
|
1317 ]. |
|
1318 ^ sel |
|
1319 ! |
|
1320 |
|
1321 enterBoxTitle:title okText:okText |
|
1322 "convenient method: setup enterBox" |
|
1323 |
|
1324 |box| |
|
1325 |
|
1326 box := EnterBox new. |
|
1327 box title:(resources string:title) okText:(resources string:okText). |
|
1328 ^ box |
|
1329 ! |
|
1330 |
|
1331 askAndBrowseSelectorTitle:title action:aBlock |
|
1332 "convenient method: setup enterBox with text from codeView or selected |
|
1333 method for browsing based on a selector. Set action and launch box" |
|
1334 |
|
1335 |box| |
|
1336 |
|
1337 box := self enterBoxTitle:title okText:'browse'. |
|
1338 box initialText:(self selectorToSearchFor). |
|
1339 box action:[:aString | self withCursor:(Cursor questionMark) do:[aBlock value:aString]]. |
|
1340 box showAtPointer |
|
1341 ! |
|
1342 |
|
1343 setSearchPattern:aString |
|
1344 codeView setSearchPattern:aString |
|
1345 ! |
|
1346 |
|
1347 listBoxTitle:title okText:okText list:aList |
|
1348 "convenient method: setup a listBox & return it" |
|
1349 |
|
1350 |box| |
|
1351 |
|
1352 box := ListSelectionBox new. |
|
1353 box okText:(resources string:okText). |
|
1354 box title:(resources string:title). |
|
1355 box list:aList. |
|
1356 ^ box |
|
1357 ! |
|
1358 |
|
1359 showExplanation:someText |
|
1360 "show explanation from Parser" |
|
1361 |
|
1362 self notify:someText |
|
1363 ! |
|
1364 |
|
1365 stringToSearchFor |
|
1366 "look in codeView and methodListView for a search-string when searching for classes/names" |
|
1367 |
|
1368 |sel| |
|
1369 |
|
1370 sel := codeView selection. |
|
1371 sel notNil ifTrue:[ |
|
1372 sel := sel asString withoutSpaces |
|
1373 ] ifFalse:[ |
|
1374 sel isNil ifTrue:[ |
|
1375 currentClass notNil ifTrue:[ |
|
1376 sel := currentClass name |
|
1377 ] |
|
1378 ]. |
|
1379 sel notNil ifTrue:[ |
|
1380 sel := sel withoutSpaces |
|
1381 ] ifFalse:[ |
|
1382 sel := '' |
|
1383 ] |
|
1384 ]. |
|
1385 ^ sel |
|
1386 ! |
|
1387 |
|
1388 findClassOfVariable:aVariableName accessWith:aSelector |
|
1389 "this method returns the class, in which a variable |
|
1390 is defined; |
|
1391 needs either #instVarNames or #classVarNames as aSelector." |
|
1392 |
|
1393 |cls homeClass| |
|
1394 |
|
1395 " |
|
1396 first, find the class, where the variable is declared |
|
1397 " |
|
1398 cls := currentClass. |
|
1399 [cls notNil] whileTrue:[ |
|
1400 ((cls perform:aSelector) includes:aVariableName) ifTrue:[ |
|
1401 homeClass := cls. |
|
1402 cls := nil. |
|
1403 ] ifFalse:[ |
|
1404 cls := cls superclass |
|
1405 ] |
|
1406 ]. |
|
1407 homeClass isNil ifTrue:[ |
|
1408 "nope, must be one below ... (could optimize a bit, by searching down |
|
1409 for the declaring class ... |
|
1410 " |
|
1411 homeClass := currentClass |
|
1412 ] ifFalse:[ |
|
1413 "/ Transcript showCr:'starting search in ' , homeClass name. |
|
1414 ]. |
|
1415 ^ homeClass |
|
1416 ! |
|
1417 |
|
1418 enterBoxForSearchSelectorTitle:title |
|
1419 "convenient method: setup enterBox with text from codeView or selected |
|
1420 method for browsing based on a selector" |
|
1421 |
|
1422 |box| |
|
1423 |
|
1424 box := self enterBoxTitle:title okText:'search'. |
|
1425 box initialText:(self selectorToSearchFor). |
|
1426 ^ box |
|
1427 ! |
|
1428 |
|
1429 enterBoxForCodeSelectionTitle:title okText:okText |
|
1430 "convenient method: setup enterBox with text from codeview" |
|
1431 |
|
1432 |sel box| |
|
1433 |
|
1434 box := self enterBoxTitle:(resources string:title) okText:(resources string:okText). |
|
1435 sel := codeView selection. |
|
1436 sel notNil ifTrue:[ |
|
1437 box initialText:(sel asString withoutSeparators) |
|
1438 ]. |
|
1439 ^ box |
|
1440 ! |
|
1441 |
|
1442 classesInFullProtocolHierarchy:aClass do:aBlock |
|
1443 "evaluate aBlock for all non-striked out classes in |
|
1444 the hierarchy" |
|
1445 |
|
1446 |index| |
|
1447 |
|
1448 index := (classListView list size). |
|
1449 aClass withAllSuperclasses do:[:c | |
|
1450 (classListView isInSelection:index) ifFalse:[ |
|
1451 aBlock value:c |
|
1452 ]. |
|
1453 index := index - 1 |
|
1454 ] |
|
1455 |
|
1456 ! |
|
1457 |
|
1458 enterBoxForBrowseTitle:title action:aBlock |
|
1459 "convenient method: setup enterBox with text from codeView or selected |
|
1460 method for method browsing based on className/variable" |
|
1461 |
|
1462 |box| |
|
1463 |
|
1464 box := self enterBoxTitle:title okText:'browse'. |
|
1465 box initialText:(self stringToSearchFor). |
|
1466 box action:[:aString | self withWaitCursorDo:[aBlock value:aString]]. |
|
1467 box showAtPointer |
|
1468 ! |
|
1469 |
|
1470 askBoxTitle:title okText:okText initialText:initialText action:aBlock |
|
1471 "convenient method: setup enterBox, and open it" |
|
1472 |
|
1473 |box| |
|
1474 |
|
1475 box := EnterBox new. |
|
1476 box title:(resources string:title) okText:(resources string:okText). |
|
1477 box initialText:initialText. |
|
1478 box action:[:aString | self withWaitCursorDo:aBlock value:aString]. |
|
1479 box showAtPointer |
|
1480 ! |
|
1481 |
|
1482 askAndBrowseMethodCategory:title action:aBlock |
|
1483 "convenient method: setup enterBox with initial being current method category" |
|
1484 |
|
1485 |sel box| |
|
1486 |
|
1487 box := self enterBoxTitle:title okText:'browse'. |
|
1488 sel := codeView selection. |
|
1489 sel isNil ifTrue:[ |
|
1490 currentMethodCategory notNil ifTrue:[ |
|
1491 sel := currentMethodCategory |
|
1492 ] |
|
1493 ]. |
|
1494 sel notNil ifTrue:[ |
|
1495 box initialText:(sel asString withoutSpaces) |
|
1496 ]. |
|
1497 box action:[:aString | self withWaitCursorDo:[aBlock value:aString]]. |
|
1498 box showAtPointer |
|
1499 ! |
|
1500 |
|
1501 classHierarchyDo:aBlock |
|
1502 "eavluate the 2-arg block for every class, |
|
1503 starting at Object; passing class and nesting level to the block." |
|
1504 |
|
1505 |classes s classDict l| |
|
1506 |
|
1507 classes := Smalltalk allClasses. |
|
1508 classDict := IdentityDictionary new:classes size. |
|
1509 classes do:[:aClass | |
|
1510 s := aClass superclass. |
|
1511 s notNil ifTrue:[ |
|
1512 l := classDict at:s ifAbsent:[nil]. |
|
1513 l isNil ifTrue:[ |
|
1514 l := OrderedCollection new:5. |
|
1515 classDict at:s put:l |
|
1516 ]. |
|
1517 l add:aClass |
|
1518 ] |
|
1519 ]. |
|
1520 self classHierarchyOf:Object level:0 do:aBlock using:classDict |
|
1521 ! |
|
1522 |
|
1523 classHierarchyOf:aClass level:level do:aBlock using:aDictionary |
|
1524 "evaluate the 2-arg block for every subclass of aClass, |
|
1525 passing class and nesting level to the block." |
|
1526 |
|
1527 |names subclasses| |
|
1528 |
|
1529 aBlock value:aClass value:level. |
|
1530 subclasses := aDictionary at:aClass ifAbsent:[nil]. |
|
1531 (subclasses size == 0) ifFalse:[ |
|
1532 names := subclasses collect:[:class | class name]. |
|
1533 names sortWith:subclasses. |
|
1534 subclasses do:[:aSubClass | |
|
1535 self classHierarchyOf:aSubClass level:(level + 1) do:aBlock using:aDictionary |
|
1536 ] |
|
1537 ] |
|
1538 ! |
|
1539 |
|
1540 compileCode:someCode |
|
1541 (ReadStream on:someCode) fileIn |
|
1542 ! |
|
1543 |
|
1544 extractClassAndSelectorFromSelectionInto:aBlock |
|
1545 "given a string which can be either 'class>>sel' or |
|
1546 'class sel', extract className and selector, and call aBlock with |
|
1547 the result." |
|
1548 |
|
1549 |sel clsName isMeta sep s| |
|
1550 |
|
1551 sel := codeView selection. |
|
1552 sel notNil ifTrue:[ |
|
1553 sel := sel asString withoutSeparators. |
|
1554 ('*>>*' match:sel) ifTrue:[ |
|
1555 sep := $> |
|
1556 ] ifFalse:[ |
|
1557 ('* *' match:sel) ifTrue:[ |
|
1558 sep := Character space |
|
1559 ] |
|
1560 ]. |
|
1561 sep notNil ifTrue:[ |
|
1562 " |
|
1563 extract class/sel from selection |
|
1564 " |
|
1565 s := ReadStream on:sel. |
|
1566 clsName := s upTo:sep. |
|
1567 [s peek == sep] whileTrue:[s next]. |
|
1568 sel := s upToEnd. |
|
1569 |
|
1570 (clsName endsWith:'class') ifTrue:[ |
|
1571 isMeta := true. |
|
1572 clsName := clsName copyTo:(clsName size - 5) |
|
1573 ] ifFalse:[ |
|
1574 isMeta := false |
|
1575 ]. |
|
1576 ] |
|
1577 ]. |
|
1578 aBlock value:clsName value:sel value:isMeta |
|
1579 |
|
1580 |
|
1581 ! |
|
1582 |
|
1583 classesInHierarchy:aClass do:aBlock |
|
1584 |index| |
|
1585 |
|
1586 index := (classListView list size). |
|
1587 aClass withAllSuperclasses do:[:c | |
|
1588 (classListView isInSelection:index) ifFalse:[ |
|
1589 aBlock value:c |
|
1590 ]. |
|
1591 index := index - 1 |
|
1592 ] |
|
1593 |
|
1594 ! |
|
1595 |
|
1596 askForMethodCategory |
|
1597 |someCategories box txt| |
|
1598 |
|
1599 someCategories := actualClass categories sort. |
|
1600 box := self listBoxTitle:'accept in which method category ?' okText:'accept' list:someCategories. |
|
1601 |
|
1602 lastMethodCategory isNil ifTrue:[ |
|
1603 txt := 'new methods' |
|
1604 ] ifFalse:[ |
|
1605 txt := lastMethodCategory |
|
1606 ]. |
|
1607 box initialText:txt. |
|
1608 box action:[:aString | |
|
1609 ^ aString |
|
1610 ]. |
|
1611 box showAtPointer. |
|
1612 ^ nil |
|
1613 ! |
|
1614 |
|
1615 warnLabel:what |
|
1616 "set the title for some warning" |
|
1617 |
|
1618 self label:('System Browser WARNING: ' , what) |
|
1619 ! |
|
1620 |
|
1621 busyLabel:what with:someArgument |
|
1622 "set the title for some warning" |
|
1623 |
|
1624 self label:('System Browser:' , (resources string:what with:someArgument)) |
|
1625 |
|
1626 ! ! |
|
1627 |
|
1628 !SystemBrowser methodsFor:'method stuff'! |
|
1629 |
|
1630 updateMethodListWithScroll:scroll |
|
1631 |selectors scr first last| |
|
1632 |
|
1633 methodListView notNil ifTrue:[ |
|
1634 currentMethodCategory notNil ifTrue:[ |
|
1635 fullProtocol ifTrue:[ |
|
1636 selectors := self listOfAllSelectorsInCategory:currentMethodCategory |
|
1637 inFullProtocolHierarchyOfClass:actualClass |
|
1638 ] ifFalse:[ |
|
1639 selectors := self listOfAllSelectorsInCategory:currentMethodCategory |
|
1640 ofClass:actualClass |
|
1641 ] |
|
1642 ]. |
|
1643 scr := scroll. |
|
1644 first := methodListView firstLineShown. |
|
1645 first ~~ 1 ifTrue:[ |
|
1646 last := methodListView lastLineShown. |
|
1647 selectors size <= (last - first + 1) ifTrue:[ |
|
1648 scr := true |
|
1649 ] |
|
1650 ]. |
|
1651 methodListView list = selectors ifFalse:[ |
|
1652 scr ifTrue:[ |
|
1653 methodListView contents:selectors |
|
1654 ] ifFalse:[ |
|
1655 methodListView setContents:selectors |
|
1656 ] |
|
1657 ]. |
|
1658 ] |
|
1659 ! |
|
1660 |
|
1661 methodSelectionChanged |
|
1662 "method selection has changed - update dependent views" |
|
1663 |
|
1664 self withWaitCursorDo:[ |
|
1665 |index cls| |
|
1666 |
|
1667 self updateCodeView. |
|
1668 self setAcceptAndExplainActionsForMethod. |
|
1669 |
|
1670 " |
|
1671 if there is any autoSearch string, do the search |
|
1672 " |
|
1673 autoSearch notNil ifTrue:[ |
|
1674 codeView searchFwd:autoSearch ifAbsent:[] |
|
1675 ]. |
|
1676 |
|
1677 fullProtocol ifTrue:[ |
|
1678 " |
|
1679 remove any bold attribute from classList |
|
1680 " |
|
1681 1 to:classListView list size do:[:i | |
|
1682 classListView attributeAt:i remove:#bold. |
|
1683 ]. |
|
1684 " |
|
1685 boldify the class where this method is implemented |
|
1686 " |
|
1687 currentMethod notNil ifTrue:[ |
|
1688 cls := currentMethod who at:1. |
|
1689 index := classListView list indexOf:(cls name). |
|
1690 index ~~ 0 ifTrue:[ |
|
1691 classListView attributeAt:index add:#bold. |
|
1692 ]. |
|
1693 currentClass := cls. |
|
1694 |
|
1695 ] |
|
1696 ]. |
|
1697 ] |
|
1698 ! |
|
1699 |
|
1700 updateMethodList |
|
1701 self updateMethodListWithScroll:true |
|
1702 ! |
|
1703 |
|
1704 methodSelection:lineNr |
|
1705 "user clicked on a method line - show code" |
|
1706 |
|
1707 |selectorString selectorSymbol index| |
|
1708 |
|
1709 (fullProtocol not and:[currentClass isNil]) ifTrue:[^ self]. |
|
1710 |
|
1711 selectorString := methodListView selectionValue. |
|
1712 " |
|
1713 kludge: check if its a wrapped one |
|
1714 " |
|
1715 (selectorString endsWith:' !!') ifTrue:[ |
|
1716 selectorString := selectorString copyTo:(selectorString size - 2) |
|
1717 ]. |
|
1718 selectorSymbol := selectorString asSymbol. |
|
1719 fullProtocol ifTrue:[ |
|
1720 currentMethod := currentSelector := nil. |
|
1721 " |
|
1722 search which class implements the selector |
|
1723 " |
|
1724 self classesInFullProtocolHierarchy:actualClass do:[:c | |
|
1725 (currentMethod isNil |
|
1726 and:[c implements:selectorSymbol]) ifTrue:[ |
|
1727 currentSelector := selectorSymbol. |
|
1728 currentMethod := c compiledMethodAt:selectorSymbol. |
|
1729 ] |
|
1730 ] |
|
1731 ] ifFalse:[ |
|
1732 currentSelector := selectorSymbol. |
|
1733 currentMethod := actualClass compiledMethodAt:selectorSymbol. |
|
1734 ]. |
|
1735 |
|
1736 methodCategoryListView notNil ifTrue:[ |
|
1737 currentMethod notNil ifTrue:[ |
|
1738 (currentMethodCategory = currentMethod category) ifFalse:[ |
|
1739 currentMethodCategory := currentMethod category. |
|
1740 methodCategoryListView selectElement:currentMethodCategory |
|
1741 ] |
|
1742 ] |
|
1743 ]. |
|
1744 |
|
1745 self methodSelectionChanged |
|
1746 ! |
|
1747 |
|
1748 listOfAllSelectorsInCategory:aCategory ofClass:aClass |
|
1749 "answer a list of all selectors in a given method category |
|
1750 of the argument, aClass" |
|
1751 |
|
1752 |newList searchCategory selector| |
|
1753 |
|
1754 (aCategory = '* all *') ifTrue:[ |
|
1755 newList := aClass selectorArray asOrderedCollection |
|
1756 ] ifFalse:[ |
|
1757 (aCategory = '* no category *') ifTrue:[ |
|
1758 searchCategory := nil |
|
1759 ] ifFalse:[ |
|
1760 searchCategory := aCategory |
|
1761 ]. |
|
1762 newList := OrderedCollection new. |
|
1763 aClass methodArray with:aClass selectorArray do:[:aMethod :selector | |
|
1764 |sel| |
|
1765 |
|
1766 (aMethod category = searchCategory) ifTrue:[ |
|
1767 aMethod isWrapped ifTrue:[ |
|
1768 sel := selector , ' !!' |
|
1769 ] ifFalse:[ |
|
1770 sel := selector |
|
1771 ]. |
|
1772 |
|
1773 "mhmh - can this happen ?" |
|
1774 "/ (newList includes:sel) ifFalse:[ |
|
1775 newList add:sel |
|
1776 "/ ] |
|
1777 ] |
|
1778 ] |
|
1779 ]. |
|
1780 (newList size == 0) ifTrue:[^ nil]. |
|
1781 ^ newList sort |
|
1782 ! |
|
1783 |
|
1784 template |
|
1785 "return a method definition template" |
|
1786 |
|
1787 ^ |
|
1788 'message selector and argument names |
|
1789 "comment stating purpose of message" |
|
1790 |
|
1791 |
|
1792 |temporaries| |
|
1793 statements |
|
1794 |
|
1795 |
|
1796 " |
|
1797 change above template into real code. |
|
1798 Then ''accept'' either via the menu |
|
1799 or via the keyboard (usually CMD-A). |
|
1800 |
|
1801 You do not need this template; you can also |
|
1802 select any existing methods code, change it, |
|
1803 and finally ''accept''. |
|
1804 " |
|
1805 ' |
|
1806 ! |
|
1807 |
|
1808 listOfAllSelectorsInCategory:aCategory inFullProtocolHierarchyOfClass:aClass |
|
1809 "answer a list of all selectors in a given method category |
|
1810 of the argument, aClass and its superclasses. |
|
1811 Used with fullProtocol browsing." |
|
1812 |
|
1813 |newList thisList searchCategory selector| |
|
1814 |
|
1815 newList := Set new. |
|
1816 self classesInFullProtocolHierarchy:aClass do:[:c | |
|
1817 (aCategory = '* all *') ifTrue:[ |
|
1818 newList addAll:(c selectorArray) |
|
1819 ] ifFalse:[ |
|
1820 (aCategory = '* no category *') ifTrue:[ |
|
1821 searchCategory := nil |
|
1822 ] ifFalse:[ |
|
1823 searchCategory := aCategory |
|
1824 ]. |
|
1825 c methodArray with:c selectorArray do:[:aMethod :selector | |
|
1826 (aMethod category = searchCategory) ifTrue:[ |
|
1827 newList add:selector |
|
1828 ] |
|
1829 ] |
|
1830 ]. |
|
1831 ]. |
|
1832 (newList size == 0) ifTrue:[^ nil]. |
|
1833 ^ newList asOrderedCollection sort |
|
1834 ! |
|
1835 |
|
1836 checkMethodSelected |
|
1837 currentMethod isNil ifTrue:[ |
|
1838 self warn:'select a method first'. |
|
1839 ^ false |
|
1840 ]. |
|
1841 ^ true |
|
1842 ! |
|
1843 |
|
1844 switchToMethodNamed:matchString |
|
1845 |aSelector method cat index classToSearch selectors| |
|
1846 |
|
1847 currentClass notNil ifTrue:[ |
|
1848 showInstance ifTrue:[ |
|
1849 classToSearch := currentClass |
|
1850 ] ifFalse:[ |
|
1851 classToSearch := currentClass class |
|
1852 ]. |
|
1853 selectors := classToSearch selectorArray. |
|
1854 |
|
1855 ((matchString ~= '*') and:[matchString includesMatchCharacters]) ifTrue:[ |
|
1856 index := selectors findFirst:[:element | matchString match:element] |
|
1857 ] ifFalse:[ |
|
1858 index := selectors indexOf:matchString |
|
1859 ]. |
|
1860 |
|
1861 (index ~~ 0) ifTrue:[ |
|
1862 aSelector := selectors at:index. |
|
1863 method := classToSearch methodArray at:index. |
|
1864 cat := method category. |
|
1865 cat isNil ifTrue:[cat := '* all *']. |
|
1866 methodCategoryListView selectElement:cat. |
|
1867 currentMethodCategory := cat. |
|
1868 self methodCategorySelectionChanged. |
|
1869 |
|
1870 currentMethod := classToSearch compiledMethodAt:aSelector. |
|
1871 currentMethod notNil ifTrue:[ |
|
1872 currentSelector := aSelector. |
|
1873 methodListView selectElement:aSelector. |
|
1874 ]. |
|
1875 self methodSelectionChanged |
|
1876 ] |
|
1877 ] |
|
1878 ! |
|
1879 |
|
1880 switchToAnyMethodNamed:aString |
|
1881 |aSelector classToStartSearch aClass nm| |
|
1882 |
|
1883 aSelector := aString asSymbol. |
|
1884 currentClass isNil ifTrue:[ |
|
1885 currentClassHierarchy notNil ifTrue:[ |
|
1886 classToStartSearch := currentClassHierarchy |
|
1887 ] |
|
1888 ] ifFalse:[ |
|
1889 classToStartSearch := currentClass |
|
1890 ]. |
|
1891 classToStartSearch notNil ifTrue:[ |
|
1892 showInstance ifFalse:[ |
|
1893 classToStartSearch := classToStartSearch class |
|
1894 ]. |
|
1895 aClass := classToStartSearch whichClassImplements:aSelector. |
|
1896 aClass notNil ifTrue:[ |
|
1897 nm := aClass name. |
|
1898 showInstance ifFalse:[ |
|
1899 ((nm ~= 'Metaclass') and:[nm endsWith:'class']) ifTrue:[ |
|
1900 nm := nm copyTo:(nm size - 5) |
|
1901 ] |
|
1902 ]. |
|
1903 self switchToClassNamed:nm. |
|
1904 self switchToMethodNamed:aString |
|
1905 ] |
|
1906 ] |
|
1907 ! ! |
|
1908 |
|
1909 !SystemBrowser methodsFor:'misc'! |
|
1910 |
|
1911 updateCodeView |
|
1912 |code aStream| |
|
1913 |
|
1914 fullClass ifTrue:[ |
|
1915 currentClass notNil ifTrue:[ |
|
1916 code := currentClass source. |
|
1917 ] |
|
1918 ] ifFalse:[ |
|
1919 currentMethod notNil ifTrue:[ |
|
1920 (codeView acceptAction isNil |
|
1921 and:[actualClass notNil |
|
1922 and:[currentMethodCategory notNil]]) ifTrue:[ |
|
1923 self setAcceptAndExplainActionsForMethod. |
|
1924 ]. |
|
1925 |
|
1926 code := currentMethod source. |
|
1927 |
|
1928 ] |
|
1929 ]. |
|
1930 codeView contents:code. |
|
1931 codeView modified:false. |
|
1932 |
|
1933 self normalLabel. |
|
1934 |
|
1935 |
|
1936 ! |
|
1937 |
|
1938 instanceProtocol |
|
1939 "switch to instance protocol" |
|
1940 |
|
1941 showInstance ifFalse:[ |
|
1942 self checkSelectionChangeAllowed ifTrue:[ |
|
1943 classToggle turnOff. |
|
1944 instanceToggle turnOn. |
|
1945 showInstance := true. |
|
1946 |
|
1947 (variableListView notNil |
|
1948 and:[variableListView hasSelection]) ifTrue:[ |
|
1949 self unhilightMethodCategories. |
|
1950 self unhilightMethods. |
|
1951 variableListView deselect |
|
1952 ]. |
|
1953 |
|
1954 fullProtocol ifTrue:[ |
|
1955 actualClass := currentClass. |
|
1956 self updateClassList. |
|
1957 self updateMethodCategoryListWithScroll:false. |
|
1958 self updateMethodListWithScroll:false. |
|
1959 self updateVariableList. |
|
1960 ^ self |
|
1961 ]. |
|
1962 currentClass notNil ifTrue:[ |
|
1963 self classSelectionChanged |
|
1964 ]. |
|
1965 codeView modified:false. |
|
1966 ] ifFalse:[ |
|
1967 instanceToggle turnOff. |
|
1968 classToggle turnOn |
|
1969 ] |
|
1970 ] |
|
1971 ! |
|
1972 |
|
1973 classProtocol |
|
1974 "switch to class protocol" |
|
1975 |
|
1976 showInstance ifTrue:[ |
|
1977 self checkSelectionChangeAllowed ifTrue:[ |
|
1978 instanceToggle turnOff. |
|
1979 classToggle turnOn. |
|
1980 showInstance := false. |
|
1981 |
|
1982 (variableListView notNil |
|
1983 and:[variableListView hasSelection]) ifTrue:[ |
|
1984 self unhilightMethodCategories. |
|
1985 self unhilightMethods. |
|
1986 variableListView deselect |
|
1987 ]. |
|
1988 |
|
1989 fullProtocol ifTrue:[ |
|
1990 actualClass := currentClass class. |
|
1991 self updateClassList. |
|
1992 self updateMethodCategoryListWithScroll:false. |
|
1993 self updateMethodListWithScroll:false. |
|
1994 self updateVariableList. |
|
1995 ^ self |
|
1996 ]. |
|
1997 currentClass notNil ifTrue:[ |
|
1998 self classSelectionChanged |
|
1999 ]. |
|
2000 codeView modified:false. |
|
2001 ] ifFalse:[ |
|
2002 instanceToggle turnOn. |
|
2003 classToggle turnOff |
|
2004 ] |
|
2005 ] |
|
2006 ! ! |
|
2007 |
|
2008 !SystemBrowser methodsFor:'method category stuff'! |
|
2009 |
|
2010 updateMethodCategoryListWithScroll:scroll |
|
2011 |categories| |
|
2012 |
|
2013 methodCategoryListView notNil ifTrue:[ |
|
2014 fullProtocol ifTrue:[ |
|
2015 currentClassHierarchy notNil ifTrue:[ |
|
2016 categories := self listOfAllMethodCategoriesInFullProtocolHierarchy:currentClassHierarchy |
|
2017 ] |
|
2018 ] ifFalse:[ |
|
2019 currentClass notNil ifTrue:[ |
|
2020 categories := self listOfAllMethodCategoriesInClass:actualClass |
|
2021 ] |
|
2022 ]. |
|
2023 methodCategoryListView list = categories ifFalse:[ |
|
2024 scroll ifTrue:[ |
|
2025 methodCategoryListView contents:categories |
|
2026 ] ifFalse:[ |
|
2027 methodCategoryListView setContents:categories |
|
2028 ]. |
|
2029 currentMethodCategory notNil ifTrue:[ |
|
2030 methodCategoryListView selectElement:currentMethodCategory |
|
2031 ] |
|
2032 ] |
|
2033 ] |
|
2034 ! |
|
2035 |
|
2036 listOfAllMethodCategoriesInClass:aClass |
|
2037 "answer a list of all method categories of the argument, aClass" |
|
2038 |
|
2039 |newList cat| |
|
2040 |
|
2041 newList := Text new. |
|
2042 aClass methodArray do:[:aMethod | |
|
2043 cat := aMethod category. |
|
2044 cat isNil ifTrue:[ |
|
2045 cat := '* no category *' |
|
2046 ]. |
|
2047 (newList includes:cat) ifFalse:[newList add:cat] |
|
2048 ]. |
|
2049 (newList size == 0) ifTrue:[^ nil]. |
|
2050 newList add:'* all *'. |
|
2051 ^ newList sort |
|
2052 ! |
|
2053 |
|
2054 methodCategorySelection:lineNr |
|
2055 "user clicked on a method category line - show selectors" |
|
2056 |
|
2057 |oldSelector| |
|
2058 |
|
2059 oldSelector := currentSelector. |
|
2060 |
|
2061 (fullProtocol not and:[currentClass isNil]) ifTrue:[^ self]. |
|
2062 |
|
2063 currentMethodCategory := methodCategoryListView selectionValue. |
|
2064 self methodCategorySelectionChanged. |
|
2065 |
|
2066 "if there is only one method, show it right away" |
|
2067 methodListView list size == 1 ifTrue:[ |
|
2068 methodListView selection:1. |
|
2069 self methodSelection:1 |
|
2070 ] ifFalse:[ |
|
2071 oldSelector notNil ifTrue:[ |
|
2072 methodListView selectElement:oldSelector. |
|
2073 methodListView selection notNil ifTrue:[ |
|
2074 self methodSelection:methodListView selection. |
|
2075 ] |
|
2076 ] |
|
2077 ] |
|
2078 |
|
2079 ! |
|
2080 |
|
2081 updateMethodCategoryList |
|
2082 self updateMethodCategoryListWithScroll:true |
|
2083 ! |
|
2084 |
|
2085 methodCategorySelectionChanged |
|
2086 "method category selection has changed - update dependant views" |
|
2087 |
|
2088 self withWaitCursorDo:[ |
|
2089 currentMethod := currentSelector := nil. |
|
2090 |
|
2091 self updateMethodList. |
|
2092 self updateCodeView. |
|
2093 |
|
2094 currentMethodCategory notNil ifTrue:[ |
|
2095 methodCategoryListView selectElement:currentMethodCategory |
|
2096 ]. |
|
2097 |
|
2098 self setAcceptAndExplainActionsForMethod. |
|
2099 self hilightMethodsInMethodCategoryList:false inMethodList:true. |
|
2100 ] |
|
2101 ! |
|
2102 |
|
2103 listOfAllMethodCategoriesInFullProtocolHierarchy:aClass |
|
2104 "answer a list of all method categories of the argument, aClass, |
|
2105 and all of its superclasses. |
|
2106 Used with fullProtocol browsing." |
|
2107 |
|
2108 |newList cat| |
|
2109 |
|
2110 newList := Text new. |
|
2111 self classesInFullProtocolHierarchy:aClass do:[:c | |
|
2112 c methodArray do:[:aMethod | |
|
2113 cat := aMethod category. |
|
2114 cat isNil ifTrue:[ |
|
2115 cat := '* no category *' |
|
2116 ]. |
|
2117 (newList includes:cat) ifFalse:[newList add:cat] |
|
2118 ] |
|
2119 ]. |
|
2120 (newList size == 0) ifTrue:[^ nil]. |
|
2121 newList add:'* all *'. |
|
2122 ^ newList sort |
|
2123 |
|
2124 ! |
|
2125 |
|
2126 checkMethodCategorySelected |
|
2127 currentMethodCategory isNil ifTrue:[ |
|
2128 self warn:'select a method category first'. |
|
2129 ^ false |
|
2130 ]. |
|
2131 ^ true |
|
2132 ! |
|
2133 |
|
2134 whenMethodCategorySelected:aBlock |
|
2135 self checkMethodCategorySelected ifTrue:[ |
|
2136 self withWaitCursorDo:aBlock |
|
2137 ] |
|
2138 ! |
|
2139 |
|
2140 copyMethodsFromClass:aClassName |
|
2141 |class box| |
|
2142 |
|
2143 currentClass notNil ifTrue:[ |
|
2144 Symbol hasInterned:aClassName ifTrue:[:sym | |
|
2145 (Smalltalk includesKey:sym) ifTrue:[ |
|
2146 class := Smalltalk at:sym |
|
2147 ]. |
|
2148 ]. |
|
2149 class isBehavior ifFalse:[ |
|
2150 self warn:'no class named %1' with:aClassName. |
|
2151 ^ self |
|
2152 ]. |
|
2153 |
|
2154 showInstance ifFalse:[ |
|
2155 class := class class |
|
2156 ]. |
|
2157 |
|
2158 "show enterbox for category to copy from" |
|
2159 |
|
2160 box := self enterBoxTitle:'name of category to copy from (matchpattern allowed, * for all):' |
|
2161 okText:'copy'. |
|
2162 box action:[:aString | self copyMethodsFromClass:class category:aString]. |
|
2163 box showAtPointer. |
|
2164 ] |
|
2165 ! |
|
2166 |
|
2167 copyMethodsFromClass:class category:category |
|
2168 |source| |
|
2169 |
|
2170 currentClass notNil ifTrue:[ |
|
2171 "/ codeView abortAction:[^ self]. |
|
2172 Object abortSignal catch:[ |
|
2173 class methodArray do:[:aMethod | |
|
2174 (category match:aMethod category) ifTrue:[ |
|
2175 source := aMethod source. |
|
2176 codeView contents:source. |
|
2177 codeView modified:false. |
|
2178 actualClass compiler compile:source |
|
2179 forClass:actualClass |
|
2180 inCategory:aMethod category |
|
2181 notifying:codeView. |
|
2182 self updateMethodCategoryListWithScroll:false. |
|
2183 self updateMethodListWithScroll:false. |
|
2184 ] |
|
2185 ] |
|
2186 ] |
|
2187 ] |
|
2188 ! |
|
2189 |
|
2190 newMethodCategory:aString |
|
2191 |categories| |
|
2192 |
|
2193 currentClass isNil ifTrue:[ |
|
2194 ^ self warn:'select/create a class first'. |
|
2195 ]. |
|
2196 categories := methodCategoryListView list. |
|
2197 categories isNil ifTrue:[categories := Text new]. |
|
2198 (categories includes:aString) ifFalse:[ |
|
2199 categories add:aString. |
|
2200 categories sort. |
|
2201 methodCategoryListView contents:categories |
|
2202 ]. |
|
2203 currentMethodCategory := aString. |
|
2204 self methodCategorySelectionChanged |
|
831 ! ! |
2205 ! ! |
832 |
2206 |
833 !SystemBrowser methodsFor:'initialize / release'! |
2207 !SystemBrowser methodsFor:'initialize / release'! |
834 |
2208 |
835 initialize |
2209 initialize |
838 self icon:(Form fromFile:(resources at:'ICON_FILE' default:'SBrowser.xbm') |
2212 self icon:(Form fromFile:(resources at:'ICON_FILE' default:'SBrowser.xbm') |
839 resolution:100). |
2213 resolution:100). |
840 |
2214 |
841 showInstance := true. |
2215 showInstance := true. |
842 fullClass := false. |
2216 fullClass := false. |
2217 fullProtocol := false. |
|
843 aspect := nil. |
2218 aspect := nil. |
844 |
2219 |
845 "inform me, when Smalltalk changes" |
2220 "inform me, when Smalltalk changes" |
846 Smalltalk addDependent:self |
2221 Smalltalk addDependent:self |
2222 ! |
|
2223 |
|
2224 realize |
|
2225 |v checkBlock| |
|
2226 |
|
2227 super realize. |
|
2228 |
|
2229 checkBlock := [:lineNr | self checkSelectionChangeAllowed]. |
|
2230 |
|
2231 v := classCategoryListView. |
|
2232 v notNil ifTrue:[ |
|
2233 v action:[:lineNr | self classCategorySelection:lineNr]. |
|
2234 v selectConditionBlock:checkBlock. |
|
2235 v ignoreReselect:false. |
|
2236 v contents:(self listOfAllClassCategories). |
|
2237 self initializeClassCategoryMenu |
|
2238 ]. |
|
2239 |
|
2240 v := classListView. |
|
2241 v notNil ifTrue:[ |
|
2242 v action:[:lineNr | self classSelection:lineNr]. |
|
2243 v selectConditionBlock:checkBlock. |
|
2244 v ignoreReselect:false. |
|
2245 self initializeClassMenu |
|
2246 ]. |
|
2247 |
|
2248 v := methodCategoryListView. |
|
2249 v notNil ifTrue:[ |
|
2250 v action:[:lineNr | self methodCategorySelection:lineNr]. |
|
2251 v selectConditionBlock:checkBlock. |
|
2252 v ignoreReselect:false. |
|
2253 self initializeMethodCategoryMenu |
|
2254 ]. |
|
2255 |
|
2256 v := methodListView. |
|
2257 v notNil ifTrue:[ |
|
2258 v action:[:lineNr | self methodSelection:lineNr]. |
|
2259 v selectConditionBlock:checkBlock. |
|
2260 v ignoreReselect:false. |
|
2261 self initializeMethodMenu |
|
2262 ]. |
|
2263 |
|
2264 v := classMethodListView. |
|
2265 v notNil ifTrue:[ |
|
2266 v action:[:lineNr | self classMethodSelection:lineNr]. |
|
2267 v selectConditionBlock:checkBlock. |
|
2268 v ignoreReselect:false. |
|
2269 self initializeClassMethodMenu |
|
2270 ]. |
|
2271 |
|
2272 v := variableListView. |
|
2273 v notNil ifTrue:[ |
|
2274 v action:[:lineNr | self variableSelection:lineNr]. |
|
2275 v ignoreReselect:false. |
|
2276 v toggleSelect:true |
|
2277 ] |
|
2278 |
|
2279 ! |
|
2280 |
|
2281 terminate |
|
2282 (self checkSelectionChangeAllowed) ifTrue:[ |
|
2283 super terminate |
|
2284 ] |
|
847 ! |
2285 ! |
848 |
2286 |
849 destroy |
2287 destroy |
850 "relese dependant - destroy popups" |
2288 "relese dependant - destroy popups" |
851 |
2289 |
855 currentClass := nil |
2293 currentClass := nil |
856 ]. |
2294 ]. |
857 super destroy |
2295 super destroy |
858 ! |
2296 ! |
859 |
2297 |
860 terminate |
2298 autoSearch:aString |
861 (self checkSelectionChangeAllowed) ifTrue:[ |
2299 "used with class-method list browsing. If true, |
862 super terminate |
2300 selecting an entry from the list will automatically |
863 ] |
2301 search for the searchstring in the codeView" |
864 ! |
2302 |
865 |
2303 self setSearchPattern:aString. |
866 createTogglesIn:aFrame |
2304 autoSearch := aString |
867 "create and setup the class/instance toggles" |
2305 ! |
868 |
2306 |
869 |halfSpacing h| |
2307 title:someString |
870 |
2308 myLabel := someString. |
871 instanceToggle := Toggle label:(resources at:'instance') in:aFrame. |
2309 self label:someString. |
872 h := instanceToggle height. |
2310 |
873 instanceToggle origin:(0.0 @ 1.0) corner:(0.5 @ 1.0). |
2311 ! ! |
874 instanceToggle topInset:(h negated). |
2312 |
875 |
2313 !SystemBrowser methodsFor:'initialize subviews'! |
876 instanceToggle turnOn. |
|
877 instanceToggle pressAction:[self instanceProtocol]. |
|
878 instanceToggle releaseAction:[self classProtocol]. |
|
879 |
|
880 classToggle := Toggle label:(resources at:'class') in:aFrame. |
|
881 h := classToggle height. |
|
882 classToggle origin:(0.5 @ 1.0) corner:(1.0 @ 1.0). |
|
883 classToggle topInset:(h negated). |
|
884 |
|
885 classToggle turnOff. |
|
886 classToggle pressAction:[self classProtocol]. |
|
887 classToggle releaseAction:[self instanceProtocol]. |
|
888 |
|
889 StyleSheet is3D ifTrue:[ |
|
890 instanceToggle leftInset:(ViewSpacing // 2). |
|
891 classToggle leftInset:(ViewSpacing // 2). |
|
892 instanceToggle rightInset:ViewSpacing - (ViewSpacing // 2). |
|
893 classToggle rightInset:ViewSpacing - (ViewSpacing // 2). |
|
894 ]. |
|
895 ! |
|
896 |
2314 |
897 createClassListViewIn:frame |
2315 createClassListViewIn:frame |
898 "setup the classlist subview, with its toggles" |
2316 "setup the classlist subview, with its toggles" |
899 |
2317 |
900 |v panel oldStyle| |
2318 |v panel oldStyle| |
926 - instanceToggle borderWidth |
2344 - instanceToggle borderWidth |
927 + v borderWidth)] |
2345 + v borderWidth)] |
928 in:frame. |
2346 in:frame. |
929 |
2347 |
930 v := ScrollableView for:SelectionInListView in:panel. |
2348 v := ScrollableView for:SelectionInListView in:panel. |
931 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.5). |
2349 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.7). |
932 classListView := v scrolledView. |
2350 classListView := v scrolledView. |
933 |
2351 |
934 |
2352 |
935 v := ScrollableView for:SelectionInListView in:panel. |
2353 v := ScrollableView for:SelectionInListView in:panel. |
936 v origin:(0.0 @ 0.5) |
2354 v origin:(0.0 @ 0.7) |
937 corner:(1.0 @ 1.0). |
2355 corner:(1.0 @ 1.0). |
938 |
2356 |
939 variableListView := v scrolledView |
2357 variableListView := v scrolledView |
940 ] |
2358 ] |
2359 ! |
|
2360 |
|
2361 createCodeViewIn:aView at:relY |
|
2362 "setup the code view" |
|
2363 |v| |
|
2364 |
|
2365 v := HVScrollableView for:CodeView miniScrollerH:true miniScrollerV:false in:aView. |
|
2366 v origin:(0.0 @ relY) corner:(1.0 @ 1.0). |
|
2367 codeView := v scrolledView |
|
2368 ! |
|
2369 |
|
2370 createTogglesIn:aFrame |
|
2371 "create and setup the class/instance toggles" |
|
2372 |
|
2373 |halfSpacing h classAction instanceAction| |
|
2374 |
|
2375 classAction := [self classProtocol]. |
|
2376 instanceAction := [self instanceProtocol]. |
|
2377 |
|
2378 instanceToggle := Toggle label:(resources at:'instance') in:aFrame. |
|
2379 h := instanceToggle height. |
|
2380 instanceToggle origin:(0.0 @ 1.0) corner:(0.5 @ 1.0). |
|
2381 instanceToggle topInset:(h negated). |
|
2382 |
|
2383 instanceToggle turnOn. |
|
2384 instanceToggle pressAction:instanceAction. |
|
2385 instanceToggle releaseAction:classAction. |
|
2386 |
|
2387 classToggle := Toggle label:(resources at:'class') in:aFrame. |
|
2388 h := classToggle height. |
|
2389 classToggle origin:(0.5 @ 1.0) corner:(1.0 @ 1.0). |
|
2390 classToggle topInset:(h negated). |
|
2391 |
|
2392 classToggle turnOff. |
|
2393 classToggle pressAction:classAction. |
|
2394 classToggle releaseAction:instanceAction. |
|
2395 |
|
2396 StyleSheet is3D ifTrue:[ |
|
2397 instanceToggle leftInset:(ViewSpacing // 2). |
|
2398 classToggle leftInset:(ViewSpacing // 2). |
|
2399 instanceToggle rightInset:ViewSpacing - (ViewSpacing // 2). |
|
2400 classToggle rightInset:ViewSpacing - (ViewSpacing // 2). |
|
2401 ]. |
|
941 ! |
2402 ! |
942 |
2403 |
943 createCodeViewIn:aView |
2404 createCodeViewIn:aView |
944 "setup the code view" |
2405 "setup the code view" |
945 |v| |
2406 |
946 |
2407 ^ self createCodeViewIn:aView at:0.25 |
947 v := HVScrollableView for:CodeView miniScrollerH:true miniScrollerV:false in:aView. |
2408 ! |
948 v origin:(0.0 @ 0.25) corner:(1.0 @ 1.0). |
2409 |
949 codeView := v scrolledView |
2410 setupForList:aList |
950 ! |
2411 "setup subviews to browse methods from a list" |
951 |
2412 |
952 setupActions |
2413 |vpanel v| |
953 "/ |v| |
2414 |
954 |
2415 vpanel := VariableVerticalPanel |
955 "/ v := classCategoryListView. |
2416 origin:(0.0 @ 0.0) |
956 "/ v notNil ifTrue:[ |
2417 corner:(1.0 @ 1.0) |
957 "/ v action:[:lineNr | self classCategorySelection:lineNr]. |
2418 in:self. |
958 "/ v selectConditionBlock:[self checkSelectionChangeAllowed]. |
2419 |
959 "/ v ignoreReselect:false. |
2420 v := ScrollableView for:SelectionInListView in:vpanel. |
960 "/ ]. |
2421 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.25). |
961 "/ v := classListView. |
2422 classMethodListView := v scrolledView. |
962 "/ v notNil ifTrue:[ |
2423 classMethodListView contents:aList. |
963 "/ v action:[:lineNr | self classSelection:lineNr]. |
2424 |
964 "/ v selectConditionBlock:[self checkSelectionChangeAllowed]. |
2425 self createCodeViewIn:vpanel. |
965 "/ v ignoreReselect:false. |
2426 self updateCodeView |
966 "/ ]. |
|
967 "/ v := methodCategoryListView. |
|
968 "/ v notNil ifTrue:[ |
|
969 "/ v action:[:lineNr | self methodCategorySelection:lineNr]. |
|
970 "/ v selectConditionBlock:[self checkSelectionChangeAllowed]. |
|
971 "/ v ignoreReselect:false. |
|
972 "/ ]. |
|
973 "/ v := methodListView. |
|
974 "/ v notNil ifTrue:[ |
|
975 "/ v action:[:lineNr | self methodSelection:lineNr]. |
|
976 "/ v selectConditionBlock:[self checkSelectionChangeAllowed]. |
|
977 "/ v ignoreReselect:false. |
|
978 "/ ]. |
|
979 "/ v := classMethodListView. |
|
980 "/ v notNil ifTrue:[ |
|
981 "/ v action:[:lineNr | self listSelection:lineNr]. |
|
982 "/ v selectConditionBlock:[self checkSelectionChangeAllowed]. |
|
983 "/ v ignoreReselect:false. |
|
984 "/ ] |
|
985 ! |
2427 ! |
986 |
2428 |
987 setupForAll |
2429 setupForAll |
988 "create subviews for a full browser" |
2430 "create subviews for a full browser" |
989 |
2431 |
996 v := HVScrollableView for:SelectionInListView |
2438 v := HVScrollableView for:SelectionInListView |
997 miniScrollerH:true miniScrollerV:false |
2439 miniScrollerH:true miniScrollerV:false |
998 in:hpanel. |
2440 in:hpanel. |
999 v origin:(0.0 @ 0.0) corner:(0.25 @ 1.0). |
2441 v origin:(0.0 @ 0.0) corner:(0.25 @ 1.0). |
1000 classCategoryListView := v scrolledView. |
2442 classCategoryListView := v scrolledView. |
1001 "/ classCategoryListView contents:(self listOfAllClassCategories). |
|
1002 |
2443 |
1003 frame := View origin:(0.25 @ 0.0) corner:(0.5 @ 1.0) in:hpanel. |
2444 frame := View origin:(0.25 @ 0.0) corner:(0.5 @ 1.0) in:hpanel. |
1004 self createClassListViewIn:frame. |
2445 self createClassListViewIn:frame. |
1005 |
2446 |
1006 v := HVScrollableView for:SelectionInListView miniScrollerH:true miniScrollerV:false in:hpanel. |
2447 v := HVScrollableView for:SelectionInListView miniScrollerH:true miniScrollerV:false in:hpanel. |
1009 |
2450 |
1010 v := HVScrollableView for:SelectionInListView miniScrollerH:true miniScrollerV:false in:hpanel. |
2451 v := HVScrollableView for:SelectionInListView miniScrollerH:true miniScrollerV:false in:hpanel. |
1011 v origin:(0.75 @ 0.0) corner:(1.0 @ 1.0). |
2452 v origin:(0.75 @ 0.0) corner:(1.0 @ 1.0). |
1012 methodListView := v scrolledView. |
2453 methodListView := v scrolledView. |
1013 |
2454 |
1014 "/ self setupActions. |
|
1015 self createCodeViewIn:vpanel |
2455 self createCodeViewIn:vpanel |
2456 ! |
|
2457 |
|
2458 setupForClassHierarchy:aClass |
|
2459 "setup subviews to browse a class hierarchy" |
|
2460 |
|
2461 |vpanel hpanel frame v| |
|
2462 |
|
2463 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
2464 corner:(1.0 @ 1.0) |
|
2465 in:self. |
|
2466 |
|
2467 " |
|
2468 notice: we use a different ratio here |
|
2469 " |
|
2470 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.4) in:vpanel. |
|
2471 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
2472 |
|
2473 self createClassListViewIn:frame. |
|
2474 |
|
2475 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2476 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
2477 methodCategoryListView := v scrolledView. |
|
2478 |
|
2479 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2480 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
2481 methodListView := v scrolledView. |
|
2482 |
|
2483 self createCodeViewIn:vpanel at:0.4. |
|
2484 |
|
2485 currentClassHierarchy := aClass. |
|
2486 self updateClassList. |
|
2487 self updateMethodCategoryList. |
|
2488 self updateMethodList. |
|
2489 self updateCodeView |
|
1016 ! |
2490 ! |
1017 |
2491 |
1018 setupForFullClass |
2492 setupForFullClass |
1019 "setup subviews to browse a class as full text" |
2493 "setup subviews to browse a class as full text" |
1020 |
2494 |
1033 |
2507 |
1034 v := ScrollableView for:SelectionInListView in:hpanel. |
2508 v := ScrollableView for:SelectionInListView in:hpanel. |
1035 v origin:(0.5 @ 0.0) corner:(1.0 @ 1.0). |
2509 v origin:(0.5 @ 0.0) corner:(1.0 @ 1.0). |
1036 classListView := v scrolledView. |
2510 classListView := v scrolledView. |
1037 |
2511 |
1038 "/ self setupActions. |
|
1039 self createCodeViewIn:vpanel. |
2512 self createCodeViewIn:vpanel. |
1040 |
2513 |
1041 fullClass := true. |
2514 fullClass := true. |
1042 self updateCodeView |
|
1043 ! |
|
1044 |
|
1045 setupForClassCategory:aClassCategory |
|
1046 "setup subviews to browse a class category" |
|
1047 |
|
1048 |vpanel hpanel frame v| |
|
1049 |
|
1050 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
1051 corner:(1.0 @ 1.0) |
|
1052 in:self. |
|
1053 |
|
1054 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.25) in:vpanel. |
|
1055 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
1056 |
|
1057 self createClassListViewIn:frame. |
|
1058 |
|
1059 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1060 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
1061 methodCategoryListView := v scrolledView. |
|
1062 |
|
1063 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1064 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
1065 methodListView := v scrolledView. |
|
1066 |
|
1067 "/ self setupActions. |
|
1068 self createCodeViewIn:vpanel. |
|
1069 |
|
1070 currentClassCategory := aClassCategory. |
|
1071 self updateClassList. |
|
1072 self updateMethodCategoryList. |
|
1073 self updateMethodList. |
|
1074 self updateCodeView |
|
1075 ! |
|
1076 |
|
1077 setupForClassList:aList |
|
1078 "setup subviews to browse classes from a list" |
|
1079 |
|
1080 |vpanel hpanel frame l v| |
|
1081 |
|
1082 vpanel := VariableVerticalPanel |
|
1083 origin:(0.0 @ 0.0) corner:(1.0 @ 1.0) in:self. |
|
1084 |
|
1085 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.25) in:vpanel. |
|
1086 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
1087 |
|
1088 self createClassListViewIn:frame. |
|
1089 |
|
1090 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1091 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
1092 methodCategoryListView := v scrolledView. |
|
1093 |
|
1094 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1095 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
1096 methodListView := v scrolledView. |
|
1097 |
|
1098 "/ self setupActions. |
|
1099 self createCodeViewIn:vpanel. |
|
1100 |
|
1101 l := aList collect:[:entry | entry name]. |
|
1102 classListView list:(l sort). |
|
1103 |
|
1104 self updateMethodCategoryList. |
|
1105 self updateMethodList. |
|
1106 self updateCodeView |
|
1107 ! |
|
1108 |
|
1109 setupForClassHierarchy:aClass |
|
1110 "setup subviews to browse a class hierarchy" |
|
1111 |
|
1112 |vpanel hpanel frame v| |
|
1113 |
|
1114 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
1115 corner:(1.0 @ 1.0) |
|
1116 in:self. |
|
1117 |
|
1118 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.25) in:vpanel. |
|
1119 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
1120 |
|
1121 self createClassListViewIn:frame. |
|
1122 |
|
1123 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1124 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
1125 methodCategoryListView := v scrolledView. |
|
1126 |
|
1127 v := ScrollableView for:SelectionInListView in:hpanel. |
|
1128 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
1129 methodListView := v scrolledView. |
|
1130 |
|
1131 "/ self setupActions. |
|
1132 self createCodeViewIn:vpanel. |
|
1133 |
|
1134 currentClassHierarchy := aClass. |
|
1135 self updateClassList. |
|
1136 self updateMethodCategoryList. |
|
1137 self updateMethodList. |
|
1138 self updateCodeView |
2515 self updateCodeView |
1139 ! |
2516 ! |
1140 |
2517 |
1141 setupForClass:aClass |
2518 setupForClass:aClass |
1142 "create subviews for browsing a single class" |
2519 "create subviews for browsing a single class" |
1165 |
2542 |
1166 v := ScrollableView for:SelectionInListView in:hpanel. |
2543 v := ScrollableView for:SelectionInListView in:hpanel. |
1167 v origin:(0.5 @ 0.0) corner:(1.0 @ 1.0). |
2544 v origin:(0.5 @ 0.0) corner:(1.0 @ 1.0). |
1168 methodListView := v scrolledView. |
2545 methodListView := v scrolledView. |
1169 |
2546 |
1170 "/ self setupActions. |
|
1171 self createCodeViewIn:vpanel. |
2547 self createCodeViewIn:vpanel. |
1172 |
2548 |
1173 self switchToClass:aClass. |
2549 self switchToClass:aClass. |
1174 actualClass := aClass. |
2550 actualClass := aClass. |
1175 self updateMethodCategoryList. |
2551 self updateMethodCategoryList. |
1176 self updateMethodList. |
2552 self updateMethodList. |
1177 self updateCodeView |
2553 self updateCodeView |
1178 ! |
2554 ! |
1179 |
2555 |
2556 setupForClassCategory:aClassCategory |
|
2557 "setup subviews to browse a class category" |
|
2558 |
|
2559 |vpanel hpanel frame v| |
|
2560 |
|
2561 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
2562 corner:(1.0 @ 1.0) |
|
2563 in:self. |
|
2564 |
|
2565 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.25) in:vpanel. |
|
2566 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
2567 |
|
2568 self createClassListViewIn:frame. |
|
2569 |
|
2570 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2571 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
2572 methodCategoryListView := v scrolledView. |
|
2573 |
|
2574 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2575 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
2576 methodListView := v scrolledView. |
|
2577 |
|
2578 self createCodeViewIn:vpanel. |
|
2579 |
|
2580 currentClassCategory := aClassCategory. |
|
2581 self updateClassList. |
|
2582 self updateMethodCategoryList. |
|
2583 self updateMethodList. |
|
2584 self updateCodeView |
|
2585 ! |
|
2586 |
|
2587 setupForClass:aClass selector:selector |
|
2588 "setup subviews to browse a single method" |
|
2589 |
|
2590 |v| |
|
2591 |
|
2592 v := ScrollableView for:CodeView in:self. |
|
2593 v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0). |
|
2594 codeView := v scrolledView. |
|
2595 |
|
2596 currentClassCategory := aClass category. |
|
2597 self switchToClass:aClass. |
|
2598 actualClass := aClass. |
|
2599 currentSelector := selector. |
|
2600 currentMethod := currentClass compiledMethodAt:selector. |
|
2601 currentMethodCategory := currentMethod category. |
|
2602 self updateCodeView |
|
2603 ! |
|
2604 |
|
2605 setupForClassList:aList |
|
2606 "setup subviews to browse classes from a list" |
|
2607 |
|
2608 |vpanel hpanel frame l v| |
|
2609 |
|
2610 vpanel := VariableVerticalPanel |
|
2611 origin:(0.0 @ 0.0) corner:(1.0 @ 1.0) in:self. |
|
2612 |
|
2613 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.25) in:vpanel. |
|
2614 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
2615 |
|
2616 self createClassListViewIn:frame. |
|
2617 |
|
2618 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2619 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
2620 methodCategoryListView := v scrolledView. |
|
2621 |
|
2622 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2623 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
2624 methodListView := v scrolledView. |
|
2625 |
|
2626 self createCodeViewIn:vpanel. |
|
2627 |
|
2628 l := aList collect:[:entry | entry name]. |
|
2629 classListView list:(l sort). |
|
2630 |
|
2631 self updateMethodCategoryList. |
|
2632 self updateMethodList. |
|
2633 self updateCodeView |
|
2634 ! |
|
2635 |
|
1180 setupForClass:aClass methodCategory:aMethodCategory |
2636 setupForClass:aClass methodCategory:aMethodCategory |
1181 "setup subviews to browse a method category" |
2637 "setup subviews to browse a method category" |
1182 |
2638 |
1183 |vpanel v| |
2639 |vpanel v| |
1184 |
2640 |
1188 |
2644 |
1189 v := ScrollableView for:SelectionInListView in:vpanel. |
2645 v := ScrollableView for:SelectionInListView in:vpanel. |
1190 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.25). |
2646 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.25). |
1191 methodListView := v scrolledView. |
2647 methodListView := v scrolledView. |
1192 |
2648 |
1193 "/ self setupActions. |
|
1194 self createCodeViewIn:vpanel. |
2649 self createCodeViewIn:vpanel. |
1195 |
2650 |
1196 currentClassCategory := aClass category. |
2651 currentClassCategory := aClass category. |
1197 self switchToClass:aClass. |
2652 self switchToClass:aClass. |
1198 actualClass := aClass. |
2653 actualClass := aClass. |
1199 currentMethodCategory := aMethodCategory. |
2654 currentMethodCategory := aMethodCategory. |
1200 self updateMethodList. |
2655 self updateMethodList. |
1201 self updateCodeView |
2656 self updateCodeView |
1202 ! |
2657 ! |
1203 |
2658 |
1204 setupForClass:aClass selector:selector |
2659 setupForFullClassProtocol:aClass |
1205 "setup subviews to browse a single method" |
2660 "setup subviews to browse a classes full protocol" |
1206 |
2661 |
1207 |v| |
2662 |vpanel hpanel frame v| |
1208 |
2663 |
1209 v := ScrollableView for:CodeView in:self. |
2664 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
1210 v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0). |
2665 corner:(1.0 @ 1.0) |
1211 codeView := v scrolledView. |
2666 in:self. |
1212 |
2667 |
1213 currentClassCategory := aClass category. |
2668 " |
1214 self switchToClass:aClass. |
2669 notice: we use a different ratio here |
1215 actualClass := aClass. |
2670 " |
1216 currentMethod := currentClass compiledMethodAt:selector. |
2671 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.4) in:vpanel. |
1217 currentMethodCategory := currentMethod category. |
2672 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
1218 self updateCodeView |
2673 |
1219 ! |
2674 self createClassListViewIn:frame. |
1220 |
2675 classListView multipleSelectOk:true. |
1221 setupForList:aList |
2676 classListView toggleSelect:true. |
1222 "setup subviews to browse methods from a list" |
2677 classListView strikeOut:true. |
1223 |
2678 |
1224 |vpanel v| |
2679 v := ScrollableView for:SelectionInListView in:hpanel. |
1225 |
2680 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
1226 vpanel := VariableVerticalPanel |
2681 methodCategoryListView := v scrolledView. |
1227 origin:(0.0 @ 0.0) |
2682 |
1228 corner:(1.0 @ 1.0) |
2683 v := ScrollableView for:SelectionInListView in:hpanel. |
1229 in:self. |
2684 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
1230 |
2685 methodListView := v scrolledView. |
1231 v := ScrollableView for:SelectionInListView in:vpanel. |
2686 |
1232 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.25). |
2687 self createCodeViewIn:vpanel at:0.4. |
1233 classMethodListView := v scrolledView. |
2688 |
1234 classMethodListView contents:aList. |
2689 currentClassHierarchy := actualClass := currentClass := aClass. |
2690 fullProtocol := true. |
|
2691 |
|
2692 self updateClassList. |
|
2693 self updateMethodCategoryList. |
|
2694 self updateMethodList. |
|
2695 self updateCodeView. |
|
2696 self updateVariableList. |
|
2697 |
|
2698 ! |
|
2699 |
|
2700 setupForFullClassHierarchy:aClass |
|
2701 "setup subviews to browse a class hierarchy" |
|
2702 |
|
2703 |vpanel hpanel frame v| |
|
2704 |
|
2705 vpanel := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
2706 corner:(1.0 @ 1.0) |
|
2707 in:self. |
|
2708 |
|
2709 hpanel := View origin:(0.0 @ 0.0) corner:(1.0 @ 0.4) in:vpanel. |
|
2710 frame := View origin:(0.0 @ 0.0) corner:(0.33 @ 1.0) in:hpanel. |
|
2711 |
|
2712 self createClassListViewIn:frame. |
|
2713 classListView multipleSelectOk:true. |
|
2714 classListView toggleSelect:true. |
|
2715 classListView strikeOut:true. |
|
2716 |
|
2717 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2718 v origin:(0.33 @ 0.0) corner:(0.66 @ 1.0). |
|
2719 methodCategoryListView := v scrolledView. |
|
2720 |
|
2721 v := ScrollableView for:SelectionInListView in:hpanel. |
|
2722 v origin:(0.66 @ 0.0) corner:(1.0 @ 1.0). |
|
2723 methodListView := v scrolledView. |
|
1235 |
2724 |
1236 "/ self setupActions. |
2725 "/ self setupActions. |
1237 self createCodeViewIn:vpanel. |
2726 self createCodeViewIn:vpanel at:0.4. |
1238 |
2727 |
1239 self updateCodeView |
2728 currentClassHierarchy := actualClass := aClass. |
2729 fullProtocol := true. |
|
2730 |
|
2731 self updateClassList. |
|
2732 self updateMethodCategoryList. |
|
2733 self updateMethodList. |
|
2734 self updateCodeView. |
|
2735 self updateVariableList. |
|
2736 |
|
1240 ! ! |
2737 ! ! |
1241 |
2738 |
1242 !SystemBrowser methodsFor:'realization'! |
2739 !SystemBrowser methodsFor:'unused'! |
1243 |
2740 |
1244 realize |
2741 listOfAllSelectorsInCategory:aCategory inHierarchyOfClass:aClass |
1245 |v checkBlock| |
2742 "answer a list of all selectors in a given method category |
1246 |
2743 of the argument, aClass and its superclasses" |
1247 super realize. |
2744 |
1248 |
2745 |newList thisList searchCategory selector| |
1249 checkBlock := [:lineNr | self checkSelectionChangeAllowed]. |
2746 |
1250 |
2747 newList := Set new. |
1251 v := classCategoryListView. |
2748 self classesInHierarchy:aClass do:[:c | |
1252 v notNil ifTrue:[ |
2749 (aCategory = '* all *') ifTrue:[ |
1253 v action:[:lineNr | self classCategorySelection:lineNr]. |
2750 newList addAll:(c selectorArray) |
1254 v selectConditionBlock:checkBlock. |
2751 ] ifFalse:[ |
1255 v ignoreReselect:false. |
2752 (aCategory = '* no category *') ifTrue:[ |
1256 v contents:(self listOfAllClassCategories). |
2753 searchCategory := nil |
1257 self initializeClassCategoryMenu |
2754 ] ifFalse:[ |
1258 ]. |
2755 searchCategory := aCategory |
1259 |
2756 ]. |
1260 v := classListView. |
2757 c methodArray with:c selectorArray do:[:aMethod :selector | |
1261 v notNil ifTrue:[ |
2758 (aMethod category = searchCategory) ifTrue:[ |
1262 v action:[:lineNr | self classSelection:lineNr]. |
2759 newList add:selector |
1263 v selectConditionBlock:checkBlock. |
2760 ] |
1264 v ignoreReselect:false. |
2761 ] |
1265 self initializeClassMenu |
2762 ]. |
1266 ]. |
2763 ]. |
1267 |
2764 (newList size == 0) ifTrue:[^ nil]. |
1268 v := methodCategoryListView. |
2765 ^ newList asOrderedCollection sort |
1269 v notNil ifTrue:[ |
2766 ! |
1270 v action:[:lineNr | self methodCategorySelection:lineNr]. |
2767 |
1271 v selectConditionBlock:checkBlock. |
2768 listOfAllMethodCategoriesInHierarchy:aClass |
1272 v ignoreReselect:false. |
2769 "answer a list of all method categories of the argument, aClass, |
1273 self initializeMethodCategoryMenu |
2770 and all of its superclasses" |
1274 ]. |
2771 |
1275 |
2772 |newList cat| |
1276 v := methodListView. |
2773 |
1277 v notNil ifTrue:[ |
2774 newList := Text new. |
1278 v action:[:lineNr | self methodSelection:lineNr]. |
2775 self classesInHierarchy:aClass do:[:c | |
1279 v selectConditionBlock:checkBlock. |
2776 c methodArray do:[:aMethod | |
1280 v ignoreReselect:false. |
2777 cat := aMethod category. |
1281 self initializeMethodMenu |
2778 cat isNil ifTrue:[ |
1282 ]. |
2779 cat := '* no category *' |
1283 |
2780 ]. |
1284 v := classMethodListView. |
2781 (newList includes:cat) ifFalse:[newList add:cat] |
1285 v notNil ifTrue:[ |
2782 ] |
1286 v action:[:lineNr | self listSelection:lineNr]. |
2783 ]. |
1287 v selectConditionBlock:checkBlock. |
2784 (newList size == 0) ifTrue:[^ nil]. |
1288 v ignoreReselect:false. |
2785 newList add:'* all *'. |
1289 self initializeClassMethodMenu |
2786 ^ newList sort |
1290 ] |
2787 |
1291 ! ! |
2788 ! ! |
1292 |
2789 |
1293 !SystemBrowser methodsFor:'private'! |
2790 !SystemBrowser methodsFor:'class stuff'! |
1294 |
|
1295 checkSelectionChangeAllowed |
|
1296 "return true, if selection change is ok; |
|
1297 its not ok, if code has been changed. |
|
1298 in this case, return the result of a user query" |
|
1299 |
|
1300 |box| |
|
1301 |
|
1302 codeView modified ifFalse:[ |
|
1303 ^ true |
|
1304 ]. |
|
1305 box := YesNoBox |
|
1306 title:(resources at:'contents in codeview has not been accepted.\\Modifications will be lost when continuing.') withCRs |
|
1307 yesText:(resources at:'continue') |
|
1308 noText:(resources at:'abort'). |
|
1309 ^ box confirm |
|
1310 ! |
|
1311 |
2791 |
1312 switchToClass:newClass |
2792 switchToClass:newClass |
2793 fullProtocol ifTrue:[^ self]. |
|
1313 currentClass notNil ifTrue:[ |
2794 currentClass notNil ifTrue:[ |
1314 currentClass removeDependent:self |
2795 currentClass removeDependent:self |
1315 ]. |
2796 ]. |
1316 currentClass := newClass. |
2797 currentClass := newClass. |
1317 currentClass notNil ifTrue:[ |
2798 currentClass notNil ifTrue:[ |
1318 currentClass addDependent:self. |
2799 currentClass addDependent:self. |
1319 ]. |
2800 ]. |
1320 self normalLabel |
2801 self normalLabel |
1321 ! |
2802 ! |
1322 |
2803 |
1323 showExplanation:someText |
2804 classSelectionChanged |
1324 "show explanation from Parser" |
2805 |oldMethodCategory oldMethod oldSelector| |
1325 |
2806 |
1326 self notify:someText |
2807 self withWaitCursorDo:[ |
1327 ! |
2808 oldMethodCategory := currentMethodCategory. |
1328 |
2809 oldMethod := currentMethod. |
1329 normalLabel |
2810 oldSelector := currentSelector. |
1330 "set the normal (inactive) window- and icon labels" |
2811 |
1331 |
2812 showInstance ifTrue:[ |
1332 currentClass notNil ifTrue:[ |
2813 actualClass := currentClass |
1333 self label:'System Browser: ', currentClass name. |
|
1334 self iconLabel:currentClass name |
|
1335 ] ifFalse:[ |
|
1336 self label:'System Browser'. |
|
1337 self iconLabel:'System Browser'. |
|
1338 ] |
|
1339 ! |
|
1340 |
|
1341 setSearchPattern:aString |
|
1342 codeView setSearchPattern:aString |
|
1343 ! |
|
1344 |
|
1345 selectorToSearchFor |
|
1346 "look in codeView and methodListView for a search-string when searching for selectors" |
|
1347 |
|
1348 |sel t| |
|
1349 |
|
1350 sel := codeView selection. |
|
1351 sel notNil ifTrue:[ |
|
1352 sel := sel asString. |
|
1353 t := Parser selectorInExpression:sel. |
|
1354 t notNil ifTrue:[ |
|
1355 sel := t |
|
1356 ]. |
|
1357 sel := sel withoutSpaces |
|
1358 ] ifFalse:[ |
|
1359 methodListView notNil ifTrue:[ |
|
1360 sel := methodListView selectionValue |
|
1361 ] ifFalse:[ |
2814 ] ifFalse:[ |
1362 classMethodListView notNil ifTrue:[ |
2815 actualClass := currentClass class |
1363 sel := classMethodListView selectionValue. |
2816 ]. |
1364 sel notNil ifTrue:[ |
2817 currentMethodCategory := nil. |
1365 sel := self selectorFromClassMethodString:sel |
2818 currentMethod := nil. |
1366 ] |
2819 currentSelector := nil. |
2820 |
|
2821 self updateVariableList. |
|
2822 self updateMethodCategoryList. |
|
2823 |
|
2824 oldMethodCategory notNil ifTrue:[ |
|
2825 methodCategoryListView selectElement:oldMethodCategory. |
|
2826 methodCategoryListView selection notNil ifTrue:[ |
|
2827 currentMethodCategory := oldMethodCategory. |
|
2828 self methodCategorySelectionChanged |
|
1367 ] |
2829 ] |
1368 ]. |
2830 ]. |
1369 sel notNil ifTrue:[ |
2831 self updateMethodList. |
1370 sel := sel withoutSpaces |
2832 self updateCodeView. |
2833 |
|
2834 fullClass ifTrue:[ |
|
2835 codeView acceptAction:[:theCode | |
|
2836 codeView cursor:Cursor execute. |
|
2837 Object abortSignal catch:[ |
|
2838 self compileCode:theCode asString. |
|
2839 codeView modified:false. |
|
2840 ]. |
|
2841 codeView cursor:Cursor normal. |
|
2842 ]. |
|
1371 ] ifFalse:[ |
2843 ] ifFalse:[ |
1372 sel := '' |
2844 self classDefinition. |
1373 ] |
2845 codeView acceptAction:[:theCode | |
1374 ]. |
2846 codeView cursor:Cursor execute. |
1375 ^ sel |
2847 Object abortSignal catch:[ |
1376 ! |
2848 (Compiler evaluate:theCode asString notifying:codeView) |
1377 |
2849 isBehavior ifTrue:[ |
1378 stringToSearchFor |
2850 self classCategoryUpdate. |
1379 "look in codeView and methodListView for a search-string when searching for classes/names" |
2851 self updateClassListWithScroll:false. |
1380 |
2852 codeView modified:false. |
1381 |sel| |
2853 ]. |
1382 |
2854 ]. |
1383 sel := codeView selection. |
2855 codeView cursor:Cursor normal. |
1384 sel notNil ifTrue:[ |
2856 ]. |
1385 sel := sel asString withoutSpaces |
2857 ]. |
1386 ] ifFalse:[ |
2858 codeView explainAction:nil. |
1387 sel isNil ifTrue:[ |
2859 |
1388 currentClass notNil ifTrue:[ |
2860 classCategoryListView notNil ifTrue:[ |
1389 sel := currentClass name |
2861 (currentClassCategory = currentClass category) ifFalse:[ |
2862 currentClassCategory := currentClass category. |
|
2863 classCategoryListView selectElement:currentClassCategory |
|
1390 ] |
2864 ] |
1391 ]. |
2865 ]. |
1392 sel notNil ifTrue:[ |
2866 |
1393 sel := sel withoutSpaces |
2867 "set self for doits. This allows accessing the current class |
2868 as self, and access to the class variables by name. |
|
2869 " |
|
2870 codeView doItAction:[:theCode | |
|
2871 |compiler| |
|
2872 |
|
2873 currentClass isNil ifTrue:[ |
|
2874 compiler := Compiler |
|
2875 ] ifFalse:[ |
|
2876 compiler := currentClass compiler |
|
2877 ]. |
|
2878 compiler |
|
2879 evaluate:theCode |
|
2880 in:nil |
|
2881 receiver:currentClass |
|
2882 notifying:codeView |
|
2883 logged:false |
|
2884 ifFail:nil |
|
2885 ]. |
|
2886 ] |
|
2887 ! |
|
2888 |
|
2889 updateClassListWithScroll:scroll |
|
2890 |classes oldClassName| |
|
2891 |
|
2892 classListView notNil ifTrue:[ |
|
2893 " |
|
2894 refetch in case we are not up to date |
|
2895 " |
|
2896 (currentClass notNil and:[fullProtocol not]) ifTrue:[ |
|
2897 oldClassName := currentClass name. |
|
2898 currentClass := Smalltalk at:(oldClassName asSymbol). |
|
2899 ]. |
|
2900 |
|
2901 currentClassCategory notNil ifTrue:[ |
|
2902 classes := self listOfAllClassesInCategory:currentClassCategory |
|
1394 ] ifFalse:[ |
2903 ] ifFalse:[ |
1395 sel := '' |
2904 currentClassHierarchy notNil ifTrue:[ |
1396 ] |
2905 classes := self listOfClassHierarchyOf:currentClassHierarchy |
1397 ]. |
2906 ] |
1398 ^ sel |
2907 ]. |
1399 ! |
2908 |
1400 |
2909 classListView list = classes ifFalse:[ |
1401 findClassOfVariable:aVariableName accessWith:aSelector |
2910 scroll ifTrue:[ |
1402 "this method returns the class, in which a variable |
2911 classListView contents:classes |
1403 is defined; |
2912 ] ifFalse:[ |
1404 needs either #instVarNames or #classVarNames as aSelector." |
2913 classListView setContents:classes |
1405 |
2914 ]. |
1406 |cls homeClass| |
2915 oldClassName notNil ifTrue:[ |
1407 |
2916 classListView setContents:classes. |
1408 " |
2917 classListView selectElement:oldClassName |
1409 first, find the class, where the variable is declared |
2918 ] ifFalse:[ |
1410 " |
2919 variableListView notNil ifTrue:[variableListView contents:nil] |
1411 cls := currentClass. |
2920 ] |
1412 [cls notNil] whileTrue:[ |
2921 ]. |
1413 ((cls perform:aSelector) includes:aVariableName) ifTrue:[ |
2922 scroll ifTrue:[ |
1414 homeClass := cls. |
2923 fullProtocol ifTrue:[ |
1415 cls := nil. |
2924 classListView scrollToBottom |
1416 ] ifFalse:[ |
2925 ] |
1417 cls := cls superclass |
2926 ] |
1418 ] |
2927 ] |
1419 ]. |
2928 ! |
1420 homeClass isNil ifTrue:[ |
2929 |
1421 "nope, must be one below ... (could optimize a bit, by searching down |
2930 classSelection:lineNr |
1422 for the declaring class ... |
2931 "user clicked on a class line - show method categories" |
1423 " |
2932 |
1424 homeClass := currentClass |
2933 |classSymbol cls oldSelector| |
1425 ] ifFalse:[ |
2934 |
1426 Transcript showCr:'starting search in ' , homeClass name. |
2935 (currentClassHierarchy notNil |
1427 ]. |
2936 and:[fullProtocol]) ifTrue:[ |
1428 ^ homeClass |
2937 oldSelector := currentSelector. |
1429 ! |
2938 |
1430 |
2939 self updateMethodCategoryListWithScroll:false. |
1431 listBoxTitle:title okText:okText list:aList |
2940 self updateMethodListWithScroll:false. |
1432 "convenient method: setup a listBox & return it" |
2941 self updateVariableList. |
1433 |
2942 ^ self |
1434 |box| |
2943 ]. |
1435 |
2944 |
1436 box := ListSelectionBox new. |
2945 cls := Smalltalk classNamed:classListView selectionValue withoutSpaces. |
1437 box okText:(resources string:okText). |
2946 " |
1438 box title:(resources string:title). |
2947 classSymbol := classListView selectionValue withoutSpaces asSymbol. |
1439 box list:aList. |
2948 (Smalltalk includesKey:classSymbol) ifTrue:[ |
1440 ^ box |
2949 cls := Smalltalk at:classSymbol |
1441 ! |
2950 ]. |
1442 |
2951 " |
1443 enterBoxTitle:title okText:okText |
2952 cls notNil ifTrue:[ |
1444 "convenient method: setup enterBox" |
2953 self switchToClass:cls. |
1445 |
2954 self classSelectionChanged |
1446 |box| |
2955 ] |
1447 |
|
1448 box := EnterBox new. |
|
1449 box title:(resources string:title) okText:(resources string:okText). |
|
1450 ^ box |
|
1451 ! |
|
1452 |
|
1453 askBoxTitle:title okText:okText initialText:initialText action:aBlock |
|
1454 "convenient method: setup enterBox, and open it" |
|
1455 |
|
1456 |box| |
|
1457 |
|
1458 box := EnterBox new. |
|
1459 box title:(resources string:title) okText:(resources string:okText). |
|
1460 box initialText:initialText. |
|
1461 box action:[:aString | self withWaitCursorDo:aBlock value:aString]. |
|
1462 box showAtPointer |
|
1463 ! |
|
1464 |
|
1465 enterBoxForSearchSelectorTitle:title |
|
1466 "convenient method: setup enterBox with text from codeView or selected |
|
1467 method for browsing based on a selector" |
|
1468 |
|
1469 |box| |
|
1470 |
|
1471 box := self enterBoxTitle:title okText:'search'. |
|
1472 box initialText:(self selectorToSearchFor). |
|
1473 ^ box |
|
1474 ! |
|
1475 |
|
1476 askAndBrowseSelectorTitle:title action:aBlock |
|
1477 "convenient method: setup enterBox with text from codeView or selected |
|
1478 method for browsing based on a selector. Set action and launch box" |
|
1479 |
|
1480 |box| |
|
1481 |
|
1482 box := self enterBoxTitle:title okText:'browse'. |
|
1483 box initialText:(self selectorToSearchFor). |
|
1484 box action:[:aString | self withCursor:(Cursor questionMark) do:[aBlock value:aString]]. |
|
1485 box showAtPointer |
|
1486 ! |
|
1487 |
|
1488 enterBoxForBrowseTitle:title action:aBlock |
|
1489 "convenient method: setup enterBox with text from codeView or selected |
|
1490 method for method browsing based on className/variable" |
|
1491 |
|
1492 |box| |
|
1493 |
|
1494 box := self enterBoxTitle:title okText:'browse'. |
|
1495 box initialText:(self stringToSearchFor). |
|
1496 box action:[:aString | self withWaitCursorDo:[aBlock value:aString]]. |
|
1497 box showAtPointer |
|
1498 ! |
|
1499 |
|
1500 enterBoxForCodeSelectionTitle:title okText:okText |
|
1501 "convenient method: setup enterBox with text from codeview" |
|
1502 |
|
1503 |sel box| |
|
1504 |
|
1505 box := self enterBoxTitle:(resources string:title) okText:(resources string:okText). |
|
1506 sel := codeView selection. |
|
1507 sel notNil ifTrue:[ |
|
1508 box initialText:(sel asString withoutSeparators) |
|
1509 ]. |
|
1510 ^ box |
|
1511 ! |
|
1512 |
|
1513 askAndBrowseMethodCategory:title action:aBlock |
|
1514 "convenient method: setup enterBox with initial being current method category" |
|
1515 |
|
1516 |sel box| |
|
1517 |
|
1518 box := self enterBoxTitle:title okText:'browse'. |
|
1519 sel := codeView selection. |
|
1520 sel isNil ifTrue:[ |
|
1521 currentMethodCategory notNil ifTrue:[ |
|
1522 sel := currentMethodCategory |
|
1523 ] |
|
1524 ]. |
|
1525 sel notNil ifTrue:[ |
|
1526 box initialText:(sel asString withoutSpaces) |
|
1527 ]. |
|
1528 box action:[:aString | self withWaitCursorDo:[aBlock value:aString]]. |
|
1529 box showAtPointer |
|
1530 ! |
|
1531 |
|
1532 listOfAllClassCategories |
|
1533 "return a list of all class categories" |
|
1534 |
|
1535 |newList cat| |
|
1536 |
|
1537 newList := Text with:'* all *' with:'* hierarchy *'. |
|
1538 Smalltalk allBehaviorsDo:[:aClass | |
|
1539 cat := aClass category. |
|
1540 cat isNil ifTrue:[ |
|
1541 cat := '* no category *' |
|
1542 ]. |
|
1543 newList indexOf:cat ifAbsent:[newList add:cat] |
|
1544 ]. |
|
1545 newList sort. |
|
1546 ^ newList |
|
1547 ! |
|
1548 |
|
1549 listOfClassHierarchyOf:aClass |
|
1550 "return a hierarchy class-list" |
|
1551 |
|
1552 ^ (aClass allSuperclasses reverse , |
|
1553 (Array with:aClass), |
|
1554 aClass allSubclassesInOrder) collect:[:c | c name] |
|
1555 |
|
1556 " |
|
1557 |newList theClass| |
|
1558 |
|
1559 theClass := aClass. |
|
1560 newList := Text with:theClass name. |
|
1561 [theClass ~~ Object] whileTrue:[ |
|
1562 theClass := theClass superclass. |
|
1563 newList add:theClass name |
|
1564 ]. |
|
1565 newList reverse. |
|
1566 ^ newList |
|
1567 " |
|
1568 ! |
2956 ! |
1569 |
2957 |
1570 listOfAllClassesInCategory:aCategory |
2958 listOfAllClassesInCategory:aCategory |
1571 "return a list of all classes in a given category" |
2959 "return a list of all classes in a given category" |
1572 |
2960 |
1607 ]. |
2995 ]. |
1608 (newList size == 0) ifTrue:[^ nil]. |
2996 (newList size == 0) ifTrue:[^ nil]. |
1609 ^ newList sort |
2997 ^ newList sort |
1610 ! |
2998 ! |
1611 |
2999 |
1612 classHierarchyDo:aBlock |
3000 doClassMenu:aBlock |
1613 "eavluate the 2-arg block for every class, |
3001 "a helper - check if class is selected and evaluate aBlock |
1614 starting at Object; passing class and nesting level to the block." |
3002 while showing waitCursor" |
1615 |
3003 |
1616 |classes s classDict l| |
3004 self checkClassSelected ifTrue:[ |
1617 |
3005 self withWaitCursorDo:aBlock |
1618 classes := Smalltalk allClasses. |
3006 ] |
1619 classDict := IdentityDictionary new:classes size. |
3007 ! |
1620 classes do:[:aClass | |
3008 |
1621 s := aClass superclass. |
3009 checkClassSelected |
1622 s notNil ifTrue:[ |
3010 "warn and return false, if no class is selected" |
1623 l := classDict at:s ifAbsent:[nil]. |
3011 |
1624 l isNil ifTrue:[ |
3012 currentClass isNil ifTrue:[ |
1625 l := OrderedCollection new:5. |
3013 self warn:'select a class first'. |
1626 classDict at:s put:l |
3014 ^ false |
1627 ]. |
3015 ]. |
1628 l add:aClass |
3016 ^ true |
1629 ] |
3017 ! |
1630 ]. |
3018 |
1631 self classHierarchyOf:Object level:0 do:aBlock using:classDict |
3019 updateClassList |
1632 ! |
3020 self updateClassListWithScroll:true |
1633 |
3021 ! |
1634 classHierarchyOf:aClass level:level do:aBlock using:aDictionary |
3022 |
1635 "evaluate the 2-arg block for every subclass of aClass, |
3023 listOfClassHierarchyOf:aClass |
1636 passing class and nesting level to the block." |
3024 "return a hierarchy class-list" |
1637 |
3025 |
1638 |names subclasses| |
3026 |classes| |
1639 |
3027 |
1640 aBlock value:aClass value:level. |
3028 classes := aClass allSuperclasses reverse , (Array with:aClass). |
1641 subclasses := aDictionary at:aClass ifAbsent:[nil]. |
3029 fullProtocol ifFalse:[ |
1642 (subclasses size == 0) ifFalse:[ |
3030 classes := classes , aClass allSubclassesInOrder |
1643 names := subclasses collect:[:class | class name]. |
3031 ]. |
1644 names sortWith:subclasses. |
3032 ^ classes collect:[:c | c name] |
1645 subclasses do:[:aSubClass | |
3033 |
1646 self classHierarchyOf:aSubClass level:(level + 1) do:aBlock using:aDictionary |
|
1647 ] |
|
1648 ] |
|
1649 ! |
|
1650 |
|
1651 listOfAllMethodCategoriesInClass:aClass |
|
1652 "answer a list of all method categories of the argument, aClass" |
|
1653 |
|
1654 |newList cat| |
|
1655 |
|
1656 newList := Text new. |
|
1657 aClass methodArray do:[:aMethod | |
|
1658 cat := aMethod category. |
|
1659 cat isNil ifTrue:[ |
|
1660 cat := '* no category *' |
|
1661 ]. |
|
1662 (newList includes:cat) ifFalse:[newList add:cat] |
|
1663 ]. |
|
1664 (newList size == 0) ifTrue:[^ nil]. |
|
1665 newList add:'* all *'. |
|
1666 ^ newList sort |
|
1667 ! |
|
1668 |
|
1669 listOfAllSelectorsInCategory:aCategory ofClass:aClass |
|
1670 "answer a list of all selectors in a given method category |
|
1671 of the argument, aClass" |
|
1672 |
|
1673 |newList searchCategory selector| |
|
1674 |
|
1675 (aCategory = '* all *') ifTrue:[ |
|
1676 newList := aClass selectorArray asText |
|
1677 ] ifFalse:[ |
|
1678 (aCategory = '* no category *') ifTrue:[ |
|
1679 searchCategory := nil |
|
1680 ] ifFalse:[ |
|
1681 searchCategory := aCategory |
|
1682 ]. |
|
1683 newList := Text new. |
|
1684 aClass methodArray do:[:aMethod | |
|
1685 (aMethod category = searchCategory) ifTrue:[ |
|
1686 selector := aClass selectorForMethod:aMethod. |
|
1687 selector notNil ifTrue:[ |
|
1688 aMethod isWrapped ifTrue:[ |
|
1689 selector := selector , ' !!' |
|
1690 ]. |
|
1691 (newList includes:selector) ifFalse:[ |
|
1692 newList add:selector |
|
1693 ] |
|
1694 ] |
|
1695 ] |
|
1696 ] |
|
1697 ]. |
|
1698 (newList size == 0) ifTrue:[^ nil]. |
|
1699 ^ newList sort |
|
1700 ! |
3034 ! |
1701 |
3035 |
1702 templateFor:className in:cat |
3036 templateFor:className in:cat |
1703 "return a class definition template - be smart in what is offered initially" |
3037 "return a class definition template - be smart in what is offered initially" |
1704 |
3038 |
1715 instanceVariableNames: '''' |
3049 instanceVariableNames: '''' |
1716 classVariableNames: '''' |
3050 classVariableNames: '''' |
1717 poolDictionaries: '''' |
3051 poolDictionaries: '''' |
1718 category: '''. |
3052 category: '''. |
1719 |
3053 |
1720 cat notNil ifTrue:[ |
3054 cat notNil ifTrue:[ |
1721 aString := aString , cat |
3055 aString := aString , cat |
1722 ]. |
3056 ]. |
1723 aString := aString , ''''. |
3057 aString := aString , ''' |
1724 ^ aString |
3058 |
1725 ! |
3059 |
1726 |
3060 |
1727 template |
3061 |
1728 "return a method definition template" |
3062 |
1729 |
3063 " |
1730 ^ |
3064 Replace ''' , className , ''', ''', name , ''' and |
1731 'message selector and argument names |
3065 the empty string arguments by true values. |
1732 "comment stating purpose of message" |
3066 |
1733 |
3067 Install (or change) the class by ''accepting'', |
1734 |
3068 either via the menu or the keyboard (usually CMD-A). |
1735 |temporaries| |
3069 |
1736 statements |
3070 To be nice to others (and yourself later), do not forget to |
1737 ' |
3071 add some documentation; either under the classes documentation |
1738 ! |
3072 protocol, or as a class comment. |
1739 |
3073 " |
1740 compileCode:someCode |
3074 '. |
1741 (ReadStream on:someCode) fileIn |
3075 ^ aString |
3076 ! |
|
3077 |
|
3078 classClassDefinitionTemplateFor:name in:cat |
|
3079 "common helper for newClass and newSubclass |
|
3080 - show a template to define class name in category cat. |
|
3081 Also, set acceptaction to install the class." |
|
3082 |
|
3083 currentMethodCategory := nil. |
|
3084 currentMethod := currentSelector := nil. |
|
3085 |
|
3086 classListView deselect. |
|
3087 |
|
3088 fullClass ifFalse:[ |
|
3089 methodCategoryListView contents:nil. |
|
3090 methodListView contents:nil |
|
3091 ]. |
|
3092 |
|
3093 codeView contents:(self templateFor:name in:cat). |
|
3094 codeView modified:false. |
|
3095 |
|
3096 codeView acceptAction:[:theCode | |
|
3097 codeView cursor:Cursor execute. |
|
3098 Object abortSignal catch:[ |
|
3099 |cls| |
|
3100 |
|
3101 cls := (Compiler evaluate:theCode asString notifying:codeView). |
|
3102 cls isBehavior ifTrue:[ |
|
3103 codeView modified:false. |
|
3104 self classCategoryUpdate. |
|
3105 self updateClassListWithScroll:false. |
|
3106 self switchToClassNamed:(cls name). |
|
3107 ] |
|
3108 ]. |
|
3109 codeView cursor:(Cursor normal). |
|
3110 ]. |
|
3111 codeView explainAction:nil. |
|
3112 self switchToClass:nil |
|
3113 ! |
|
3114 |
|
3115 renameCurrentClassTo:aString |
|
3116 "helper - do the rename" |
|
3117 |
|
3118 self doClassMenu:[ |
|
3119 |oldName oldSym newSym| |
|
3120 |
|
3121 oldName := currentClass name. |
|
3122 oldSym := oldName asSymbol. |
|
3123 " |
|
3124 currentClass setName:aString. |
|
3125 newSym := aString asSymbol. |
|
3126 Smalltalk at:oldSym put:nil. |
|
3127 Smalltalk removeKey:oldSym. |
|
3128 Smalltalk at:newSym put:currentClass. |
|
3129 " |
|
3130 " |
|
3131 currentClass renameTo:aString. |
|
3132 " |
|
3133 Smalltalk renameClass:currentClass to:aString. |
|
3134 |
|
3135 self updateClassList. |
|
3136 self updateMethodCategoryListWithScroll:false. |
|
3137 self updateMethodListWithScroll:false. |
|
3138 self withWaitCursorDo:[ |
|
3139 Transcript showCr:('searching for users of ' , oldSym); endEntry. |
|
3140 self class browseReferendsOf:oldSym warnIfNone:false |
|
3141 ] |
|
3142 ] |
|
3143 ! |
|
3144 |
|
3145 switchToClassNamed:aString |
|
3146 |classSymbol theClass newCat| |
|
3147 |
|
3148 aString knownAsSymbol ifFalse:[^ self]. |
|
3149 |
|
3150 classSymbol := aString asSymbol. |
|
3151 theClass := Smalltalk at:classSymbol. |
|
3152 theClass isBehavior ifTrue:[ |
|
3153 classCategoryListView notNil ifTrue:[ |
|
3154 currentClassHierarchy isNil ifTrue:[ |
|
3155 ((newCat := theClass category) ~= currentClassCategory) ifTrue:[ |
|
3156 currentClassCategory := newCat. |
|
3157 newCat isNil ifTrue:[ |
|
3158 classCategoryListView selectElement:'* no category *' |
|
3159 ] ifFalse:[ |
|
3160 classCategoryListView selectElement:newCat. |
|
3161 ]. |
|
3162 "/ classCategoryListView makeSelectionVisible. |
|
3163 ] |
|
3164 ] |
|
3165 ]. |
|
3166 self updateClassList. |
|
3167 self switchToClass:theClass. |
|
3168 classListView selectElement:aString. |
|
3169 self classSelectionChanged |
|
3170 ] |
|
3171 ! |
|
3172 |
|
3173 switchToClassNameMatching:aMatchString |
|
3174 |classNames thisName box| |
|
3175 |
|
3176 classNames := OrderedCollection new. |
|
3177 Smalltalk allBehaviorsDo:[:aClass | |
|
3178 thisName := aClass name. |
|
3179 (aMatchString match:thisName) ifTrue:[ |
|
3180 classNames add:thisName |
|
3181 ] |
|
3182 ]. |
|
3183 (classNames size == 0) ifTrue:[^ nil]. |
|
3184 (classNames size == 1) ifTrue:[ |
|
3185 ^ self switchToClassNamed:(classNames at:1) |
|
3186 ]. |
|
3187 |
|
3188 box := self listBoxTitle:'select class to switch to:' |
|
3189 okText:'ok' |
|
3190 list:classNames sort. |
|
3191 box action:[:aString | self switchToClassNamed:aString]. |
|
3192 box showAtPointer |
|
1742 ! ! |
3193 ! ! |
1743 |
3194 |
1744 !SystemBrowser methodsFor:'user interaction'! |
3195 !SystemBrowser methodsFor:'variable stuff'! |
1745 |
3196 |
1746 instanceProtocol |
3197 updateVariableList |
1747 showInstance ifFalse:[ |
3198 |l subList flags last nameAccessSelector class oldSelection| |
1748 self checkSelectionChangeAllowed ifTrue:[ |
3199 |
1749 classToggle turnOff. |
3200 variableListView isNil ifTrue:[^ self]. |
1750 instanceToggle turnOn. |
3201 |
1751 showInstance := true. |
3202 oldSelection := variableListView selectionValue. |
1752 currentClass notNil ifTrue:[ |
3203 |
1753 self classSelectionChanged |
3204 l := OrderedCollection new. |
3205 " |
|
3206 show classVars, if classProtocol is shown (instead of classInstance vars) |
|
3207 " |
|
3208 showInstance ifTrue:[ |
|
3209 nameAccessSelector := #instVarNames |
|
3210 ] ifFalse:[ |
|
3211 nameAccessSelector := #classVarNames |
|
3212 ]. |
|
3213 |
|
3214 class := currentClass notNil ifTrue:[currentClass] ifFalse:[actualClass]. |
|
3215 class isNil ifTrue:[class := currentClassHierarchy]. |
|
3216 class withAllSuperclasses do:[:aClass | |
|
3217 |ignore| |
|
3218 |
|
3219 ignore := fullProtocol |
|
3220 and:[classListView valueIsInSelection:(aClass name asString)]. |
|
3221 ignore ifFalse:[ |
|
3222 subList := aClass perform:nameAccessSelector. |
|
3223 subList size ~~ 0 ifTrue:[ |
|
3224 l := l , (subList asOrderedCollection reverse). |
|
3225 l := l , (OrderedCollection with:'---- ' , aClass name , ' ---------'). |
|
3226 ] |
|
3227 ] |
|
3228 ]. |
|
3229 l reverse. |
|
3230 variableListView setAttributes:nil. |
|
3231 variableListView list:l. |
|
3232 l keysAndValuesDo:[:index :entry | |
|
3233 (entry startsWith:'---') ifTrue:[ |
|
3234 variableListView attributeAt:index put:#disabled. |
|
3235 last := index |
|
3236 ] |
|
3237 ]. |
|
3238 last notNil ifTrue:[variableListView scrollToLine:last]. |
|
3239 |
|
3240 oldSelection notNil ifTrue:[ |
|
3241 variableListView selectElement:oldSelection |
|
3242 ] |
|
3243 ! |
|
3244 |
|
3245 unhilightMethods |
|
3246 "unhighlight items in method list" |
|
3247 |
|
3248 variableListView isNil ifTrue:[^ self]. |
|
3249 |
|
3250 methodListView notNil ifTrue:[ |
|
3251 1 to:methodListView list size do:[:entry | |
|
3252 methodListView attributeAt:entry put:nil. |
|
3253 ]. |
|
3254 ]. |
|
3255 |
|
3256 |
|
3257 ! |
|
3258 |
|
3259 hilightMethodsInMethodCategoryList:inCat inMethodList:inMethods |
|
3260 "search for methods which access the selected |
|
3261 variable, and highlight them" |
|
3262 |
|
3263 |name idx redefinedSelectors| |
|
3264 |
|
3265 variableListView isNil ifTrue:[^ self]. |
|
3266 |
|
3267 inCat ifTrue:[self unhilightMethodCategories]. |
|
3268 inMethods ifTrue:[self unhilightMethods]. |
|
3269 |
|
3270 actualClass isNil ifTrue:[^ self]. |
|
3271 (methodCategoryListView isNil |
|
3272 and:[methodListView isNil]) ifTrue:[^ self]. |
|
3273 |
|
3274 name := variableListView selectionValue. |
|
3275 name isNil ifTrue:[^ self]. |
|
3276 |
|
3277 self withCursor:(Cursor questionMark) do:[ |
|
3278 |classes filter any| |
|
3279 |
|
3280 classes := Array with:currentClass. |
|
3281 currentClassHierarchy notNil ifTrue:[ |
|
3282 fullProtocol ifTrue:[ |
|
1754 ]. |
3283 ]. |
1755 codeView modified:false. |
3284 classes := classes , currentClass allSuperclasses. |
3285 redefinedSelectors := IdentitySet new. |
|
3286 ]. |
|
3287 showInstance ifTrue:[ |
|
3288 filter := self class filterToSearchInstRefsTo:name modificationsOnly:false |
|
1756 ] ifFalse:[ |
3289 ] ifFalse:[ |
1757 instanceToggle turnOff. |
3290 filter := self class filterToSearchClassRefsTo:name modificationsOnly:false |
1758 classToggle turnOn |
3291 ]. |
1759 ] |
3292 |
1760 ] |
3293 any := false. |
1761 ! |
3294 " |
1762 |
3295 highlight the method that ref this variable |
1763 classProtocol |
3296 " |
1764 showInstance ifTrue:[ |
3297 classes do:[:someClass | |
1765 self checkSelectionChangeAllowed ifTrue:[ |
3298 someClass methodArray with:someClass selectorArray |
1766 instanceToggle turnOff. |
3299 do:[:method :selector | |
1767 classToggle turnOn. |
3300 |
1768 showInstance := false. |
3301 (inCat |
1769 currentClass notNil ifTrue:[ |
3302 or:[methodListView list notNil |
1770 self classSelectionChanged |
3303 and:[methodListView list includes:selector]]) |
3304 ifTrue:[ |
|
3305 (redefinedSelectors isNil |
|
3306 or:[(redefinedSelectors includes:selector) not]) |
|
3307 ifTrue:[ |
|
3308 (filter value:someClass value:method value:selector) ifTrue:[ |
|
3309 |idx cat| |
|
3310 |
|
3311 (inCat |
|
3312 and:[methodCategoryListView notNil |
|
3313 and:[methodCategoryListView list notNil]]) ifTrue:[ |
|
3314 cat := method category. |
|
3315 " |
|
3316 highlight the methodCategory |
|
3317 " |
|
3318 idx := methodCategoryListView list indexOf:cat. |
|
3319 idx ~~ 0 ifTrue:[ |
|
3320 methodCategoryListView attributeAt:idx put:#bold. |
|
3321 ]. |
|
3322 ]. |
|
3323 |
|
3324 (inMethods |
|
3325 and:[methodListView notNil |
|
3326 and:[methodListView list notNil]]) ifTrue:[ |
|
3327 " |
|
3328 highlight the method |
|
3329 " |
|
3330 idx := methodListView list indexOf:selector. |
|
3331 idx ~~ 0 ifTrue:[ |
|
3332 methodListView attributeAt:idx put:#bold. |
|
3333 ]. |
|
3334 any := true |
|
3335 ]. |
|
3336 ]. |
|
3337 redefinedSelectors notNil ifTrue:[ |
|
3338 redefinedSelectors add:selector |
|
3339 ] |
|
3340 ] |
|
3341 ] |
|
3342 ] |
|
3343 ]. |
|
3344 any ifTrue:[ |
|
3345 self setSearchPattern:name |
|
3346 ] |
|
3347 ] |
|
3348 |
|
3349 |
|
3350 ! |
|
3351 |
|
3352 hilightMethodsInMethodCategoryList |
|
3353 "search for methods which access the selected |
|
3354 variable, and highlight them" |
|
3355 |
|
3356 self hilightMethodsInMethodCategoryList:true inMethodList:false |
|
3357 |
|
3358 |
|
3359 |
|
3360 ! |
|
3361 |
|
3362 unhilightMethodCategories |
|
3363 "unhighlight items in method list" |
|
3364 |
|
3365 variableListView isNil ifTrue:[^ self]. |
|
3366 |
|
3367 methodCategoryListView notNil ifTrue:[ |
|
3368 1 to:methodCategoryListView list size do:[:entry | |
|
3369 methodCategoryListView attributeAt:entry put:nil. |
|
3370 ] |
|
3371 ]. |
|
3372 |
|
3373 |
|
3374 ! |
|
3375 |
|
3376 hilightMethodsInMethodList |
|
3377 "search for methods which access the selected |
|
3378 variable, and highlight them" |
|
3379 |
|
3380 self hilightMethodsInMethodCategoryList:false inMethodList:true |
|
3381 |
|
3382 |
|
3383 |
|
3384 ! ! |
|
3385 |
|
3386 !SystemBrowser methodsFor:'class list menu'! |
|
3387 |
|
3388 classDefinition |
|
3389 "show class definition in codeView and setup accept-action for |
|
3390 a class-definition change. |
|
3391 Extract documentation either from a documentation method or |
|
3392 from the comment - not a biggy, but beginners will like |
|
3393 it when exploring the system." |
|
3394 |
|
3395 self doClassMenu:[ |
|
3396 |m s aStream isComment| |
|
3397 |
|
3398 aStream := WriteStream on:(String new:200). |
|
3399 currentClass fileOutDefinitionOn:aStream. |
|
3400 |
|
3401 currentClass isLoaded ifTrue:[ |
|
3402 " |
|
3403 add documentation as a comment, if there is any |
|
3404 " |
|
3405 m := currentClass class compiledMethodAt:#documentation. |
|
3406 m notNil ifTrue:[ |
|
3407 s := m comment. |
|
3408 isComment := false. |
|
3409 ] ifFalse:[ |
|
3410 "try comment" |
|
3411 s := currentClass comment. |
|
3412 s notNil ifTrue:[ |
|
3413 isComment := true |
|
3414 ] |
|
1771 ]. |
3415 ]. |
1772 codeView modified:false. |
3416 ]. |
3417 s notNil ifTrue:[ |
|
3418 aStream cr. |
|
3419 aStream cr. |
|
3420 aStream cr. |
|
3421 aStream cr. |
|
3422 aStream cr. |
|
3423 aStream nextPut:$" ; cr; nextPutAll:' Documentation:'; cr. |
|
3424 aStream cr. |
|
3425 aStream nextPutAll:s. |
|
3426 aStream cr; cr. |
|
3427 aStream nextPutAll:' Notice: '; cr. |
|
3428 aStream nextPutAll:' the above string has been extracted from the classes '. |
|
3429 aStream nextPutAll:(isComment ifTrue:['comment.'] ifFalse:['documentation method.']). |
|
3430 aStream cr. |
|
3431 aStream nextPutAll:' It will not preserved when accepting a new class definition.'; cr. |
|
3432 aStream nextPut:$". |
|
3433 ]. |
|
3434 |
|
3435 codeView contents:(aStream contents). |
|
3436 codeView modified:false. |
|
3437 codeView acceptAction:[:theCode | |
|
3438 codeView cursor:Cursor execute. |
|
3439 Object abortSignal catch:[ |
|
3440 (Compiler evaluate:theCode asString notifying:codeView) |
|
3441 isBehavior ifTrue:[ |
|
3442 codeView modified:false. |
|
3443 self classCategoryUpdate. |
|
3444 self updateClassListWithScroll:false. |
|
3445 ] |
|
3446 ]. |
|
3447 codeView cursor:Cursor normal. |
|
3448 ]. |
|
3449 codeView explainAction:nil. |
|
3450 |
|
3451 methodListView notNil ifTrue:[ |
|
3452 methodListView deselect |
|
3453 ]. |
|
3454 aspect := #definition. |
|
3455 self normalLabel |
|
3456 ] |
|
3457 ! |
|
3458 |
|
3459 initializeClassMenu |
|
3460 |labels menu| |
|
3461 |
|
3462 labels := resources array:#( |
|
3463 'fileOut' |
|
3464 'printOut' |
|
3465 'printOut protocol' |
|
3466 " 'printOut full protocol' " |
|
3467 '-' |
|
3468 'SPAWN_CLASS' |
|
3469 'spawn full protocol' |
|
3470 'spawn hierarchy' |
|
3471 'spawn subclasses' |
|
3472 '-' |
|
3473 'hierarchy' |
|
3474 'definition' |
|
3475 'comment' |
|
3476 'class instvars' |
|
3477 " 'protocols' " |
|
3478 '-' |
|
3479 "/ 'variable search' |
|
3480 'class refs' |
|
3481 '-' |
|
3482 'new class' |
|
3483 'new subclass' |
|
3484 'rename ...' |
|
3485 'remove'). |
|
3486 |
|
3487 menu := PopUpMenu labels:labels |
|
3488 selectors:#(classFileOut |
|
3489 classPrintOut |
|
3490 classPrintOutProtocol |
|
3491 " classPrintOutFullProtocol " |
|
3492 nil |
|
3493 classSpawn |
|
3494 classSpawnFullProtocol |
|
3495 classSpawnHierarchy |
|
3496 classSpawnSubclasses |
|
3497 nil |
|
3498 classHierarchy |
|
3499 classDefinition |
|
3500 classComment |
|
3501 classClassInstVars |
|
3502 " classProtocols " |
|
3503 nil |
|
3504 "/ variables |
|
3505 classRefs |
|
3506 nil |
|
3507 classNewClass |
|
3508 classNewSubclass |
|
3509 classRename |
|
3510 classRemove) |
|
3511 receiver:self |
|
3512 for:classListView. |
|
3513 |
|
3514 fullProtocol ifFalse:[ |
|
3515 classListView middleButtonMenu:menu. |
|
3516 ]. |
|
3517 |
|
3518 self initializeVariableListMenu. |
|
3519 |
|
3520 ! |
|
3521 |
|
3522 classFileOut |
|
3523 "fileOut the current class. |
|
3524 Catch errors (sure, you like to know if it failed) and |
|
3525 warn if any)" |
|
3526 |
|
3527 self doClassMenu:[ |
|
3528 self busyLabel:'saving %1' with:currentClass name. |
|
3529 Class fileOutErrorSignal handle:[:ex | |
|
3530 self warn:'cannot create: %1' with:ex parameter. |
|
3531 ex return. |
|
3532 ] do:[ |
|
3533 currentClass fileOut. |
|
3534 ]. |
|
3535 self normalLabel. |
|
3536 ] |
|
3537 ! |
|
3538 |
|
3539 doClassMenuWithSelection:aBlock |
|
3540 "a helper - if there is a selection, which represents a classes name, |
|
3541 evaluate aBlock, passing that class and optional selector as arguments. |
|
3542 Otherwise, check if a class is selected and evaluate aBlock with the |
|
3543 current class." |
|
3544 |
|
3545 |string words clsName cls sel isMeta w| |
|
3546 |
|
3547 string := codeView selection. |
|
3548 string notNil ifTrue:[ |
|
3549 self extractClassAndSelectorFromSelectionInto:[:c :s :m | |
|
3550 clsName := c. |
|
3551 sel := s. |
|
3552 isMeta := m. |
|
3553 ]. |
|
3554 clsName isNil ifTrue:[ |
|
3555 string := string asString withoutSeparators. |
|
3556 words := string asCollectionOfWords. |
|
3557 words notNil ifTrue:[ |
|
3558 clsName := words first. |
|
3559 (clsName endsWith:'class') ifTrue:[ |
|
3560 isMeta := true. |
|
3561 clsName := clsName copyTo:(clsName size - 5) |
|
3562 ] ifFalse:[ |
|
3563 isMeta := false |
|
3564 ]. |
|
3565 sel := Parser selectorInExpression:string. |
|
3566 ] |
|
3567 ]. |
|
3568 clsName notNil ifTrue:[ |
|
3569 (cls := Smalltalk classNamed:clsName) notNil ifTrue:[ |
|
3570 isMeta ifTrue:[ |
|
3571 cls := cls class |
|
3572 ]. |
|
3573 self withWaitCursorDo:[ |
|
3574 aBlock value:cls value:sel. |
|
3575 ]. |
|
3576 ^ self |
|
3577 ] ifFalse:[ |
|
3578 self warn:'no class named: %1 - spawning current' with:clsName |
|
3579 ] |
|
3580 ]. |
|
3581 ]. |
|
3582 |
|
3583 classMethodListView notNil ifTrue:[ |
|
3584 sel := classMethodListView selectionValue. |
|
3585 sel notNil ifTrue:[ |
|
3586 sel := self selectorFromClassMethodString:sel |
|
3587 ] |
|
3588 ]. |
|
3589 self doClassMenu:[aBlock value:currentClass value:sel] |
|
3590 ! |
|
3591 |
|
3592 classSpawn |
|
3593 "create a new SystemBrowser browsing current class, |
|
3594 or if there is a selection, spawn a browser on the selected class |
|
3595 even a class/selector pair can be specified." |
|
3596 |
|
3597 |browser| |
|
3598 |
|
3599 self doClassMenuWithSelection:[:cls :sel | |
|
3600 cls isMeta ifTrue:[ |
|
3601 Smalltalk allBehaviorsDo:[:aClass | |
|
3602 aClass class == cls ifTrue:[ |
|
3603 browser := self class browseClass:aClass. |
|
3604 browser classProtocol. |
|
3605 sel notNil ifTrue:[ |
|
3606 browser switchToMethodNamed:sel |
|
3607 ]. |
|
3608 ^ self |
|
3609 ]. |
|
3610 ]. |
|
3611 self warn:'oops, no class for this metaclass'. |
|
3612 ^ self |
|
3613 ]. |
|
3614 browser := self class browseClass:cls. |
|
3615 cls hasMethods ifFalse:[ |
|
3616 browser classProtocol. |
|
3617 ]. |
|
3618 sel notNil ifTrue:[ |
|
3619 browser switchToMethodNamed:sel |
|
3620 ]. |
|
3621 ] |
|
3622 |
|
3623 " |
|
3624 select 'Smalltalk allClassesDo:' and use spawn from the class menu |
|
3625 select 'Smalltalk' and use spawn from the class menu |
|
3626 " |
|
3627 ! |
|
3628 |
|
3629 classSpawnHierarchy |
|
3630 "create a new HierarchyBrowser browsing current class" |
|
3631 |
|
3632 self doClassMenuWithSelection:[:cls :sel | |
|
3633 self class browseClassHierarchy:cls |
|
3634 ] |
|
3635 ! |
|
3636 |
|
3637 classSpawnSubclasses |
|
3638 "create a new browser browsing current class's subclasses" |
|
3639 |
|
3640 |subs| |
|
3641 |
|
3642 self doClassMenuWithSelection:[:cls :sel | |
|
3643 subs := cls allSubclasses. |
|
3644 (subs notNil and:[subs size ~~ 0]) ifTrue:[ |
|
3645 self class browseClasses:subs title:('subclasses of ' , cls name) |
|
3646 ] |
|
3647 ] |
|
3648 ! |
|
3649 |
|
3650 classPrintOutFullProtocol |
|
3651 |printStream| |
|
3652 |
|
3653 self doClassMenu:[ |
|
3654 printStream := Printer new. |
|
3655 currentClass printOutFullProtocolOn:printStream. |
|
3656 printStream close |
|
3657 ] |
|
3658 ! |
|
3659 |
|
3660 classPrintOutProtocol |
|
3661 |printStream| |
|
3662 |
|
3663 self doClassMenu:[ |
|
3664 printStream := Printer new. |
|
3665 currentClass printOutProtocolOn:printStream. |
|
3666 printStream close |
|
3667 ] |
|
3668 ! |
|
3669 |
|
3670 classPrintOut |
|
3671 |printStream| |
|
3672 |
|
3673 self doClassMenu:[ |
|
3674 printStream := Printer new. |
|
3675 currentClass printOutOn:printStream. |
|
3676 printStream close |
|
3677 ] |
|
3678 ! |
|
3679 |
|
3680 classHierarchy |
|
3681 "show current classes hierarchy in codeView" |
|
3682 |
|
3683 |aStream| |
|
3684 |
|
3685 self doClassMenu:[ |
|
3686 aStream := WriteStream on:(String new:200). |
|
3687 actualClass printHierarchyOn:aStream. |
|
3688 codeView contents:(aStream contents). |
|
3689 codeView modified:false. |
|
3690 codeView acceptAction:nil. |
|
3691 codeView explainAction:nil. |
|
3692 methodListView notNil ifTrue:[ |
|
3693 methodListView deselect |
|
3694 ]. |
|
3695 aspect := #hierarchy. |
|
3696 self normalLabel |
|
3697 ] |
|
3698 ! |
|
3699 |
|
3700 classNewClass |
|
3701 "create a class-definition prototype in codeview" |
|
3702 |
|
3703 |nm| |
|
3704 |
|
3705 currentClass notNil ifTrue:[ |
|
3706 nm := currentClass superclass name |
|
3707 ] ifFalse:[ |
|
3708 nm := 'Object' |
|
3709 ]. |
|
3710 self classClassDefinitionTemplateFor:nm in:currentClassCategory. |
|
3711 aspect := nil. |
|
3712 ! |
|
3713 |
|
3714 classClassInstVars |
|
3715 "show class instance variables in codeView and setup accept-action |
|
3716 for a class-instvar-definition change" |
|
3717 |
|
3718 |s| |
|
3719 |
|
3720 self doClassMenu:[ |
|
3721 s := WriteStream on:(String new). |
|
3722 currentClass fileOutClassInstVarDefinitionOn:s. |
|
3723 codeView contents:(s contents). |
|
3724 codeView modified:false. |
|
3725 codeView acceptAction:[:theCode | |
|
3726 codeView cursor:Cursor execute. |
|
3727 Object abortSignal catch:[ |
|
3728 Compiler evaluate:theCode asString notifying:codeView. |
|
3729 codeView modified:false. |
|
3730 self updateClassList. |
|
3731 ]. |
|
3732 codeView cursor:Cursor normal. |
|
3733 ]. |
|
3734 codeView explainAction:nil. |
|
3735 methodListView notNil ifTrue:[ |
|
3736 methodListView deselect |
|
3737 ]. |
|
3738 aspect := #classInstVars. |
|
3739 self normalLabel |
|
3740 ] |
|
3741 ! |
|
3742 |
|
3743 classSpawnFullProtocol |
|
3744 "create a new browser, browsing current classes full protocol" |
|
3745 |
|
3746 self doClassMenuWithSelection:[:cls :sel | |
|
3747 self class browseFullClassProtocol:cls |
|
3748 ] |
|
3749 ! |
|
3750 |
|
3751 classProtocols |
|
3752 ^ self |
|
3753 ! |
|
3754 |
|
3755 classRemove |
|
3756 "user requested remove of current class and all subclasses - |
|
3757 count subclasses and let user confirm removal." |
|
3758 |
|
3759 |count t box| |
|
3760 |
|
3761 currentClass notNil ifTrue:[ |
|
3762 count := currentClass allSubclasses size. |
|
3763 t := 'remove ' , currentClass name. |
|
3764 count ~~ 0 ifTrue:[ |
|
3765 t := t , '\(with ' , count printString , ' subclass'. |
|
3766 count ~~ 1 ifTrue:[ |
|
3767 t := t , 'es' |
|
3768 ]. |
|
3769 t := (t , ')') withCRs |
|
3770 ]. |
|
3771 box := YesNoBox |
|
3772 title:t |
|
3773 yesText:(resources at:'remove') |
|
3774 noText:(resources at:'abort'). |
|
3775 box confirm ifTrue:[ |
|
3776 "after querying user - do really remove current class |
|
3777 and all subclasses |
|
3778 " |
|
3779 self doClassMenu:[ |
|
3780 " |
|
3781 query ? |
|
3782 " |
|
3783 currentClass allSubclassesDo:[:aSubClass | |
|
3784 (CheckForInstancesWhenRemovingClasses not |
|
3785 or:[aSubClass hasInstances not |
|
3786 or:[self confirm:(aSubClass name , ' has instances - remove anyway ?')]]) |
|
3787 ifTrue:[ |
|
3788 Smalltalk removeClass:aSubClass |
|
3789 ] |
|
3790 ]. |
|
3791 (CheckForInstancesWhenRemovingClasses not |
|
3792 or:[currentClass hasInstances not |
|
3793 or:[self confirm:(currentClass name , ' has instances - remove anyway ?')]]) |
|
3794 ifTrue:[ |
|
3795 Smalltalk removeClass:currentClass. |
|
3796 ]. |
|
3797 |
|
3798 self switchToClass:nil. |
|
3799 Smalltalk changed. |
|
3800 self updateClassList. |
|
3801 |
|
3802 "if it was the last in its category, update class category list" |
|
3803 " |
|
3804 classListView numberOfLines == 0 ifTrue:[ |
|
3805 self updateClassCategoryListWithScroll:false |
|
3806 ]. |
|
3807 " |
|
3808 methodCategoryListView notNil ifTrue:[methodCategoryListView contents:nil]. |
|
3809 methodListView notNil ifTrue:[methodListView contents:nil]. |
|
3810 codeView contents:nil. |
|
3811 codeView modified:false |
|
3812 ] |
|
3813 ] |
|
3814 ] |
|
3815 ! |
|
3816 |
|
3817 classComment |
|
3818 "show the classes comment in the codeView. |
|
3819 Also, set acceptaction to change the comment." |
|
3820 |
|
3821 self doClassMenu:[ |
|
3822 codeView contents:(currentClass comment). |
|
3823 codeView modified:false. |
|
3824 codeView acceptAction:[:theCode | |
|
3825 Object abortSignal catch:[ |
|
3826 lockUpdates := true. |
|
3827 currentClass comment:theCode asString. |
|
3828 codeView modified:false. |
|
3829 ]. |
|
3830 lockUpdates := false. |
|
3831 ]. |
|
3832 codeView explainAction:nil. |
|
3833 |
|
3834 methodListView notNil ifTrue:[ |
|
3835 methodListView deselect |
|
3836 ]. |
|
3837 aspect := #comment. |
|
3838 self normalLabel |
|
3839 ] |
|
3840 ! |
|
3841 |
|
3842 classRefs |
|
3843 self doClassMenu:[ |
|
3844 self withCursor:(Cursor questionMark) do:[ |
|
3845 self class browseReferendsOf:currentClass name asSymbol |
|
3846 ] |
|
3847 ] |
|
3848 ! |
|
3849 |
|
3850 classNewSubclass |
|
3851 "create a subclass-definition prototype in codeview" |
|
3852 |
|
3853 self doClassMenu:[ |
|
3854 self classClassDefinitionTemplateFor:(currentClass name) |
|
3855 in:(currentClass category). |
|
3856 aspect := nil |
|
3857 ] |
|
3858 ! |
|
3859 |
|
3860 classUses |
|
3861 "a powerful tool, when trying to learn more about where |
|
3862 a class is used. This one searches all uses of a class, |
|
3863 and shows a list of uses - try it and like it" |
|
3864 |
|
3865 self doClassMenu:[ |
|
3866 self withCursor:(Cursor questionMark) do:[ |
|
3867 self class browseUsesOf:currentClass |
|
3868 ] |
|
3869 ] |
|
3870 ! |
|
3871 |
|
3872 classRename |
|
3873 "launch an enterBox for new name and query user" |
|
3874 |
|
3875 |box| |
|
3876 |
|
3877 self checkClassSelected ifFalse:[^ self]. |
|
3878 box := self enterBoxTitle:(resources string:'rename %1 to:' with:currentClass name) okText:'rename'. |
|
3879 box initialText:(currentClass name). |
|
3880 box action:[:aString | self renameCurrentClassTo:aString]. |
|
3881 box showAtPointer |
|
3882 ! |
|
3883 |
|
3884 classSpawnFullHierarchy |
|
3885 "create a new HierarchyBrowser browsing current class" |
|
3886 |
|
3887 self doClassMenuWithSelection:[:cls :sel | |
|
3888 self class browseFullClassHierarchy:cls |
|
3889 ] |
|
3890 ! ! |
|
3891 |
|
3892 !SystemBrowser methodsFor:'class category stuff'! |
|
3893 |
|
3894 checkClassCategorySelected |
|
3895 currentClassCategory isNil ifTrue:[ |
|
3896 self warn:'select a class category first'. |
|
3897 ^ false |
|
3898 ]. |
|
3899 ^ true |
|
3900 ! |
|
3901 |
|
3902 listOfAllClassCategories |
|
3903 "return a list of all class categories" |
|
3904 |
|
3905 |newList cat| |
|
3906 |
|
3907 newList := Text with:'* all *' with:'* hierarchy *'. |
|
3908 Smalltalk allBehaviorsDo:[:aClass | |
|
3909 cat := aClass category. |
|
3910 cat isNil ifTrue:[ |
|
3911 cat := '* no category *' |
|
3912 ]. |
|
3913 newList indexOf:cat ifAbsent:[newList add:cat] |
|
3914 ]. |
|
3915 newList sort. |
|
3916 ^ newList |
|
3917 ! |
|
3918 |
|
3919 classCategorySelectionChanged |
|
3920 "class category has changed - update dependent views" |
|
3921 |
|
3922 self withWaitCursorDo:[ |
|
3923 self switchToClass:nil. |
|
3924 actualClass := nil. |
|
3925 currentMethodCategory := nil. |
|
3926 currentMethod := currentSelector := nil. |
|
3927 |
|
3928 self updateClassList. |
|
3929 self updateMethodCategoryList. |
|
3930 self updateMethodList. |
|
3931 self updateCodeView. |
|
3932 |
|
3933 codeView explainAction:nil. |
|
3934 codeView acceptAction:nil |
|
3935 ] |
|
3936 ! |
|
3937 |
|
3938 classCategorySelection:lineNr |
|
3939 "user clicked on a class category line - show classes. |
|
3940 If switching to hierarchy or all, keep current selections" |
|
3941 |
|
3942 |newCategory oldClass classIndex index| |
|
3943 |
|
3944 newCategory := classCategoryListView selectionValue. |
|
3945 (newCategory startsWith:'*') ifTrue:[ |
|
3946 "etiher all or hierarchy; |
|
3947 remember current selections and switch after showing class list" |
|
3948 oldClass := currentClass |
|
3949 ]. |
|
3950 currentClassCategory := newCategory. |
|
3951 oldClass isNil ifTrue:[ |
|
3952 self classCategorySelectionChanged |
|
3953 ] ifFalse:[ |
|
3954 self withWaitCursorDo:[ |
|
3955 self updateClassList |
|
3956 ]. |
|
3957 "stupid - search for class name in (indented) list" |
|
3958 index := 1. |
|
3959 classListView list do:[:elem | |
|
3960 (elem endsWith:(oldClass name)) ifTrue:[ |
|
3961 classIndex := index |
|
3962 ]. |
|
3963 index := index + 1 |
|
3964 ]. |
|
3965 classIndex notNil ifTrue:[ |
|
3966 classListView selection:classIndex. |
|
3967 self switchToClass:(Smalltalk at:(oldClass name asSymbol)) |
|
1773 ] ifFalse:[ |
3968 ] ifFalse:[ |
1774 instanceToggle turnOn. |
3969 self normalLabel. |
1775 classToggle turnOff |
|
1776 ] |
3970 ] |
1777 ] |
3971 ] |
1778 ! |
3972 ! |
1779 |
3973 |
1780 updateClassCategoryListWithScroll:scroll |
3974 updateClassCategoryListWithScroll:scroll |
1786 oldClassCategory := currentClassCategory. |
3980 oldClassCategory := currentClassCategory. |
1787 oldClass := currentClass. |
3981 oldClass := currentClass. |
1788 oldMethodCategory := currentMethodCategory. |
3982 oldMethodCategory := currentMethodCategory. |
1789 oldMethod := currentMethod. |
3983 oldMethod := currentMethod. |
1790 oldMethod notNil ifTrue:[ |
3984 oldMethod notNil ifTrue:[ |
1791 oldSelector := methodListView selectionValue |
3985 oldSelector := currentSelector |
1792 ]. |
3986 ]. |
1793 |
3987 |
1794 classCategoryListView notNil ifTrue:[ |
3988 classCategoryListView notNil ifTrue:[ |
1795 newCategoryList := self listOfAllClassCategories. |
3989 newCategoryList := self listOfAllClassCategories. |
1796 newCategoryList = classCategoryListView list ifFalse:[ |
3990 newCategoryList = classCategoryListView list ifFalse:[ |
1826 |
4020 |
1827 updateClassCategoryList |
4021 updateClassCategoryList |
1828 self updateClassCategoryListWithScroll:true |
4022 self updateClassCategoryListWithScroll:true |
1829 ! |
4023 ! |
1830 |
4024 |
1831 updateClassListWithScroll:scroll |
4025 allClassesInCurrentCategoryInOrderDo:aBlock |
1832 |classes oldClassName| |
4026 "evaluate aBlock for all classes in the current class category; |
1833 |
4027 superclasses come first - then subclasses" |
1834 classListView notNil ifTrue:[ |
4028 |
1835 currentClass notNil ifTrue:[ |
4029 |classes| |
1836 oldClassName := currentClass name. |
4030 |
1837 currentClass := Smalltalk at:(oldClassName asSymbol). |
4031 currentClassCategory notNil ifTrue:[ |
1838 ]. |
4032 classes := OrderedCollection new. |
1839 |
4033 Smalltalk allBehaviorsDo:[:aClass | |
1840 currentClassCategory notNil ifTrue:[ |
4034 aClass isMeta ifFalse:[ |
1841 classes := self listOfAllClassesInCategory:currentClassCategory |
4035 (aClass category = currentClassCategory) ifTrue:[ |
1842 ] ifFalse:[ |
4036 classes add:aClass |
1843 currentClassHierarchy notNil ifTrue:[ |
4037 ] |
1844 classes := self listOfClassHierarchyOf:currentClassHierarchy |
|
1845 ] |
4038 ] |
1846 ]. |
4039 ]. |
1847 |
4040 classes topologicalSort:[:a :b | b isSubclassOf:a]. |
1848 classListView list = classes ifFalse:[ |
4041 classes do:aBlock |
1849 scroll ifTrue:[ |
4042 ] |
1850 classListView contents:classes |
4043 ! |
1851 ] ifFalse:[ |
4044 |
1852 classListView setContents:classes |
4045 allClassesInCurrentCategoryDo:aBlock |
1853 ]. |
4046 "evaluate aBlock for all classes in the current class category; |
1854 oldClassName notNil ifTrue:[ |
4047 superclasses come first - then subclasses" |
1855 classListView setContents:classes. |
4048 |
1856 classListView selectElement:oldClassName |
4049 currentClassCategory notNil ifTrue:[ |
1857 ] ifFalse:[ |
4050 Smalltalk allBehaviorsDo:[:aClass | |
1858 variableListView notNil ifTrue:[variableListView contents:nil] |
4051 aClass isMeta ifFalse:[ |
4052 (aClass category = currentClassCategory) ifTrue:[ |
|
4053 aBlock value:aClass |
|
4054 ] |
|
1859 ] |
4055 ] |
1860 ] |
4056 ]. |
1861 ] |
4057 ] |
1862 ! |
4058 ! |
1863 |
4059 |
1864 updateClassList |
4060 renameCurrentClassCategoryTo:aString |
1865 self updateClassListWithScroll:true |
4061 "helper - do the rename" |
1866 ! |
4062 |
1867 |
4063 |any categories| |
1868 updateVariableList |
4064 |
1869 |l subList flags last| |
4065 currentClassCategory notNil ifTrue:[ |
1870 |
4066 any := false. |
1871 variableListView isNil ifTrue:[^ self]. |
4067 Smalltalk allBehaviorsDo:[:aClass | |
1872 |
4068 aClass category = currentClassCategory ifTrue:[ |
1873 l := OrderedCollection new. |
4069 aClass category:aString. |
1874 actualClass withAllSuperclasses do:[:aClass | |
4070 any := true |
1875 subList := aClass instVarNames. |
|
1876 subList size ~~ 0 ifTrue:[ |
|
1877 l := l , (subList asOrderedCollection reverse). |
|
1878 l := l , (OrderedCollection with:'---- ' , aClass name , ' ---------'). |
|
1879 ] |
|
1880 ]. |
|
1881 l reverse. |
|
1882 variableListView attributes:nil. |
|
1883 variableListView list:l. |
|
1884 l keysAndValuesDo:[:index :entry | |
|
1885 (entry startsWith:'---') ifTrue:[ |
|
1886 variableListView attributeAt:index put:#halfIntensity. |
|
1887 last := index |
|
1888 ] |
|
1889 ]. |
|
1890 last notNil ifTrue:[variableListView scrollToLine:last] |
|
1891 ! |
|
1892 |
|
1893 updateMethodCategoryListWithScroll:scroll |
|
1894 |categories| |
|
1895 |
|
1896 methodCategoryListView notNil ifTrue:[ |
|
1897 currentClass notNil ifTrue:[ |
|
1898 categories := self listOfAllMethodCategoriesInClass:actualClass |
|
1899 ]. |
|
1900 methodCategoryListView list = categories ifFalse:[ |
|
1901 scroll ifTrue:[ |
|
1902 methodCategoryListView contents:categories |
|
1903 ] ifFalse:[ |
|
1904 methodCategoryListView setContents:categories |
|
1905 ]. |
|
1906 currentMethodCategory notNil ifTrue:[ |
|
1907 methodCategoryListView selectElement:currentMethodCategory |
|
1908 ] |
4071 ] |
1909 ] |
4072 ]. |
1910 ] |
4073 any ifFalse:[ |
1911 ! |
4074 categories := classCategoryListView list. |
1912 |
4075 categories remove:currentClassCategory. |
1913 updateMethodCategoryList |
4076 categories add:aString. |
1914 self updateMethodCategoryListWithScroll:true |
4077 categories sort. |
1915 ! |
4078 classCategoryListView setContents:categories. |
1916 |
4079 currentClassCategory := aString. |
1917 updateMethodListWithScroll:scroll |
4080 classCategoryListView selectElement:aString. |
1918 |selectors scr first last| |
4081 ] ifTrue:[ |
1919 |
4082 currentClassCategory := aString. |
1920 methodListView notNil ifTrue:[ |
4083 self updateClassCategoryList. |
1921 currentMethodCategory notNil ifTrue:[ |
4084 self updateClassListWithScroll:false |
1922 selectors := self listOfAllSelectorsInCategory:currentMethodCategory |
4085 ] |
1923 ofClass:actualClass |
4086 ] |
1924 ]. |
4087 ! ! |
1925 scr := scroll. |
4088 |
1926 first := methodListView firstLineShown. |
4089 !SystemBrowser methodsFor:'class-method stuff'! |
1927 first ~~ 1 ifTrue:[ |
|
1928 last := methodListView lastLineShown. |
|
1929 selectors size <= (last - first + 1) ifTrue:[ |
|
1930 scr := true |
|
1931 ] |
|
1932 ]. |
|
1933 methodListView list = selectors ifFalse:[ |
|
1934 scr ifTrue:[ |
|
1935 methodListView contents:selectors |
|
1936 ] ifFalse:[ |
|
1937 methodListView setContents:selectors |
|
1938 ] |
|
1939 ]. |
|
1940 ] |
|
1941 ! |
|
1942 |
|
1943 updateMethodList |
|
1944 self updateMethodListWithScroll:true |
|
1945 ! |
|
1946 |
|
1947 updateCodeView |
|
1948 |code aStream| |
|
1949 |
|
1950 fullClass ifTrue:[ |
|
1951 currentClass notNil ifTrue:[ |
|
1952 " this is too slow for big classes ... |
|
1953 code := String new:1000. |
|
1954 aStream := WriteStream on:code. |
|
1955 currentClass fileOutOn:aStream |
|
1956 " |
|
1957 aStream := FileStream newFileNamed:'__temp'. |
|
1958 aStream isNil ifTrue:[ |
|
1959 self notify:'cannot create temporary file.'. |
|
1960 codeView contents:nil. |
|
1961 codeView modified:false. |
|
1962 ^ self |
|
1963 ]. |
|
1964 currentClass fileOutOn:aStream. |
|
1965 aStream close. |
|
1966 aStream := FileStream oldFileNamed:'__temp'. |
|
1967 aStream isNil ifTrue:[ |
|
1968 self notify:'oops - cannot reopen temp file'. |
|
1969 codeView contents:nil. |
|
1970 codeView modified:false. |
|
1971 ^ self |
|
1972 ]. |
|
1973 code := aStream contents. |
|
1974 aStream close. |
|
1975 OperatingSystem removeFile:'__temp' |
|
1976 ] |
|
1977 ] ifFalse:[ |
|
1978 currentMethod notNil ifTrue:[ |
|
1979 code := currentMethod source |
|
1980 ] |
|
1981 ]. |
|
1982 codeView contents:code. |
|
1983 codeView modified:false |
|
1984 ! |
|
1985 |
|
1986 classSelectionChanged |
|
1987 |oldMethodCategory oldMethod| |
|
1988 |
|
1989 self withWaitCursorDo:[ |
|
1990 oldMethodCategory := currentMethodCategory. |
|
1991 oldMethod := currentMethod. |
|
1992 |
|
1993 showInstance ifTrue:[ |
|
1994 actualClass := currentClass |
|
1995 ] ifFalse:[ |
|
1996 actualClass := currentClass class |
|
1997 ]. |
|
1998 currentMethodCategory := nil. |
|
1999 currentMethod := nil. |
|
2000 |
|
2001 self updateVariableList. |
|
2002 self updateMethodCategoryList. |
|
2003 oldMethodCategory notNil ifTrue:[ |
|
2004 methodCategoryListView selectElement:oldMethodCategory. |
|
2005 methodCategoryListView selection notNil ifTrue:[ |
|
2006 currentMethodCategory := oldMethodCategory. |
|
2007 self methodCategorySelectionChanged |
|
2008 ] |
|
2009 ]. |
|
2010 self updateMethodList. |
|
2011 self updateCodeView. |
|
2012 |
|
2013 fullClass ifTrue:[ |
|
2014 codeView acceptAction:[:theCode | |
|
2015 codeView cursor:Cursor execute. |
|
2016 Object abortSignal catch:[ |
|
2017 self compileCode:theCode asString. |
|
2018 codeView modified:false. |
|
2019 ]. |
|
2020 codeView cursor:Cursor normal. |
|
2021 ]. |
|
2022 codeView explainAction:nil |
|
2023 ] ifFalse:[ |
|
2024 self classDefinition. |
|
2025 codeView acceptAction:[:theCode | |
|
2026 codeView cursor:Cursor execute. |
|
2027 Object abortSignal catch:[ |
|
2028 (Compiler evaluate:theCode asString notifying:codeView) |
|
2029 isBehavior ifTrue:[ |
|
2030 self classCategoryUpdate. |
|
2031 self updateClassListWithScroll:false. |
|
2032 codeView modified:false. |
|
2033 ]. |
|
2034 ]. |
|
2035 codeView cursor:Cursor normal. |
|
2036 ]. |
|
2037 codeView explainAction:nil |
|
2038 ]. |
|
2039 classCategoryListView notNil ifTrue:[ |
|
2040 (currentClassCategory = currentClass category) ifFalse:[ |
|
2041 currentClassCategory := currentClass category. |
|
2042 classCategoryListView selectElement:currentClassCategory |
|
2043 ] |
|
2044 ]. |
|
2045 |
|
2046 "set self for doits. This allows accessing the current class |
|
2047 as self, and access to the class variables by name." |
|
2048 |
|
2049 codeView doItAction:[:theCode | |
|
2050 |compiler| |
|
2051 |
|
2052 currentClass isNil ifTrue:[ |
|
2053 compiler := Compiler |
|
2054 ] ifFalse:[ |
|
2055 compiler := currentClass compiler |
|
2056 ]. |
|
2057 compiler |
|
2058 evaluate:theCode |
|
2059 in:nil |
|
2060 receiver:currentClass |
|
2061 notifying:codeView |
|
2062 logged:false |
|
2063 ifFail:nil |
|
2064 ] |
|
2065 ] |
|
2066 ! |
|
2067 |
|
2068 classCategorySelectionChanged |
|
2069 "class category has changed - update dependant views" |
|
2070 |
|
2071 self withWaitCursorDo:[ |
|
2072 self switchToClass:nil. |
|
2073 actualClass := nil. |
|
2074 currentMethodCategory := nil. |
|
2075 currentMethod := nil. |
|
2076 |
|
2077 self updateClassList. |
|
2078 self updateMethodCategoryList. |
|
2079 self updateMethodList. |
|
2080 self updateCodeView. |
|
2081 |
|
2082 codeView explainAction:nil. |
|
2083 codeView acceptAction:nil |
|
2084 ] |
|
2085 ! |
|
2086 |
|
2087 classCategorySelection:lineNr |
|
2088 "user clicked on a class category line - show classes. |
|
2089 If switching to hierarchy or all, keep current selections" |
|
2090 |
|
2091 |newCategory oldClass classIndex index| |
|
2092 |
|
2093 newCategory := classCategoryListView selectionValue. |
|
2094 (newCategory startsWith:'*') ifTrue:[ |
|
2095 "etiher all or hierarchy; |
|
2096 remember current selections and switch after showing class list" |
|
2097 oldClass := currentClass |
|
2098 ]. |
|
2099 currentClassCategory := newCategory. |
|
2100 oldClass isNil ifTrue:[ |
|
2101 self classCategorySelectionChanged |
|
2102 ] ifFalse:[ |
|
2103 self withWaitCursorDo:[ |
|
2104 self updateClassList |
|
2105 ]. |
|
2106 "stupid - search for class name in (indented) list" |
|
2107 index := 1. |
|
2108 classListView list do:[:elem | |
|
2109 (elem endsWith:(oldClass name)) ifTrue:[ |
|
2110 classIndex := index |
|
2111 ]. |
|
2112 index := index + 1 |
|
2113 ]. |
|
2114 classIndex notNil ifTrue:[ |
|
2115 classListView selection:classIndex. |
|
2116 self switchToClass:(Smalltalk at:(oldClass name asSymbol)) |
|
2117 ] ifFalse:[ |
|
2118 self normalLabel. |
|
2119 ] |
|
2120 ] |
|
2121 ! |
|
2122 |
|
2123 classSelection:lineNr |
|
2124 "user clicked on a class line - show method categories" |
|
2125 |
|
2126 |classSymbol cls| |
|
2127 |
|
2128 classSymbol := classListView selectionValue withoutSpaces asSymbol. |
|
2129 (Smalltalk includesKey:classSymbol) ifTrue:[ |
|
2130 cls := Smalltalk at:classSymbol |
|
2131 ]. |
|
2132 cls notNil ifTrue:[ |
|
2133 self switchToClass:cls. |
|
2134 self classSelectionChanged |
|
2135 ] |
|
2136 ! |
|
2137 |
|
2138 methodCategorySelectionChanged |
|
2139 "method category selection has changed - update dependant views" |
|
2140 |
|
2141 self withWaitCursorDo:[ |
|
2142 currentMethod := nil. |
|
2143 |
|
2144 self updateMethodList. |
|
2145 self updateCodeView. |
|
2146 |
|
2147 currentMethodCategory notNil ifTrue:[ |
|
2148 methodCategoryListView selectElement:currentMethodCategory |
|
2149 ]. |
|
2150 |
|
2151 codeView acceptAction:[:theCode | |
|
2152 codeView cursor:Cursor execute. |
|
2153 Object abortSignal catch:[ |
|
2154 actualClass compiler compile:theCode asString |
|
2155 forClass:actualClass |
|
2156 inCategory:currentMethodCategory |
|
2157 notifying:codeView. |
|
2158 codeView modified:false. |
|
2159 self updateMethodListWithScroll:false. |
|
2160 ]. |
|
2161 codeView cursor:Cursor normal. |
|
2162 ]. |
|
2163 codeView explainAction:[:theCode :theSelection | |
|
2164 self showExplanation:(Explainer explain:theSelection |
|
2165 in:theCode |
|
2166 forClass:actualClass) |
|
2167 ] |
|
2168 ] |
|
2169 ! |
|
2170 |
|
2171 methodCategorySelection:lineNr |
|
2172 "user clicked on a method category line - show selectors" |
|
2173 |
|
2174 currentClass isNil ifTrue:[^ self]. |
|
2175 |
|
2176 currentMethodCategory := methodCategoryListView selectionValue. |
|
2177 self methodCategorySelectionChanged |
|
2178 ! |
|
2179 |
|
2180 methodSelectionChanged |
|
2181 "method selection has changed - update dependant views" |
|
2182 |
|
2183 self withWaitCursorDo:[ |
|
2184 self updateCodeView. |
|
2185 codeView acceptAction:[:theCode | |
|
2186 codeView cursor:Cursor execute. |
|
2187 Object abortSignal catch:[ |
|
2188 actualClass compiler compile:theCode asString |
|
2189 forClass:actualClass |
|
2190 inCategory:currentMethodCategory |
|
2191 notifying:codeView. |
|
2192 codeView modified:false. |
|
2193 self updateMethodListWithScroll:false. |
|
2194 ]. |
|
2195 codeView cursor:Cursor normal. |
|
2196 ]. |
|
2197 codeView explainAction:[:theCode :theSelection | |
|
2198 self showExplanation:(Explainer explain:theSelection |
|
2199 in:theCode |
|
2200 forClass:actualClass) |
|
2201 ]. |
|
2202 methodListView notNil ifTrue:[ |
|
2203 (currentMethod notNil and:[currentMethod isWrapped]) ifTrue:[ |
|
2204 self initializeMethodMenu2 |
|
2205 ] ifFalse:[ |
|
2206 self initializeMethodMenu |
|
2207 ] |
|
2208 ] |
|
2209 ] |
|
2210 ! |
|
2211 |
|
2212 methodSelection:lineNr |
|
2213 "user clicked on a method line - show code" |
|
2214 |
|
2215 |selectorString selectorSymbol| |
|
2216 |
|
2217 currentClass isNil ifTrue:[^ self]. |
|
2218 |
|
2219 selectorString := methodListView selectionValue. |
|
2220 " |
|
2221 kludge: check if its a wrapped one |
|
2222 " |
|
2223 (selectorString endsWith:' !!') ifTrue:[ |
|
2224 selectorString := selectorString copyTo:(selectorString size - 2) |
|
2225 ]. |
|
2226 selectorSymbol := selectorString asSymbol. |
|
2227 currentMethod := actualClass compiledMethodAt:selectorSymbol. |
|
2228 |
|
2229 methodCategoryListView notNil ifTrue:[ |
|
2230 currentMethod notNil ifTrue:[ |
|
2231 (currentMethodCategory = currentMethod category) ifFalse:[ |
|
2232 currentMethodCategory := currentMethod category. |
|
2233 methodCategoryListView selectElement:currentMethodCategory |
|
2234 ] |
|
2235 ] |
|
2236 ]. |
|
2237 |
|
2238 self methodSelectionChanged |
|
2239 ! |
|
2240 |
4090 |
2241 classFromClassMethodString:aString |
4091 classFromClassMethodString:aString |
2242 "helper for classMethod-list - extract class name from the string" |
4092 "helper for classMethod-list - extract class name from the string" |
2243 |
4093 |
2244 |pos| |
4094 |pos| |
2254 |
4104 |
2255 pos := aString indexOf:(Character space). |
4105 pos := aString indexOf:(Character space). |
2256 ^ aString copyFrom:(pos + 1) |
4106 ^ aString copyFrom:(pos + 1) |
2257 ! |
4107 ! |
2258 |
4108 |
2259 listSelection:lineNr |
4109 classMethodSelection:lineNr |
2260 "user clicked on a class/method line - show code" |
4110 "user clicked on a class/method line - show code" |
2261 |
4111 |
2262 |string classString selectorString| |
4112 |string classString selectorString| |
2263 |
4113 |
2264 string := classMethodListView selectionValue. |
4114 string := classMethodListView selectionValue. |
2274 ]. |
4124 ]. |
2275 currentClass isNil ifTrue:[ |
4125 currentClass isNil ifTrue:[ |
2276 self warn:'oops class is gone' |
4126 self warn:'oops class is gone' |
2277 ] ifFalse:[ |
4127 ] ifFalse:[ |
2278 currentClassCategory := currentClass category. |
4128 currentClassCategory := currentClass category. |
2279 currentMethod := actualClass compiledMethodAt:(selectorString asSymbol). |
4129 currentSelector := selectorString asSymbol. |
4130 currentMethod := actualClass compiledMethodAt:currentSelector. |
|
2280 currentMethodCategory := currentMethod category. |
4131 currentMethodCategory := currentMethod category. |
2281 |
4132 |
2282 self methodSelectionChanged |
4133 self methodSelectionChanged |
2283 ] |
4134 ] |
2284 ! ! |
4135 ! ! |
2285 |
4136 |
2286 !SystemBrowser methodsFor:'class category menu'! |
4137 !SystemBrowser methodsFor:'class category list menu'! |
2287 |
4138 |
2288 initializeClassCategoryMenu |
4139 initializeClassCategoryMenu |
2289 |labels| |
4140 |labels| |
2290 |
4141 |
2291 labels := resources array:#( |
4142 labels := resources array:#( |
2326 classCategoryRemove) |
4177 classCategoryRemove) |
2327 receiver:self |
4178 receiver:self |
2328 for:classCategoryListView) |
4179 for:classCategoryListView) |
2329 ! |
4180 ! |
2330 |
4181 |
2331 allClassesInCurrentCategoryInOrderDo:aBlock |
|
2332 "evaluate aBlock for all classes in the current class category; |
|
2333 superclasses come first - then subclasses" |
|
2334 |
|
2335 |classes| |
|
2336 |
|
2337 currentClassCategory notNil ifTrue:[ |
|
2338 classes := OrderedCollection new. |
|
2339 Smalltalk allClassesDo:[:aClass | |
|
2340 aClass isMeta ifFalse:[ |
|
2341 (aClass category = currentClassCategory) ifTrue:[ |
|
2342 classes add:aClass |
|
2343 ] |
|
2344 ] |
|
2345 ]. |
|
2346 classes topologicalSort:[:a :b | b isSubclassOf:a]. |
|
2347 classes do:aBlock |
|
2348 ] |
|
2349 ! |
|
2350 |
|
2351 allClassesInCurrentCategoryDo:aBlock |
|
2352 "evaluate aBlock for all classes in the current class category; |
|
2353 superclasses come first - then subclasses" |
|
2354 |
|
2355 currentClassCategory notNil ifTrue:[ |
|
2356 Smalltalk allClassesDo:[:aClass | |
|
2357 aClass isMeta ifFalse:[ |
|
2358 (aClass category = currentClassCategory) ifTrue:[ |
|
2359 aBlock value:aClass |
|
2360 ] |
|
2361 ] |
|
2362 ]. |
|
2363 ] |
|
2364 ! |
|
2365 |
|
2366 classCategoryUpdate |
4182 classCategoryUpdate |
2367 "update class category list and dependants" |
4183 "update class category list and dependants" |
2368 |
4184 |
2369 |oldClassName oldMethodCategory| |
4185 |oldClassName oldMethodCategory| |
2370 |
4186 |
2413 aClass printOutOn:printStream. |
4229 aClass printOutOn:printStream. |
2414 printStream close |
4230 printStream close |
2415 ] |
4231 ] |
2416 ! |
4232 ! |
2417 |
4233 |
4234 classCategorySpawn |
|
4235 "create a new SystemBrowser browsing current classCategory" |
|
4236 |
|
4237 currentClassCategory notNil ifTrue:[ |
|
4238 self withWaitCursorDo:[ |
|
4239 self class browseClassCategory:currentClassCategory |
|
4240 ] |
|
4241 ] |
|
4242 ! |
|
4243 |
|
2418 classCategoryFileOut |
4244 classCategoryFileOut |
2419 "create a file 'categoryName' consisting of all classes in current category" |
4245 "create a file 'categoryName' consisting of all classes in current category" |
2420 |
4246 |
2421 |aStream fileName| |
4247 |aStream fileName| |
2422 |
4248 |
2440 aStream := FileStream newFileNamed:fileName. |
4266 aStream := FileStream newFileNamed:fileName. |
2441 aStream isNil ifTrue:[ |
4267 aStream isNil ifTrue:[ |
2442 ^ self warn:'cannot create: %1' with:fileName |
4268 ^ self warn:'cannot create: %1' with:fileName |
2443 ]. |
4269 ]. |
2444 self withWaitCursorDo:[ |
4270 self withWaitCursorDo:[ |
2445 self label:('System Browser writing: ' , fileName). |
4271 self busyLabel:'writing: %1' with:fileName. |
2446 self allClassesInCurrentCategoryInOrderDo:[:aClass | |
4272 self allClassesInCurrentCategoryInOrderDo:[:aClass | |
2447 aClass fileOutOn:aStream. |
4273 aClass fileOutOn:aStream. |
2448 ]. |
4274 ]. |
2449 aStream close. |
4275 aStream close. |
2450 self normalLabel. |
4276 self normalLabel. |
4277 ] |
|
4278 ! |
|
4279 |
|
4280 classCategorySpawnFullClass |
|
4281 "create a new SystemBrowser browsing full class" |
|
4282 |
|
4283 |newBrowser| |
|
4284 |
|
4285 self withWaitCursorDo:[ |
|
4286 newBrowser := self class browseFullClasses |
|
4287 " " |
|
4288 . |
|
4289 currentClass notNil ifTrue:[ |
|
4290 newBrowser switchToClassNamed:(currentClass name) |
|
4291 ] |
|
4292 " " |
|
2451 ] |
4293 ] |
2452 ! |
4294 ! |
2453 |
4295 |
2454 classCategoryFileOutEach |
4296 classCategoryFileOutEach |
2455 self withWaitCursorDo:[ |
4297 self withWaitCursorDo:[ |
2456 self allClassesInCurrentCategoryDo:[:aClass | |
4298 self allClassesInCurrentCategoryDo:[:aClass | |
2457 self label:('System Browser saving: ' , aClass name). |
4299 self busyLabel:'saving: ' with:aClass name. |
2458 Class fileOutErrorSignal handle:[:ex | |
4300 Class fileOutErrorSignal handle:[:ex | |
2459 self warn:'cannot create: %1' with:ex parameter. |
4301 self warn:'cannot create: %1' with:ex parameter. |
2460 ex return. |
4302 ex return. |
2461 ] do:[ |
4303 ] do:[ |
2462 aClass fileOut |
4304 aClass fileOut |
2464 ]. |
4306 ]. |
2465 self normalLabel. |
4307 self normalLabel. |
2466 ] |
4308 ] |
2467 ! |
4309 ! |
2468 |
4310 |
2469 classCategorySpawn |
|
2470 "create a new SystemBrowser browsing current classCategory" |
|
2471 |
|
2472 currentClassCategory notNil ifTrue:[ |
|
2473 self withWaitCursorDo:[ |
|
2474 self class browseClassCategory:currentClassCategory |
|
2475 ] |
|
2476 ] |
|
2477 ! |
|
2478 |
|
2479 classCategorySpawnFullClass |
|
2480 "create a new SystemBrowser browsing full class" |
|
2481 |
|
2482 |newBrowser| |
|
2483 |
|
2484 self withWaitCursorDo:[ |
|
2485 newBrowser := self class browseFullClasses |
|
2486 " |
|
2487 . |
|
2488 currentClass notNil ifTrue:[ |
|
2489 newBrowser switchToClassNamed:(currentClass name) |
|
2490 ] |
|
2491 " |
|
2492 ] |
|
2493 ! |
|
2494 |
|
2495 classCategoryNewCategory |
4311 classCategoryNewCategory |
2496 |box| |
4312 |box| |
2497 |
4313 |
2498 box := self enterBoxTitle:'name of new class category:' okText:'create'. |
4314 box := self enterBoxTitle:'name of new class category:' okText:'create'. |
2499 box action:[:aString | |
4315 box action:[:aString | |
2500 |categories| |
4316 |categories| |
2501 |
4317 |
2502 categories := classCategoryListView list. |
4318 currentClass notNil ifTrue:[ |
4319 categories := OrderedCollection new. |
|
4320 currentClass withAllSuperclasses do:[:aClass | |
|
4321 aClass methodArray do:[:aMethod | |
|
4322 (categories includes:aMethod category) ifFalse:[ |
|
4323 categories add:aMethod category |
|
4324 ] |
|
4325 ] |
|
4326 ]. |
|
4327 ]. |
|
4328 categories isNil ifTrue:[ |
|
4329 categories := classCategoryListView list. |
|
4330 ]. |
|
2503 (categories includes:aString) ifFalse:[ |
4331 (categories includes:aString) ifFalse:[ |
2504 categories add:aString. |
4332 categories add:aString. |
2505 categories sort. |
4333 categories sort. |
2506 classCategoryListView setContents:categories. |
4334 classCategoryListView setContents:categories. |
2507 currentClassCategory := aString. |
4335 currentClassCategory := aString. |
2512 ] |
4340 ] |
2513 ]. |
4341 ]. |
2514 box showAtPointer |
4342 box showAtPointer |
2515 ! |
4343 ! |
2516 |
4344 |
2517 switchToClassNamed:aString |
|
2518 |classSymbol theClass| |
|
2519 |
|
2520 classSymbol := aString asSymbol. |
|
2521 theClass := Smalltalk at:classSymbol. |
|
2522 theClass isBehavior ifTrue:[ |
|
2523 classCategoryListView notNil ifTrue:[ |
|
2524 currentClassHierarchy isNil ifTrue:[ |
|
2525 (theClass category ~~ currentClassCategory) ifTrue:[ |
|
2526 currentClassCategory := theClass category. |
|
2527 currentClassCategory isNil ifTrue:[ |
|
2528 classCategoryListView selectElement:'* no category *' |
|
2529 ] ifFalse:[ |
|
2530 classCategoryListView selectElement:currentClassCategory |
|
2531 ]. |
|
2532 self classCategorySelectionChanged |
|
2533 ] |
|
2534 ] |
|
2535 ]. |
|
2536 self switchToClass:theClass. |
|
2537 classListView selectElement:aString. |
|
2538 self classSelectionChanged |
|
2539 ] |
|
2540 ! |
|
2541 |
|
2542 switchToClassNameMatching:aMatchString |
|
2543 |classNames thisName box| |
|
2544 |
|
2545 classNames := OrderedCollection new. |
|
2546 Smalltalk allBehaviorsDo:[:aClass | |
|
2547 thisName := aClass name. |
|
2548 (aMatchString match:thisName) ifTrue:[ |
|
2549 classNames add:thisName |
|
2550 ] |
|
2551 ]. |
|
2552 (classNames size == 0) ifTrue:[^ nil]. |
|
2553 (classNames size == 1) ifTrue:[ |
|
2554 ^ self switchToClassNamed:(classNames at:1) |
|
2555 ]. |
|
2556 |
|
2557 box := self listBoxTitle:'select class to switch to:' |
|
2558 okText:'ok' |
|
2559 list:classNames sort. |
|
2560 box action:[:aString | self switchToClassNamed:aString]. |
|
2561 box showAtPointer |
|
2562 ! |
|
2563 |
|
2564 classCategoryFindClass |
4345 classCategoryFindClass |
2565 |box| |
4346 |box| |
2566 |
4347 |
2567 box := self enterBoxForCodeSelectionTitle:'class to find:' okText:'find'. |
4348 box := self enterBoxForCodeSelectionTitle:'class to find:' okText:'find'. |
2568 box action:[:aString | self switchToClassNameMatching:aString]. |
4349 box action:[:aString | self switchToClassNameMatching:aString]. |
2569 box showAtPointer |
4350 box showAtPointer |
2570 ! |
|
2571 |
|
2572 renameCurrentClassCategoryTo:aString |
|
2573 "helper - do the rename" |
|
2574 |
|
2575 |any categories| |
|
2576 |
|
2577 currentClassCategory notNil ifTrue:[ |
|
2578 any := false. |
|
2579 Smalltalk allBehaviorsDo:[:aClass | |
|
2580 aClass category = currentClassCategory ifTrue:[ |
|
2581 aClass category:aString. |
|
2582 any := true |
|
2583 ] |
|
2584 ]. |
|
2585 any ifFalse:[ |
|
2586 categories := classCategoryListView list. |
|
2587 categories remove:currentClassCategory. |
|
2588 categories add:aString. |
|
2589 categories sort. |
|
2590 classCategoryListView setContents:categories. |
|
2591 currentClassCategory := aString. |
|
2592 classCategoryListView selectElement:aString. |
|
2593 ] ifTrue:[ |
|
2594 currentClassCategory := aString. |
|
2595 self updateClassCategoryList. |
|
2596 self updateClassListWithScroll:false |
|
2597 ] |
|
2598 ] |
|
2599 ! |
4351 ! |
2600 |
4352 |
2601 classCategoryRename |
4353 classCategoryRename |
2602 "launch an enterBox to rename current class category" |
4354 "launch an enterBox to rename current class category" |
2603 |
4355 |
2666 noText:(resources at:'abort'). |
4418 noText:(resources at:'abort'). |
2667 box confirm ifTrue:[ |
4419 box confirm ifTrue:[ |
2668 "after querying user - do really remove classes in list1 and list2" |
4420 "after querying user - do really remove classes in list1 and list2" |
2669 |
4421 |
2670 subclassesRemoved do:[:aClass | |
4422 subclassesRemoved do:[:aClass | |
2671 Smalltalk removeClass:aClass |
4423 (CheckForInstancesWhenRemovingClasses not |
4424 or:[aClass hasInstances not |
|
4425 or:[self confirm:(aClass name , ' has instances - remove anyway ?')]]) |
|
4426 ifTrue:[ |
|
4427 Smalltalk removeClass:aClass |
|
4428 ] |
|
2672 ]. |
4429 ]. |
2673 classesToRemove do:[:aClass | |
4430 classesToRemove do:[:aClass | |
2674 Smalltalk removeClass:aClass |
4431 (CheckForInstancesWhenRemovingClasses not |
4432 or:[aClass hasInstances not |
|
4433 or:[self confirm:(aClass name , ' has instances - remove anyway ?')]]) |
|
4434 ifTrue:[ |
|
4435 Smalltalk removeClass:aClass |
|
4436 ]. |
|
2675 ]. |
4437 ]. |
2676 currentClassCategory := nil. |
4438 currentClassCategory := nil. |
2677 self switchToClass:nil. |
4439 self switchToClass:nil. |
2678 Smalltalk changed |
4440 Smalltalk changed |
2679 ] |
4441 ] |
2680 ! ! |
4442 ! ! |
2681 |
4443 |
2682 !SystemBrowser methodsFor:'class menu'! |
4444 !SystemBrowser methodsFor:'method category list menu'! |
2683 |
|
2684 initializeClassMenu |
|
2685 |labels menu varMenu| |
|
2686 |
|
2687 labels := resources array:#( |
|
2688 'fileOut' |
|
2689 'printOut' |
|
2690 'printOut protocol' |
|
2691 " 'printOut full protocol' " |
|
2692 '-' |
|
2693 'SPAWN_CLASS' |
|
2694 'spawn hierarchy' |
|
2695 'spawn subclasses' |
|
2696 '-' |
|
2697 'hierarchy' |
|
2698 'definition' |
|
2699 'comment' |
|
2700 'class instvars' |
|
2701 " 'protocols' " |
|
2702 '-' |
|
2703 "/ 'variable search' |
|
2704 'class refs' |
|
2705 '-' |
|
2706 'new class' |
|
2707 'new subclass' |
|
2708 'rename ...' |
|
2709 'remove'). |
|
2710 |
|
2711 menu := PopUpMenu labels:labels |
|
2712 selectors:#(classFileOut |
|
2713 classPrintOut |
|
2714 classPrintOutProtocol |
|
2715 " classPrintOutFullProtocol " |
|
2716 nil |
|
2717 classSpawn |
|
2718 classSpawnHierarchy |
|
2719 classSpawnSubclasses |
|
2720 nil |
|
2721 classHierarchy |
|
2722 classDefinition |
|
2723 classComment |
|
2724 classClassInstVars |
|
2725 " classProtocols " |
|
2726 nil |
|
2727 "/ variables |
|
2728 classRefs |
|
2729 nil |
|
2730 classNewClass |
|
2731 classNewSubclass |
|
2732 classRename |
|
2733 classRemove) |
|
2734 receiver:self |
|
2735 for:classListView. |
|
2736 |
|
2737 classListView middleButtonMenu:menu. |
|
2738 |
|
2739 varMenu := (PopUpMenu labels:(resources array:#( |
|
2740 'instvar refs ...' |
|
2741 'classvar refs ...' |
|
2742 'all instvar refs ...' |
|
2743 'all classvar refs ...' |
|
2744 '-' |
|
2745 'instvar mods ...' |
|
2746 'classvar mods ...' |
|
2747 'all instvar mods ...' |
|
2748 'all classvar mods ...' |
|
2749 )) |
|
2750 selectors:#( |
|
2751 classInstVarRefs |
|
2752 classClassVarRefs |
|
2753 classAllInstVarRefs |
|
2754 classAllClassVarRefs |
|
2755 nil |
|
2756 classInstVarMods |
|
2757 classClassVarMods |
|
2758 classAllInstVarMods |
|
2759 classAllClassVarMods |
|
2760 ) |
|
2761 receiver:self |
|
2762 for:self). |
|
2763 |
|
2764 variableListView isNil ifTrue:[ |
|
2765 menu addLabel:(resources string:'variable search') |
|
2766 selector:#variables |
|
2767 before:#classRefs. |
|
2768 menu subMenuAt:#variables put:varMenu. |
|
2769 ] ifFalse:[ |
|
2770 variableListView middleButtonMenu:varMenu |
|
2771 ]. |
|
2772 ! |
|
2773 |
|
2774 checkClassCategorySelected |
|
2775 currentClassCategory isNil ifTrue:[ |
|
2776 self warn:'select a class category first'. |
|
2777 ^ false |
|
2778 ]. |
|
2779 ^ true |
|
2780 ! |
|
2781 |
|
2782 checkClassSelected |
|
2783 currentClass isNil ifTrue:[ |
|
2784 self warn:'select a class first'. |
|
2785 ^ false |
|
2786 ]. |
|
2787 ^ true |
|
2788 ! |
|
2789 |
|
2790 checkMethodCategorySelected |
|
2791 currentMethodCategory isNil ifTrue:[ |
|
2792 self warn:'select a method category first'. |
|
2793 ^ false |
|
2794 ]. |
|
2795 ^ true |
|
2796 ! |
|
2797 |
|
2798 whenMethodCategorySelected:aBlock |
|
2799 self checkMethodCategorySelected ifTrue:[ |
|
2800 self withWaitCursorDo:aBlock |
|
2801 ] |
|
2802 ! |
|
2803 |
|
2804 checkMethodSelected |
|
2805 currentMethod isNil ifTrue:[ |
|
2806 self warn:'select a method first'. |
|
2807 ^ false |
|
2808 ]. |
|
2809 ^ true |
|
2810 ! |
|
2811 |
|
2812 doClassMenu:aBlock |
|
2813 "a helper - check if class is selected and evaluate aBlock |
|
2814 while showing waitCursor" |
|
2815 |
|
2816 self checkClassSelected ifTrue:[ |
|
2817 self withWaitCursorDo:aBlock |
|
2818 ] |
|
2819 ! |
|
2820 |
|
2821 doClassMenuWithSelection:aBlock |
|
2822 "a helper - if there is a selection, which represents a classes name, |
|
2823 evaluate aBlock, passing that class and optional selector as arguments. |
|
2824 Otherwise, check if a class is selected and evaluate aBlock with the |
|
2825 current class." |
|
2826 |
|
2827 |string words clsName cls sel isMeta w| |
|
2828 |
|
2829 string := codeView selection. |
|
2830 string notNil ifTrue:[ |
|
2831 string := string asString withoutSeparators. |
|
2832 words := string asCollectionOfWords. |
|
2833 words notNil ifTrue:[ |
|
2834 clsName := words first. |
|
2835 (clsName endsWith:'class') ifTrue:[ |
|
2836 isMeta := true. |
|
2837 clsName := clsName copyTo:(clsName size - 5) |
|
2838 ] ifFalse:[ |
|
2839 isMeta := false |
|
2840 ]. |
|
2841 (cls := Smalltalk classNamed:clsName) notNil ifTrue:[ |
|
2842 sel := Parser selectorInExpression:string. |
|
2843 isMeta ifTrue:[ |
|
2844 cls := cls class |
|
2845 ]. |
|
2846 self withWaitCursorDo:[ |
|
2847 aBlock value:cls value:sel. |
|
2848 ]. |
|
2849 ^ self |
|
2850 ] ifFalse:[ |
|
2851 self warn:'no class named: %1 - spawning current' with:clsName |
|
2852 ] |
|
2853 ]. |
|
2854 ]. |
|
2855 |
|
2856 self doClassMenu:[aBlock value:currentClass value:nil] |
|
2857 ! |
|
2858 |
|
2859 classSpawn |
|
2860 "create a new SystemBrowser browsing current class, |
|
2861 or if there is a selection, spawn a browser on the selected class |
|
2862 even a class/selector pair can be specified." |
|
2863 |
|
2864 |browser| |
|
2865 |
|
2866 self doClassMenuWithSelection:[:cls :sel | |
|
2867 cls isMeta ifTrue:[ |
|
2868 Smalltalk allClassesDo:[:aClass | |
|
2869 aClass class == cls ifTrue:[ |
|
2870 browser := self class browseClass:aClass. |
|
2871 browser classProtocol. |
|
2872 sel notNil ifTrue:[ |
|
2873 browser switchToMethodNamed:sel |
|
2874 ]. |
|
2875 ^ self |
|
2876 ]. |
|
2877 ]. |
|
2878 self warn:'oops, no class for this metaclass'. |
|
2879 ^ self |
|
2880 ]. |
|
2881 browser := self class browseClass:cls. |
|
2882 cls hasMethods ifFalse:[ |
|
2883 browser classProtocol. |
|
2884 ]. |
|
2885 sel notNil ifTrue:[ |
|
2886 browser switchToMethodNamed:sel |
|
2887 ]. |
|
2888 ] |
|
2889 |
|
2890 " |
|
2891 select 'Smalltalk allClassesDo:' and use spawn from the class menu |
|
2892 select 'Smalltalk' and use spawn from the class menu |
|
2893 " |
|
2894 ! |
|
2895 |
|
2896 classSpawnHierarchy |
|
2897 "create a new HierarchyBrowser browsing current class" |
|
2898 |
|
2899 self doClassMenuWithSelection:[:cls :sel | |
|
2900 self class browseClassHierarchy:cls |
|
2901 ] |
|
2902 ! |
|
2903 |
|
2904 classSpawnSubclasses |
|
2905 "create a new browser browsing current class's subclasses" |
|
2906 |
|
2907 |subs| |
|
2908 |
|
2909 self doClassMenuWithSelection:[:cls :sel | |
|
2910 subs := cls allSubclasses. |
|
2911 (subs notNil and:[subs size ~~ 0]) ifTrue:[ |
|
2912 self class browseClasses:subs title:('subclasses of ' , cls name) |
|
2913 ] |
|
2914 ] |
|
2915 ! |
|
2916 |
|
2917 classPrintOutFullProtocol |
|
2918 |printStream| |
|
2919 |
|
2920 self doClassMenu:[ |
|
2921 printStream := Printer new. |
|
2922 currentClass printOutFullProtocolOn:printStream. |
|
2923 printStream close |
|
2924 ] |
|
2925 ! |
|
2926 |
|
2927 classPrintOutProtocol |
|
2928 |printStream| |
|
2929 |
|
2930 self doClassMenu:[ |
|
2931 printStream := Printer new. |
|
2932 currentClass printOutProtocolOn:printStream. |
|
2933 printStream close |
|
2934 ] |
|
2935 ! |
|
2936 |
|
2937 classPrintOut |
|
2938 |printStream| |
|
2939 |
|
2940 self doClassMenu:[ |
|
2941 printStream := Printer new. |
|
2942 currentClass printOutOn:printStream. |
|
2943 printStream close |
|
2944 ] |
|
2945 ! |
|
2946 |
|
2947 classFileOut |
|
2948 self doClassMenu:[ |
|
2949 self label:('System Browser saving: ' , currentClass name). |
|
2950 Class fileOutErrorSignal handle:[:ex | |
|
2951 self warn:'cannot create: %1' with:ex parameter. |
|
2952 ex return. |
|
2953 ] do:[ |
|
2954 currentClass fileOut. |
|
2955 ]. |
|
2956 self normalLabel. |
|
2957 ] |
|
2958 ! |
|
2959 |
|
2960 classHierarchy |
|
2961 "show current classes hierarchy in codeView" |
|
2962 |
|
2963 |aStream| |
|
2964 |
|
2965 self doClassMenu:[ |
|
2966 aStream := WriteStream on:(String new:200). |
|
2967 actualClass printHierarchyOn:aStream. |
|
2968 codeView contents:(aStream contents). |
|
2969 codeView modified:false. |
|
2970 codeView acceptAction:nil. |
|
2971 codeView explainAction:nil. |
|
2972 methodListView notNil ifTrue:[ |
|
2973 methodListView deselect |
|
2974 ]. |
|
2975 aspect := #hierarchy |
|
2976 ] |
|
2977 ! |
|
2978 |
|
2979 classDefinition |
|
2980 "show class definition in codeView and setup accept-action for |
|
2981 class-definition change" |
|
2982 |
|
2983 |aStream| |
|
2984 |
|
2985 self doClassMenu:[ |
|
2986 aStream := WriteStream on:(String new:200). |
|
2987 currentClass fileOutDefinitionOn:aStream. |
|
2988 codeView contents:(aStream contents). |
|
2989 codeView modified:false. |
|
2990 codeView acceptAction:[:theCode | |
|
2991 codeView cursor:Cursor execute. |
|
2992 Object abortSignal catch:[ |
|
2993 (Compiler evaluate:theCode asString notifying:codeView) |
|
2994 isBehavior ifTrue:[ |
|
2995 codeView modified:false. |
|
2996 self classCategoryUpdate. |
|
2997 self updateClassListWithScroll:false. |
|
2998 ] |
|
2999 ]. |
|
3000 codeView cursor:Cursor normal. |
|
3001 ]. |
|
3002 codeView explainAction:nil. |
|
3003 methodListView notNil ifTrue:[ |
|
3004 methodListView deselect |
|
3005 ]. |
|
3006 aspect := #definition |
|
3007 ] |
|
3008 ! |
|
3009 |
|
3010 classClassInstVars |
|
3011 "show class instance variables in codeView and setup accept-action |
|
3012 for class-instvar-definition change" |
|
3013 |
|
3014 |s| |
|
3015 |
|
3016 self doClassMenu:[ |
|
3017 s := WriteStream on:(String new). |
|
3018 currentClass fileOutClassInstVarDefinitionOn:s. |
|
3019 codeView contents:(s contents). |
|
3020 codeView modified:false. |
|
3021 codeView acceptAction:[:theCode | |
|
3022 codeView cursor:Cursor execute. |
|
3023 Object abortSignal catch:[ |
|
3024 Compiler evaluate:theCode asString notifying:codeView. |
|
3025 codeView modified:false. |
|
3026 self updateClassList. |
|
3027 ]. |
|
3028 codeView cursor:Cursor normal. |
|
3029 ]. |
|
3030 codeView explainAction:nil. |
|
3031 methodListView notNil ifTrue:[ |
|
3032 methodListView deselect |
|
3033 ] |
|
3034 ] |
|
3035 ! |
|
3036 |
|
3037 classProtocols |
|
3038 ^ self |
|
3039 ! |
|
3040 |
|
3041 classComment |
|
3042 "show the classes comment in the codeView" |
|
3043 |
|
3044 self doClassMenu:[ |
|
3045 codeView contents:(currentClass comment). |
|
3046 codeView modified:false. |
|
3047 codeView acceptAction:[:theCode | |
|
3048 Object abortSignal catch:[ |
|
3049 currentClass comment:theCode asString. |
|
3050 codeView modified:false. |
|
3051 ] |
|
3052 ]. |
|
3053 codeView explainAction:nil. |
|
3054 methodListView notNil ifTrue:[ |
|
3055 methodListView deselect |
|
3056 ]. |
|
3057 aspect := #comment |
|
3058 ] |
|
3059 ! |
|
3060 |
|
3061 classRefs |
|
3062 self doClassMenu:[ |
|
3063 self withCursor:(Cursor questionMark) do:[ |
|
3064 self class browseReferendsOf:currentClass name asSymbol |
|
3065 ] |
|
3066 ] |
|
3067 ! |
|
3068 |
|
3069 classClassDefinitionTemplateFor:name in:cat |
|
3070 "common helper for newClass and newSubclass |
|
3071 - show a template to define class name in category cat" |
|
3072 |
|
3073 currentMethodCategory := nil. |
|
3074 currentMethod := nil. |
|
3075 |
|
3076 classListView deselect. |
|
3077 |
|
3078 fullClass ifFalse:[ |
|
3079 methodCategoryListView contents:nil. |
|
3080 methodListView contents:nil |
|
3081 ]. |
|
3082 |
|
3083 codeView contents:(self templateFor:name in:cat). |
|
3084 codeView modified:false. |
|
3085 |
|
3086 codeView acceptAction:[:theCode | |
|
3087 codeView cursor:Cursor execute. |
|
3088 Object abortSignal catch:[ |
|
3089 |cl| |
|
3090 |
|
3091 cl := (Compiler evaluate:theCode asString notifying:codeView). |
|
3092 cl isBehavior ifTrue:[ |
|
3093 codeView modified:false. |
|
3094 self classCategoryUpdate. |
|
3095 self updateClassListWithScroll:false. |
|
3096 self switchToClassNamed:(cl name) |
|
3097 ] |
|
3098 ]. |
|
3099 codeView cursor:(Cursor normal). |
|
3100 ]. |
|
3101 codeView explainAction:nil. |
|
3102 self switchToClass:nil |
|
3103 ! |
|
3104 |
|
3105 classNewClass |
|
3106 "create a class-definition prototype in codeview" |
|
3107 |
|
3108 |nm| |
|
3109 |
|
3110 currentClass notNil ifTrue:[ |
|
3111 nm := currentClass superclass name |
|
3112 ] ifFalse:[ |
|
3113 nm := 'Object' |
|
3114 ]. |
|
3115 self classClassDefinitionTemplateFor:nm in:currentClassCategory. |
|
3116 aspect := nil |
|
3117 ! |
|
3118 |
|
3119 classNewSubclass |
|
3120 "create a subclass-definition prototype in codeview" |
|
3121 |
|
3122 self doClassMenu:[ |
|
3123 self classClassDefinitionTemplateFor:(currentClass name) |
|
3124 in:(currentClass category). |
|
3125 aspect := nil |
|
3126 ] |
|
3127 ! |
|
3128 |
|
3129 renameCurrentClassTo:aString |
|
3130 "helper - do the rename" |
|
3131 |
|
3132 self doClassMenu:[ |
|
3133 |oldName oldSym newSym| |
|
3134 |
|
3135 oldName := currentClass name. |
|
3136 oldSym := oldName asSymbol. |
|
3137 " |
|
3138 currentClass setName:aString. |
|
3139 newSym := aString asSymbol. |
|
3140 Smalltalk at:oldSym put:nil. |
|
3141 Smalltalk removeKey:oldSym. |
|
3142 Smalltalk at:newSym put:currentClass. |
|
3143 " |
|
3144 " |
|
3145 currentClass renameTo:aString. |
|
3146 " |
|
3147 Smalltalk renameClass:currentClass to:aString. |
|
3148 |
|
3149 self updateClassList. |
|
3150 self updateMethodCategoryListWithScroll:false. |
|
3151 self updateMethodListWithScroll:false. |
|
3152 self withWaitCursorDo:[ |
|
3153 Transcript showCr:('searching for users of ' , oldSym); endEntry. |
|
3154 self class browseReferendsOf:oldSym warnIfNone:false |
|
3155 ] |
|
3156 ] |
|
3157 ! |
|
3158 |
|
3159 classRename |
|
3160 "launch an enterBox for new name and query user" |
|
3161 |
|
3162 |box| |
|
3163 |
|
3164 self checkClassSelected ifFalse:[^ self]. |
|
3165 box := self enterBoxTitle:(resources string:'rename %1 to:' with:currentClass name) okText:'rename'. |
|
3166 box initialText:(currentClass name). |
|
3167 box action:[:aString | self renameCurrentClassTo:aString]. |
|
3168 box showAtPointer |
|
3169 ! |
|
3170 |
|
3171 classRemove |
|
3172 "user requested remove of current class and all subclasses - |
|
3173 count subclasses and let user confirm removal." |
|
3174 |
|
3175 |count t box| |
|
3176 |
|
3177 currentClass notNil ifTrue:[ |
|
3178 count := currentClass allSubclasses size. |
|
3179 t := 'remove ' , currentClass name. |
|
3180 count ~~ 0 ifTrue:[ |
|
3181 t := t , '\(with ' , count printString , ' subclass'. |
|
3182 count ~~ 1 ifTrue:[ |
|
3183 t := t , 'es' |
|
3184 ]. |
|
3185 t := (t , ')') withCRs |
|
3186 ]. |
|
3187 box := YesNoBox |
|
3188 title:t |
|
3189 yesText:(resources at:'remove') |
|
3190 noText:(resources at:'abort'). |
|
3191 box confirm ifTrue:[ |
|
3192 "after querying user - do really remove current class |
|
3193 and all subclasses |
|
3194 " |
|
3195 self doClassMenu:[ |
|
3196 currentClass allSubclassesDo:[:aSubClass | |
|
3197 Smalltalk removeClass:aSubClass |
|
3198 ]. |
|
3199 Smalltalk removeClass:currentClass. |
|
3200 |
|
3201 self switchToClass:nil. |
|
3202 Smalltalk changed. |
|
3203 self updateClassList. |
|
3204 |
|
3205 "if it was the last in its category, update class category list" |
|
3206 " |
|
3207 classListView numberOfLines == 0 ifTrue:[ |
|
3208 self updateClassCategoryListWithScroll:false |
|
3209 ]. |
|
3210 " |
|
3211 methodCategoryListView notNil ifTrue:[methodCategoryListView contents:nil]. |
|
3212 methodListView notNil ifTrue:[methodListView contents:nil]. |
|
3213 codeView contents:nil. |
|
3214 codeView modified:false |
|
3215 ] |
|
3216 ] |
|
3217 ] |
|
3218 ! ! |
|
3219 |
|
3220 !SystemBrowser methodsFor:'variables menu'! |
|
3221 |
|
3222 enterBoxForVariableSearch:title |
|
3223 |box sel| |
|
3224 |
|
3225 box := self enterBoxForCodeSelectionTitle:title okText:'browse'. |
|
3226 variableListView notNil ifTrue:[ |
|
3227 codeView hasSelection ifFalse:[ |
|
3228 (sel := variableListView selectionValue) notNil ifTrue:[ |
|
3229 (sel startsWith:'---') ifFalse:[ |
|
3230 box initialText:sel |
|
3231 ] |
|
3232 ] |
|
3233 ] |
|
3234 ]. |
|
3235 ^ box |
|
3236 ! |
|
3237 |
|
3238 classInstVarRefsOrModsTitle:title mods:mods |
|
3239 "show an enterbox for instvar to search for" |
|
3240 |
|
3241 self doClassMenu:[ |
|
3242 |box| |
|
3243 |
|
3244 box := self enterBoxForVariableSearch:title. |
|
3245 box action:[:aString | |
|
3246 self withCursor:(Cursor questionMark) do:[ |
|
3247 self class browseInstRefsTo:aString |
|
3248 in:(Array with:currentClass) |
|
3249 modificationsOnly:mods |
|
3250 ] |
|
3251 ]. |
|
3252 box showAtPointer |
|
3253 ] |
|
3254 ! |
|
3255 |
|
3256 classInstVarRefs |
|
3257 "show an enterbox for instVar to search for" |
|
3258 |
|
3259 self classInstVarRefsOrModsTitle:'instance variable to browse references to:' |
|
3260 mods:false |
|
3261 ! |
|
3262 |
|
3263 classInstVarMods |
|
3264 "show an enterbox for instVar to search for" |
|
3265 |
|
3266 self classInstVarRefsOrModsTitle:'instance variable to browse modifications of:' |
|
3267 mods:true |
|
3268 ! |
|
3269 |
|
3270 classClassVarRefsOrModsTitle:title mods:mods |
|
3271 "show an enterbox for classVar to search for" |
|
3272 |
|
3273 self doClassMenu:[ |
|
3274 |box| |
|
3275 |
|
3276 box := self enterBoxForVariableSearch:title. |
|
3277 box action:[:aString | |
|
3278 self withCursor:(Cursor questionMark) do:[ |
|
3279 self class browseClassRefsTo:aString |
|
3280 in:(Array with:currentClass) |
|
3281 modificationsOnly:mods |
|
3282 ] |
|
3283 ]. |
|
3284 box showAtPointer |
|
3285 ] |
|
3286 ! |
|
3287 |
|
3288 classClassVarMods |
|
3289 "show an enterbox for classVar to search for" |
|
3290 |
|
3291 self classClassVarRefsOrModsTitle:'class variable to browse modifications of:' |
|
3292 mods:true |
|
3293 ! |
|
3294 |
|
3295 classClassVarRefs |
|
3296 "show an enterbox for classVar to search for" |
|
3297 |
|
3298 self classClassVarRefsOrModsTitle:'class variable to browse references to:' |
|
3299 mods:false |
|
3300 ! |
|
3301 |
|
3302 classAllClassOrInstVarRefsTitle:title access:access mods:modifications |
|
3303 "show an enterbox for instVar to search for" |
|
3304 |
|
3305 self doClassMenu:[ |
|
3306 |box| |
|
3307 |
|
3308 box := self enterBoxForVariableSearch:title. |
|
3309 box action:[:aVariableName | |
|
3310 self withCursor:(Cursor questionMark) do:[ |
|
3311 |homeClass| |
|
3312 |
|
3313 homeClass := self findClassOfVariable:aVariableName |
|
3314 accessWith:access. |
|
3315 (self class) browseInstRefsTo:aVariableName |
|
3316 under:homeClass |
|
3317 modificationsOnly:modifications |
|
3318 ] |
|
3319 ]. |
|
3320 box showAtPointer |
|
3321 ] |
|
3322 ! |
|
3323 |
|
3324 classAllInstVarRefs |
|
3325 "show an enterbox for instVar to search for" |
|
3326 |
|
3327 self classAllClassOrInstVarRefsTitle:'instance variable to browse references to:' |
|
3328 access:#instVarNames |
|
3329 mods:false |
|
3330 ! |
|
3331 |
|
3332 classAllClassVarRefs |
|
3333 "show an enterbox for classVar to search for" |
|
3334 |
|
3335 self classAllClassOrInstVarRefsTitle:'class variable to browse references to:' |
|
3336 access:#classVarNames |
|
3337 mods:false |
|
3338 ! |
|
3339 |
|
3340 classAllInstVarMods |
|
3341 "show an enterbox for instVar to search for" |
|
3342 |
|
3343 self classAllClassOrInstVarRefsTitle:'instance variable to browse modifications of:' |
|
3344 access:#instVarNames |
|
3345 mods:true |
|
3346 ! |
|
3347 |
|
3348 classAllClassVarMods |
|
3349 "show an enterbox for classVar to search for" |
|
3350 |
|
3351 self classAllClassOrInstVarRefsTitle:'class variable to browse modifications of:' |
|
3352 access:#classVarNames |
|
3353 mods:true |
|
3354 ! ! |
|
3355 |
|
3356 !SystemBrowser methodsFor:'method category menu'! |
|
3357 |
4445 |
3358 initializeMethodCategoryMenu |
4446 initializeMethodCategoryMenu |
3359 |labels| |
4447 |labels| |
3360 |
4448 |
3361 labels := resources array:#( |
4449 labels := resources array:#( |
3396 methodCategoryRemove) |
4484 methodCategoryRemove) |
3397 receiver:self |
4485 receiver:self |
3398 for:methodCategoryListView) |
4486 for:methodCategoryListView) |
3399 ! |
4487 ! |
3400 |
4488 |
3401 switchToMethodNamed:matchString |
4489 methodCategoryFindAnyMethod |
3402 |aSelector method cat index classToSearch selectors| |
4490 |box| |
3403 |
4491 |
3404 currentClass notNil ifTrue:[ |
4492 box := self enterBoxForSearchSelectorTitle:'method selector to search for:'. |
3405 showInstance ifTrue:[ |
4493 box action:[:aString | self switchToAnyMethodNamed:aString]. |
3406 classToSearch := currentClass |
4494 box showAtPointer |
3407 ] ifFalse:[ |
|
3408 classToSearch := currentClass class |
|
3409 ]. |
|
3410 selectors := classToSearch selectorArray. |
|
3411 |
|
3412 ((matchString ~= '*') and:[matchString includesMatchCharacters]) ifTrue:[ |
|
3413 index := selectors findFirst:[:element | matchString match:element] |
|
3414 ] ifFalse:[ |
|
3415 index := selectors indexOf:matchString |
|
3416 ]. |
|
3417 |
|
3418 (index ~~ 0) ifTrue:[ |
|
3419 aSelector := selectors at:index. |
|
3420 method := classToSearch methodArray at:index. |
|
3421 cat := method category. |
|
3422 cat isNil ifTrue:[cat := '* all *']. |
|
3423 methodCategoryListView selectElement:cat. |
|
3424 currentMethodCategory := cat. |
|
3425 self methodCategorySelectionChanged. |
|
3426 |
|
3427 currentMethod := classToSearch compiledMethodAt:aSelector. |
|
3428 methodListView selectElement:aSelector. |
|
3429 self methodSelectionChanged |
|
3430 ] |
|
3431 ] |
|
3432 ! |
|
3433 |
|
3434 switchToAnyMethodNamed:aString |
|
3435 |aSelector classToStartSearch aClass nm| |
|
3436 |
|
3437 aSelector := aString asSymbol. |
|
3438 currentClass isNil ifTrue:[ |
|
3439 currentClassHierarchy notNil ifTrue:[ |
|
3440 classToStartSearch := currentClassHierarchy |
|
3441 ] |
|
3442 ] ifFalse:[ |
|
3443 classToStartSearch := currentClass |
|
3444 ]. |
|
3445 classToStartSearch notNil ifTrue:[ |
|
3446 showInstance ifFalse:[ |
|
3447 classToStartSearch := classToStartSearch class |
|
3448 ]. |
|
3449 aClass := classToStartSearch whichClassImplements:aSelector. |
|
3450 aClass notNil ifTrue:[ |
|
3451 nm := aClass name. |
|
3452 showInstance ifFalse:[ |
|
3453 ((nm ~= 'Metaclass') and:[nm endsWith:'class']) ifTrue:[ |
|
3454 nm := nm copyTo:(nm size - 5) |
|
3455 ] |
|
3456 ]. |
|
3457 self switchToClassNamed:nm. |
|
3458 self switchToMethodNamed:aString |
|
3459 ] |
|
3460 ] |
|
3461 ! |
|
3462 |
|
3463 copyMethodsFromClass:aClassName |
|
3464 |class box| |
|
3465 |
|
3466 currentClass notNil ifTrue:[ |
|
3467 Symbol hasInterned:aClassName ifTrue:[:sym | |
|
3468 (Smalltalk includesKey:sym) ifTrue:[ |
|
3469 class := Smalltalk at:sym |
|
3470 ]. |
|
3471 ]. |
|
3472 class isBehavior ifFalse:[ |
|
3473 self warn:'no class named %1' with:aClassName. |
|
3474 ^ self |
|
3475 ]. |
|
3476 |
|
3477 showInstance ifFalse:[ |
|
3478 class := class class |
|
3479 ]. |
|
3480 |
|
3481 "show enterbox for category to copy from" |
|
3482 |
|
3483 box := self enterBoxTitle:'name of category to copy from (matchpattern allowed, * for all):' |
|
3484 okText:'copy'. |
|
3485 box action:[:aString | self copyMethodsFromClass:class category:aString]. |
|
3486 box showAtPointer. |
|
3487 ] |
|
3488 ! |
|
3489 |
|
3490 copyMethodsFromClass:class category:category |
|
3491 |source| |
|
3492 |
|
3493 currentClass notNil ifTrue:[ |
|
3494 "/ codeView abortAction:[^ self]. |
|
3495 Object abortSignal catch:[ |
|
3496 class methodArray do:[:aMethod | |
|
3497 (category match:aMethod category) ifTrue:[ |
|
3498 source := aMethod source. |
|
3499 codeView contents:source. |
|
3500 codeView modified:false. |
|
3501 actualClass compiler compile:source |
|
3502 forClass:actualClass |
|
3503 inCategory:aMethod category |
|
3504 notifying:codeView. |
|
3505 self updateMethodCategoryListWithScroll:false. |
|
3506 self updateMethodListWithScroll:false. |
|
3507 ] |
|
3508 ] |
|
3509 ] |
|
3510 ] |
|
3511 ! |
4495 ! |
3512 |
4496 |
3513 methodCategoryFindMethod |
4497 methodCategoryFindMethod |
3514 |box| |
4498 |box| |
3515 |
4499 |
3516 box := self enterBoxForSearchSelectorTitle:'method selector to search for:'. |
4500 box := self enterBoxForSearchSelectorTitle:'method selector to search for:'. |
3517 box action:[:aString | self switchToMethodNamed:aString]. |
4501 box action:[:aString | self switchToMethodNamed:aString]. |
3518 box showAtPointer |
|
3519 ! |
|
3520 |
|
3521 methodCategoryFindAnyMethod |
|
3522 |box| |
|
3523 |
|
3524 box := self enterBoxForSearchSelectorTitle:'method selector to search for:'. |
|
3525 box action:[:aString | self switchToAnyMethodNamed:aString]. |
|
3526 box showAtPointer |
4502 box showAtPointer |
3527 ! |
4503 ! |
3528 |
4504 |
3529 methodCategoryPrintOut |
4505 methodCategoryPrintOut |
3530 |printStream| |
4506 |printStream| |
3541 "fileOut all methods in the selected methodcategory of |
4517 "fileOut all methods in the selected methodcategory of |
3542 the current class" |
4518 the current class" |
3543 |
4519 |
3544 self checkClassSelected ifFalse:[^ self]. |
4520 self checkClassSelected ifFalse:[^ self]. |
3545 self whenMethodCategorySelected:[ |
4521 self whenMethodCategorySelected:[ |
3546 self label:('System Browser saving: ' , currentClass name , '-' , currentMethodCategory). |
4522 self busyLabel:'saving: %1' with:currentClass name , '-' , currentMethodCategory. |
3547 Class fileOutErrorSignal handle:[:ex | |
4523 Class fileOutErrorSignal handle:[:ex | |
3548 self warn:'cannot create: %1' with:ex parameter. |
4524 self warn:'cannot create: %1' with:ex parameter. |
3549 ex return. |
4525 ex return. |
3550 ] do:[ |
4526 ] do:[ |
3551 actualClass fileOutCategory:currentMethodCategory. |
4527 actualClass fileOutCategory:currentMethodCategory. |
3552 ]. |
4528 ]. |
3553 self normalLabel. |
4529 self normalLabel. |
4530 ] |
|
4531 ! |
|
4532 |
|
4533 methodCategorySpawn |
|
4534 "create a new SystemBrowser browsing current method category" |
|
4535 |
|
4536 currentMethodCategory notNil ifTrue:[ |
|
4537 self withWaitCursorDo:[ |
|
4538 self class browseClass:actualClass |
|
4539 methodCategory:currentMethodCategory |
|
4540 ] |
|
3554 ] |
4541 ] |
3555 ! |
4542 ! |
3556 |
4543 |
3557 methodCategoryFileOutAll |
4544 methodCategoryFileOutAll |
3558 "fileOut all methods in the selected methodcategory of |
4545 "fileOut all methods in the selected methodcategory of |
3579 outStream := FileStream newFileNamed:fileName. |
4566 outStream := FileStream newFileNamed:fileName. |
3580 outStream isNil ifTrue:[ |
4567 outStream isNil ifTrue:[ |
3581 ^ self warn:'cannot create: %1' with:fileName |
4568 ^ self warn:'cannot create: %1' with:fileName |
3582 ]. |
4569 ]. |
3583 |
4570 |
3584 self label:('System Browser saving: ' , currentMethodCategory). |
4571 self busyLabel:'saving: ' with:currentMethodCategory. |
3585 Class fileOutErrorSignal handle:[:ex | |
4572 Class fileOutErrorSignal handle:[:ex | |
3586 self warn:'cannot create: %1' with:ex parameter. |
4573 self warn:'cannot create: %1' with:ex parameter. |
3587 ex return |
4574 ex return |
3588 ] do:[ |
4575 ] do:[ |
3589 Smalltalk allClassesDo:[:class | |
4576 Smalltalk allBehaviorsDo:[:class | |
3590 |hasMethodsInThisCategory| |
4577 |hasMethodsInThisCategory| |
3591 |
4578 |
3592 hasMethodsInThisCategory := false. |
4579 hasMethodsInThisCategory := false. |
3593 class methodArray do:[:method | |
4580 class methodArray do:[:method | |
3594 method category = currentMethodCategory ifTrue:[ |
4581 method category = currentMethodCategory ifTrue:[ |
3614 outStream close. |
4601 outStream close. |
3615 self normalLabel. |
4602 self normalLabel. |
3616 ]. |
4603 ]. |
3617 ! |
4604 ! |
3618 |
4605 |
3619 methodCategorySpawn |
|
3620 "create a new SystemBrowser browsing current method category" |
|
3621 |
|
3622 currentMethodCategory notNil ifTrue:[ |
|
3623 self withWaitCursorDo:[ |
|
3624 self class browseClass:actualClass |
|
3625 methodCategory:currentMethodCategory |
|
3626 ] |
|
3627 ] |
|
3628 ! |
|
3629 |
|
3630 methodCategorySpawnCategory |
|
3631 "create a new SystemBrowser browsing all methods from all |
|
3632 classes with same category as current method category" |
|
3633 |
|
3634 self askAndBrowseMethodCategory:'category to browse methods:' |
|
3635 action:[:aString | |
|
3636 self class browseMethodCategory:aString |
|
3637 ] |
|
3638 ! |
|
3639 |
|
3640 newMethodCategory:aString |
|
3641 |categories| |
|
3642 |
|
3643 currentClass isNil ifTrue:[ |
|
3644 ^ self warn:'select/create a class first'. |
|
3645 ]. |
|
3646 categories := methodCategoryListView list. |
|
3647 categories isNil ifTrue:[categories := Text new]. |
|
3648 (categories includes:aString) ifFalse:[ |
|
3649 categories add:aString. |
|
3650 categories sort. |
|
3651 methodCategoryListView contents:categories |
|
3652 ]. |
|
3653 currentMethodCategory := aString. |
|
3654 self methodCategorySelectionChanged |
|
3655 ! |
|
3656 |
|
3657 methodCategoryNewCategory |
4606 methodCategoryNewCategory |
3658 "show the enter box to add a new method category" |
4607 "show the enter box to add a new method category. |
4608 Offer existing superclass categories in box to help avoiding |
|
4609 useless typing." |
|
3659 |
4610 |
3660 |someCategories existingCategories box| |
4611 |someCategories existingCategories box| |
3661 |
4612 |
3662 "a tiny little goody here ..." |
4613 actualClass notNil ifTrue:[ |
3663 showInstance ifTrue:[ |
4614 someCategories := actualClass allCategories |
3664 someCategories := #('accessing' |
|
3665 'initialization' |
|
3666 'private' |
|
3667 'printing & storing' |
|
3668 'queries' |
|
3669 'testing' |
|
3670 ) |
|
3671 ] ifFalse:[ |
4615 ] ifFalse:[ |
3672 someCategories := #( |
4616 " |
3673 'documentation' |
4617 mhmh - offer some typical categories ... |
3674 'initialization' |
4618 " |
3675 'instance creation' |
4619 showInstance ifTrue:[ |
3676 ). |
4620 someCategories := #('accessing' |
3677 ]. |
4621 'initialization' |
4622 'private' |
|
4623 'printing & storing' |
|
4624 'queries' |
|
4625 'testing' |
|
4626 ) |
|
4627 ] ifFalse:[ |
|
4628 someCategories := #( |
|
4629 'documentation' |
|
4630 'initialization' |
|
4631 'instance creation' |
|
4632 ). |
|
4633 ]. |
|
4634 ]. |
|
4635 someCategories sort. |
|
4636 |
|
4637 " |
|
4638 remove existing categories |
|
4639 " |
|
3678 existingCategories := methodCategoryListView list. |
4640 existingCategories := methodCategoryListView list. |
3679 existingCategories notNil ifTrue:[ |
4641 existingCategories notNil ifTrue:[ |
3680 someCategories := someCategories select:[:cat | (existingCategories includes:cat) not]. |
4642 someCategories := someCategories select:[:cat | (existingCategories includes:cat) not]. |
3681 ]. |
4643 ]. |
3682 |
4644 |
3683 box := self listBoxTitle:'name of new method category:' |
4645 box := self listBoxTitle:'name of new method category:' |
3684 okText:'create' |
4646 okText:'create' |
3685 list:someCategories. |
4647 list:someCategories. |
3686 box action:[:aString | self newMethodCategory:aString]. |
4648 box action:[:aString | self newMethodCategory:aString]. |
3687 box showAtPointer |
4649 box showAtPointer |
4650 |
|
4651 |
|
4652 |
|
4653 ! |
|
4654 |
|
4655 methodCategorySpawnCategory |
|
4656 "create a new SystemBrowser browsing all methods from all |
|
4657 classes with same category as current method category" |
|
4658 |
|
4659 self askAndBrowseMethodCategory:'category to browse methods:' |
|
4660 action:[:aString | |
|
4661 self class browseMethodCategory:aString |
|
4662 ] |
|
3688 ! |
4663 ! |
3689 |
4664 |
3690 methodCategoryCreateAccessMethods |
4665 methodCategoryCreateAccessMethods |
3691 "create access methods for all instvars" |
4666 "create access methods for all instvars" |
3692 |
|
3693 |source| |
|
3694 |
4667 |
3695 self checkClassSelected ifFalse:[^ self]. |
4668 self checkClassSelected ifFalse:[^ self]. |
3696 |
4669 |
3697 showInstance ifFalse:[ |
4670 showInstance ifFalse:[ |
3698 self warn:'select instance - and try again'. |
4671 self warn:'select instance - and try again'. |
3699 ^ self. |
4672 ^ self. |
3700 ]. |
4673 ]. |
3701 |
4674 |
3702 self withWaitCursorDo:[ |
4675 self withWaitCursorDo:[ |
3703 currentClass instVarNames do:[:name | |
4676 |nm names source| |
4677 |
|
4678 (variableListView notNil |
|
4679 and:[(nm := variableListView selectionValue) notNil]) ifTrue:[ |
|
4680 names := Array with:nm |
|
4681 ] ifFalse:[ |
|
4682 names := currentClass instVarNames |
|
4683 ]. |
|
4684 names do:[:name | |
|
3704 "check, if method is not already present" |
4685 "check, if method is not already present" |
3705 (currentClass implements:(name asSymbol)) ifFalse:[ |
4686 (currentClass implements:(name asSymbol)) ifFalse:[ |
3706 source := (name , '\ "return ' , name , '"\\ ^ ' , name) withCRs. |
4687 source := (name , '\ "return ' , name , '"\\ ^ ' , name) withCRs. |
3707 Compiler compile:source forClass:currentClass inCategory:'accessing'. |
4688 Compiler compile:source forClass:currentClass inCategory:'accessing'. |
3708 ] ifTrue:[ |
4689 ] ifTrue:[ |
3750 okText:(resources at:'rename'). |
4731 okText:(resources at:'rename'). |
3751 box initialText:currentMethodCategory. |
4732 box initialText:currentMethodCategory. |
3752 box action:[:aString | |
4733 box action:[:aString | |
3753 actualClass renameCategory:currentMethodCategory to:aString. |
4734 actualClass renameCategory:currentMethodCategory to:aString. |
3754 currentMethodCategory := aString. |
4735 currentMethodCategory := aString. |
3755 currentMethod := nil. |
4736 currentMethod := currentSelector := nil. |
3756 self updateMethodCategoryList. |
4737 self updateMethodCategoryList. |
3757 self updateMethodListWithScroll:false |
4738 self updateMethodListWithScroll:false |
3758 ]. |
4739 ]. |
3759 box showAtPointer |
4740 box showAtPointer |
3760 ! |
4741 ! |
3771 count := count + 1 |
4752 count := count + 1 |
3772 ] |
4753 ] |
3773 ]. |
4754 ]. |
3774 (count == 0) ifTrue:[ |
4755 (count == 0) ifTrue:[ |
3775 currentMethodCategory := nil. |
4756 currentMethodCategory := nil. |
3776 currentMethod := nil. |
4757 currentMethod := currentSelector := nil. |
3777 self updateMethodCategoryListWithScroll:false. |
4758 self updateMethodCategoryListWithScroll:false. |
3778 self updateMethodList |
4759 self updateMethodList |
3779 ] ifFalse:[ |
4760 ] ifFalse:[ |
3780 (count == 1) ifTrue:[ |
4761 (count == 1) ifTrue:[ |
3781 t := resources string:'remove %1 ?\(with 1 method)' with:currentMethodCategory |
4762 t := resources string:'remove %1 ?\(with 1 method)' with:currentMethodCategory |
3795 actualClass |
4776 actualClass |
3796 removeSelector:(actualClass selectorForMethod:aMethod) |
4777 removeSelector:(actualClass selectorForMethod:aMethod) |
3797 ] |
4778 ] |
3798 ]. |
4779 ]. |
3799 currentMethodCategory := nil. |
4780 currentMethodCategory := nil. |
3800 currentMethod := nil. |
4781 currentMethod := currentSelector := nil. |
3801 self updateMethodCategoryList. |
4782 self updateMethodCategoryList. |
3802 self updateMethodList |
4783 self updateMethodList |
3803 ] |
4784 ] |
3804 ] |
4785 ] |
3805 ] |
4786 ] |
3806 ! ! |
4787 ! ! |
3807 |
4788 |
3808 !SystemBrowser methodsFor:'method menu'! |
4789 !SystemBrowser methodsFor:'method list menu'! |
4790 |
|
4791 methodMenu |
|
4792 "return a popupmenu as appropriate for the methodList" |
|
4793 |
|
4794 |labels selectors| |
|
4795 |
|
4796 (currentMethod notNil and:[currentMethod isWrapped]) ifTrue:[ |
|
4797 labels := #( |
|
4798 'fileOut' |
|
4799 'printOut' |
|
4800 '-' |
|
4801 'SPAWN_METHOD' |
|
4802 '-' |
|
4803 'senders ...' |
|
4804 'implementors ...' |
|
4805 'globals ...' |
|
4806 " |
|
4807 'strings ...' |
|
4808 'apropos ...' |
|
4809 " |
|
4810 '-' |
|
4811 'local senders ...' |
|
4812 'local implementors ...' |
|
4813 " |
|
4814 'local strings ...' |
|
4815 " |
|
4816 '-' |
|
4817 'remove break/trace' |
|
4818 '-' |
|
4819 'new method' |
|
4820 'change category ...' |
|
4821 'remove' |
|
4822 ). |
|
4823 |
|
4824 selectors := #( |
|
4825 methodFileOut |
|
4826 methodPrintOut |
|
4827 nil |
|
4828 methodSpawn |
|
4829 nil |
|
4830 methodSenders |
|
4831 methodImplementors |
|
4832 methodGlobalReferends |
|
4833 " |
|
4834 methodStringSearch |
|
4835 methodAproposSearch |
|
4836 " |
|
4837 nil |
|
4838 methodLocalSenders |
|
4839 methodLocalImplementors |
|
4840 " |
|
4841 methodLocalStringSearch |
|
4842 " |
|
4843 nil |
|
4844 methodRemoveBreakOrTrace |
|
4845 nil |
|
4846 methodNewMethod |
|
4847 methodChangeCategory |
|
4848 methodRemove |
|
4849 ) |
|
4850 ] ifFalse:[ |
|
4851 labels := #( |
|
4852 'fileOut' |
|
4853 'printOut' |
|
4854 '-' |
|
4855 'SPAWN_METHOD' |
|
4856 '-' |
|
4857 'senders ...' |
|
4858 'implementors ...' |
|
4859 'globals ...' |
|
4860 " |
|
4861 'strings ...' |
|
4862 'apropos ...' |
|
4863 " |
|
4864 '-' |
|
4865 'local senders ...' |
|
4866 'local implementors ...' |
|
4867 " |
|
4868 'local strings ...' |
|
4869 " |
|
4870 '-' |
|
4871 'breakpoint' |
|
4872 'trace' |
|
4873 'trace sender' |
|
4874 '-' |
|
4875 'new method' |
|
4876 'change category ...' |
|
4877 'remove' |
|
4878 ). |
|
4879 selectors := #( |
|
4880 methodFileOut |
|
4881 methodPrintOut |
|
4882 nil |
|
4883 methodSpawn |
|
4884 nil |
|
4885 methodSenders |
|
4886 methodImplementors |
|
4887 methodGlobalReferends |
|
4888 " |
|
4889 methodStringSearch |
|
4890 methodAproposSearch |
|
4891 " |
|
4892 nil |
|
4893 methodLocalSenders |
|
4894 methodLocalImplementors |
|
4895 " |
|
4896 methodLocalStringSearch |
|
4897 " |
|
4898 nil |
|
4899 methodBreakPoint |
|
4900 methodTrace |
|
4901 methodTraceSender |
|
4902 nil |
|
4903 methodNewMethod |
|
4904 methodChangeCategory |
|
4905 methodRemove |
|
4906 ) |
|
4907 ]. |
|
4908 |
|
4909 ^ PopUpMenu |
|
4910 labels:(resources array:labels) |
|
4911 selectors:selectors |
|
4912 receiver:self |
|
4913 for:methodListView |
|
4914 ! |
|
3809 |
4915 |
3810 initializeMethodMenu |
4916 initializeMethodMenu |
3811 |labels| |
4917 |labels| |
4918 |
|
4919 methodListView model:self. |
|
4920 methodListView menu:#methodMenu. |
|
4921 ^ self. |
|
3812 |
4922 |
3813 labels := resources array:#( |
4923 labels := resources array:#( |
3814 'fileOut' |
4924 'fileOut' |
3815 'printOut' |
4925 'printOut' |
3816 '-' |
4926 '-' |
3869 methodRemove) |
4979 methodRemove) |
3870 receiver:self |
4980 receiver:self |
3871 for:methodListView) |
4981 for:methodListView) |
3872 ! |
4982 ! |
3873 |
4983 |
4984 methodImplementors |
|
4985 "launch an enterBox for selector to search for" |
|
4986 |
|
4987 self askAndBrowseSelectorTitle:'selector to browse implementors of:' |
|
4988 action:[:aString | |
|
4989 self class browseImplementorsOf:aString |
|
4990 ] |
|
4991 ! |
|
4992 |
|
4993 methodSenders |
|
4994 "launch an enterBox for selector to search for" |
|
4995 |
|
4996 self askAndBrowseSelectorTitle:'selector to browse senders of:' |
|
4997 action:[:aString | |
|
4998 self class browseAllCallsOn:aString |
|
4999 ] |
|
5000 ! |
|
5001 |
|
5002 methodRemove |
|
5003 "remove the current method" |
|
5004 |
|
5005 self checkMethodSelected ifFalse:[^ self]. |
|
5006 actualClass removeSelector:(actualClass selectorForMethod:currentMethod). |
|
5007 currentMethod := currentSelector := nil. |
|
5008 self updateMethodListWithScroll:false |
|
5009 ! |
|
5010 |
|
3874 initializeMethodMenu2 |
5011 initializeMethodMenu2 |
3875 |labels| |
5012 |labels| |
3876 |
5013 |
3877 methodListView isNil ifTrue:[^ self]. |
5014 methodListView isNil ifTrue:[^ self]. |
5015 ^self. |
|
3878 labels := resources array:#( |
5016 labels := resources array:#( |
3879 'fileOut' |
5017 'fileOut' |
3880 'printOut' |
5018 'printOut' |
3881 '-' |
5019 '-' |
3882 'SPAWN_METHOD' |
5020 'SPAWN_METHOD' |
3930 methodRemove) |
5068 methodRemove) |
3931 receiver:self |
5069 receiver:self |
3932 for:methodListView) |
5070 for:methodListView) |
3933 ! |
5071 ! |
3934 |
5072 |
5073 methodLocalSenders |
|
5074 "launch an enterBox for selector to search for in current class & subclasses" |
|
5075 |
|
5076 self checkClassSelected ifFalse:[^ self]. |
|
5077 self askAndBrowseSelectorTitle:'selector to browse local senderss of:' |
|
5078 action:[:aString | |
|
5079 self class browseCallsOn:aString under:currentClass |
|
5080 ] |
|
5081 ! |
|
5082 |
|
3935 methodPrintOut |
5083 methodPrintOut |
3936 "print out the current method" |
5084 "print out the current method" |
3937 |
5085 |
3938 |printStream| |
5086 |printStream| |
3939 |
5087 |
3940 self checkMethodSelected ifFalse:[^ self]. |
5088 self checkMethodSelected ifFalse:[^ self]. |
3941 |
5089 |
3942 printStream := Printer new. |
5090 printStream := Printer new. |
3943 actualClass printOutSource:currentMethod source on:printStream. |
5091 actualClass printOutSource:(currentMethod source) on:printStream. |
3944 printStream close |
5092 printStream close |
5093 ! |
|
5094 |
|
5095 methodLocalImplementors |
|
5096 "launch an enterBox for selector to search for" |
|
5097 |
|
5098 self checkClassSelected ifFalse:[^ self]. |
|
5099 self askAndBrowseSelectorTitle:'selector to browse local implementors of:' |
|
5100 action:[:aString | |
|
5101 self class browseImplementorsOf:aString under:currentClass |
|
5102 ] |
|
5103 ! |
|
5104 |
|
5105 methodGlobalReferends |
|
5106 "launch an enterBox for global symbol to search for" |
|
5107 |
|
5108 self enterBoxForBrowseTitle:'global variable to browse users of:' |
|
5109 action:[:aString | |
|
5110 self class browseReferendsOf:aString asSymbol |
|
5111 ] |
|
5112 ! |
|
5113 |
|
5114 methodSpawn |
|
5115 "create a new SystemBrowser browsing current method, |
|
5116 or if the current selection is of the form 'class>>selector', spawan |
|
5117 a browser on that method." |
|
5118 |
|
5119 |s sel selSymbol clsName clsSymbol cls meta isMeta w sep| |
|
5120 |
|
5121 classMethodListView notNil ifTrue:[ |
|
5122 s := classMethodListView selectionValue. |
|
5123 clsName := self classFromClassMethodString:s. |
|
5124 sel := self selectorFromClassMethodString:s. |
|
5125 isMeta := false |
|
5126 ]. |
|
5127 |
|
5128 self extractClassAndSelectorFromSelectionInto:[:c :s :m | |
|
5129 clsName := c. |
|
5130 sel := s. |
|
5131 isMeta := m |
|
5132 ]. |
|
5133 |
|
5134 (sel notNil and:[clsName notNil]) ifTrue:[ |
|
5135 (clsName knownAsSymbol and:[sel knownAsSymbol]) ifTrue:[ |
|
5136 clsSymbol := clsName asSymbol. |
|
5137 (Smalltalk includesKey:clsSymbol) ifTrue:[ |
|
5138 cls := Smalltalk at:clsSymbol. |
|
5139 isMeta ifTrue:[ |
|
5140 cls := cls class |
|
5141 ]. |
|
5142 cls isBehavior ifFalse:[ |
|
5143 cls := cls class |
|
5144 ]. |
|
5145 cls isBehavior ifTrue:[ |
|
5146 selSymbol := sel asSymbol. |
|
5147 self withWaitCursorDo:[ |
|
5148 (cls implements:selSymbol) ifFalse:[ |
|
5149 cls := cls class. |
|
5150 ]. |
|
5151 (cls implements:selSymbol) ifTrue:[ |
|
5152 self class browseClass:cls selector:selSymbol. |
|
5153 ^ self |
|
5154 ]. |
|
5155 w := ' does not implement #' , sel |
|
5156 ] |
|
5157 ] ifFalse:[ |
|
5158 w := ' is not a class' |
|
5159 ] |
|
5160 ] ifFalse:[ |
|
5161 w := ' is unknown' |
|
5162 ] |
|
5163 ] ifFalse:[ |
|
5164 w := ' and/or ' , sel , ' are unknown' |
|
5165 ]. |
|
5166 self warn:(clsName , w). |
|
5167 ^ self |
|
5168 ]. |
|
5169 |
|
5170 self checkMethodSelected ifFalse:[ |
|
5171 self warn:'select a method first'. |
|
5172 ^ self |
|
5173 ]. |
|
5174 |
|
5175 self withWaitCursorDo:[ |
|
5176 w := currentMethod who. |
|
5177 self class browseClass:(w at:1) selector:(w at:2) |
|
5178 ] |
|
3945 ! |
5179 ! |
3946 |
5180 |
3947 methodFileOut |
5181 methodFileOut |
3948 "file out the current method" |
5182 "file out the current method" |
3949 |
5183 |
3950 self checkMethodSelected ifFalse:[^ self]. |
5184 self checkMethodSelected ifFalse:[^ self]. |
3951 |
5185 |
3952 self label:'System Browser saving'. |
5186 self busyLabel:'saving:' with:currentSelector. |
3953 Class fileOutErrorSignal handle:[:ex | |
5187 Class fileOutErrorSignal handle:[:ex | |
3954 self warn:'cannot create: %1' with:ex parameter. |
5188 self warn:'cannot create: %1' with:ex parameter. |
3955 ex return |
5189 ex return |
3956 ] do:[ |
5190 ] do:[ |
3957 actualClass fileOutMethod:currentMethod. |
5191 actualClass fileOutMethod:currentMethod. |
3958 ]. |
5192 ]. |
3959 self normalLabel. |
5193 self normalLabel. |
3960 ! |
5194 ! |
3961 |
5195 |
3962 methodImplementors |
5196 methodChangeCategory |
3963 "launch an enterBox for selector to search for" |
5197 "move the current method into another category - |
3964 |
5198 nothing done here, but a query for the new category. |
3965 self askAndBrowseSelectorTitle:'selector to browse implementors of:' |
5199 Remember the last category, to allow faster category change of a group of methods." |
3966 action:[:aString | |
5200 |
3967 self class browseImplementorsOf:aString |
5201 |box txt| |
3968 ] |
5202 |
3969 ! |
5203 self checkMethodSelected ifFalse:[^ self]. |
3970 |
5204 |
3971 methodLocalImplementors |
5205 actualClass isNil ifTrue:[ |
3972 "launch an enterBox for selector to search for" |
5206 box := self enterBoxTitle:'' okText:'change'. |
3973 |
5207 ] ifFalse:[ |
3974 self checkClassSelected ifFalse:[^ self]. |
5208 |someCategories| |
3975 self askAndBrowseSelectorTitle:'selector to browse local implementors of:' |
5209 |
3976 action:[:aString | |
5210 someCategories := actualClass categories sort. |
3977 self class browseImplementorsOf:aString under:currentClass |
5211 box := self listBoxTitle:'' okText:'change' list:someCategories. |
3978 ] |
5212 ]. |
3979 ! |
5213 box title:('change category from ''' , currentMethod category , ''' to:'). |
3980 |
5214 lastMethodCategory isNil ifTrue:[ |
3981 methodSenders |
5215 txt := currentMethod category. |
3982 "launch an enterBox for selector to search for" |
5216 ] ifFalse:[ |
3983 |
5217 txt := lastMethodCategory |
3984 self askAndBrowseSelectorTitle:'selector to browse senders of:' |
5218 ]. |
3985 action:[:aString | |
5219 box initialText:txt. |
3986 self class browseAllCallsOn:aString |
5220 box action:[:aString | |
3987 ] |
5221 lastMethodCategory := aString. |
3988 ! |
5222 |
3989 |
5223 currentMethod category:aString asSymbol. |
3990 methodLocalSenders |
5224 currentClass changed. |
3991 "launch an enterBox for selector to search for in current class & subclasses" |
5225 currentMethod changed:#category. |
3992 |
5226 currentClass addChangeRecordForMethodCategory:currentMethod category:aString. |
3993 self checkClassSelected ifFalse:[^ self]. |
5227 self updateMethodCategoryListWithScroll:false. |
3994 self askAndBrowseSelectorTitle:'selector to browse local senderss of:' |
5228 self updateMethodListWithScroll:false |
3995 action:[:aString | |
5229 ]. |
3996 self class browseCallsOn:aString under:currentClass |
5230 box showAtPointer |
3997 ] |
|
3998 ! |
|
3999 |
|
4000 methodGlobalReferends |
|
4001 "launch an enterBox for global symbol to search for" |
|
4002 |
|
4003 self enterBoxForBrowseTitle:'global variable to browse users of:' |
|
4004 action:[:aString | |
|
4005 self class browseReferendsOf:aString asSymbol |
|
4006 ] |
|
4007 ! |
5231 ! |
4008 |
5232 |
4009 methodStringSearch |
5233 methodStringSearch |
4010 "launch an enterBox for (sub)-string to search for" |
5234 "launch an enterBox for (sub)-string to search for" |
4011 |
5235 |
4032 action:[:aString | |
5256 action:[:aString | |
4033 self class aproposSearch:aString |
5257 self class aproposSearch:aString |
4034 ] |
5258 ] |
4035 ! |
5259 ! |
4036 |
5260 |
4037 methodSpawn |
|
4038 "create a new SystemBrowser browsing current method, |
|
4039 or if the current selection is of the form 'class>>selector', spwan |
|
4040 a browser on that method." |
|
4041 |
|
4042 |s sel selSymbol clsName clsSymbol cls meta browseMeta w sep| |
|
4043 |
|
4044 sel := codeView selection. |
|
4045 sel notNil ifTrue:[ |
|
4046 sel := sel asString withoutSeparators. |
|
4047 ('*>>*' match:sel) ifTrue:[ |
|
4048 sep := $> |
|
4049 ] ifFalse:[ |
|
4050 ('* *' match:sel) ifTrue:[ |
|
4051 sep := Character space |
|
4052 ] |
|
4053 ]. |
|
4054 sep notNil ifTrue:[ |
|
4055 " |
|
4056 extract class/sel from selection |
|
4057 " |
|
4058 s := ReadStream on:sel. |
|
4059 clsName := s upTo:sep. |
|
4060 [s peek == sep] whileTrue:[s next]. |
|
4061 sel := s upToEnd. |
|
4062 |
|
4063 (clsName endsWith:'class') ifTrue:[ |
|
4064 browseMeta := true. |
|
4065 clsName := clsName copyTo:(clsName size - 5) |
|
4066 ] ifFalse:[ |
|
4067 browseMeta := false |
|
4068 ]. |
|
4069 (clsName knownAsSymbol and:[sel knownAsSymbol]) ifTrue:[ |
|
4070 clsSymbol := clsName asSymbol. |
|
4071 (Smalltalk includesKey:clsSymbol) ifTrue:[ |
|
4072 cls := Smalltalk at:clsSymbol. |
|
4073 browseMeta ifTrue:[ |
|
4074 cls := cls class |
|
4075 ]. |
|
4076 cls isBehavior ifFalse:[ |
|
4077 cls := cls class |
|
4078 ]. |
|
4079 cls isBehavior ifTrue:[ |
|
4080 selSymbol := sel asSymbol. |
|
4081 self withWaitCursorDo:[ |
|
4082 (cls implements:selSymbol) ifTrue:[ |
|
4083 self class browseClass:cls selector:selSymbol. |
|
4084 ^ self |
|
4085 ] ifFalse:[ |
|
4086 meta := cls class. |
|
4087 (meta implements:selSymbol) ifTrue:[ |
|
4088 self class browseClass:meta selector:selSymbol. |
|
4089 ^ self |
|
4090 ]. |
|
4091 w := ' does not implement #' , sel |
|
4092 ] |
|
4093 ] |
|
4094 ] ifFalse:[ |
|
4095 w := ' is not a class' |
|
4096 ] |
|
4097 ] ifFalse:[ |
|
4098 w := ' is unknown' |
|
4099 ] |
|
4100 ] ifFalse:[ |
|
4101 w := ' and/or ' , sel , ' is unknown' |
|
4102 ]. |
|
4103 self warn:(clsName , w). |
|
4104 ^ self |
|
4105 ]. |
|
4106 ]. |
|
4107 |
|
4108 self checkMethodSelected ifFalse:[^ self]. |
|
4109 self withWaitCursorDo:[ |
|
4110 self class browseClass:actualClass |
|
4111 selector:(actualClass selectorForMethod:currentMethod) |
|
4112 ] |
|
4113 ! |
|
4114 |
|
4115 methodNewMethod |
5261 methodNewMethod |
4116 "prepare for definition of a new method - put a template into |
5262 "prepare for definition of a new method - put a template into |
4117 code view and define accept-action to compile it" |
5263 code view and define accept-action to compile it" |
4118 |
5264 |
4119 currentClass isNil ifTrue:[ |
5265 currentClass isNil ifTrue:[ |
4121 ]. |
5267 ]. |
4122 currentMethodCategory isNil ifTrue:[ |
5268 currentMethodCategory isNil ifTrue:[ |
4123 ^ self warn:'select/create a method category first'. |
5269 ^ self warn:'select/create a method category first'. |
4124 ]. |
5270 ]. |
4125 |
5271 |
4126 currentMethod := nil. |
5272 currentMethod := currentSelector := nil. |
4127 |
5273 |
4128 methodListView deselect. |
5274 methodListView deselect. |
4129 codeView contents:(self template). |
5275 codeView contents:(self template). |
4130 codeView modified:false. |
5276 codeView modified:false. |
4131 |
5277 |
4132 codeView acceptAction:[:theCode | |
5278 self setAcceptAndExplainActionsForMethod. |
4133 codeView cursor:Cursor execute. |
5279 ! |
4134 Object abortSignal catch:[ |
5280 |
4135 actualClass compiler compile:theCode asString |
5281 methodTrace |
4136 forClass:actualClass |
5282 "turn on tracing of the current method" |
4137 inCategory:currentMethodCategory |
5283 |
4138 notifying:codeView. |
5284 |sel| |
4139 codeView modified:false. |
5285 |
4140 self updateMethodListWithScroll:false. |
5286 currentClass notNil ifTrue:[ |
4141 ]. |
5287 currentSelector notNil ifTrue:[ |
4142 codeView cursor:Cursor normal. |
5288 currentMethod := actualClass compiledMethodAt:currentSelector |
4143 ]. |
5289 ] |
4144 codeView explainAction:[:theCode :theSelection | |
5290 ]. |
4145 self showExplanation:(Explainer explain:theSelection |
5291 |
4146 in:theCode |
5292 (currentMethod notNil and:[currentMethod isWrapped not]) |
4147 forClass:actualClass) |
5293 ifTrue:[ |
4148 ] |
5294 currentMethod := MessageTracer traceMethod:currentMethod. |
4149 ! |
5295 sel := methodListView selection. |
4150 |
5296 self updateMethodListWithScroll:false. |
4151 methodRemove |
5297 methodListView selection:sel. |
4152 "remove the current method" |
5298 currentClass changed:#methodDictionary with:currentSelector. |
4153 |
5299 ] |
4154 self checkMethodSelected ifFalse:[^ self]. |
|
4155 actualClass removeSelector:(actualClass selectorForMethod:currentMethod). |
|
4156 self updateMethodListWithScroll:false |
|
4157 ! |
|
4158 |
|
4159 methodChangeCategory |
|
4160 "move the current method into another category - |
|
4161 nothing done here, but a query for the new category. |
|
4162 Remember the last category, to allow faster category change of a group of methods." |
|
4163 |
|
4164 |box txt| |
|
4165 |
|
4166 self checkMethodSelected ifFalse:[^ self]. |
|
4167 |
|
4168 box := self enterBoxTitle:('change category from ' , currentMethod category , ' to:') |
|
4169 okText:'change'. |
|
4170 lastMethodCategory isNil ifTrue:[ |
|
4171 txt := currentMethod category. |
|
4172 ] ifFalse:[ |
|
4173 txt := lastMethodCategory |
|
4174 ]. |
|
4175 box initialText:txt. |
|
4176 box action:[:aString | |
|
4177 lastMethodCategory := aString. |
|
4178 |
|
4179 currentMethod category:aString asSymbol. |
|
4180 currentClass changed. |
|
4181 self updateMethodCategoryListWithScroll:false. |
|
4182 self updateMethodListWithScroll:false |
|
4183 ]. |
|
4184 box showAtPointer |
|
4185 ! |
5300 ! |
4186 |
5301 |
4187 methodRemoveBreakOrTrace |
5302 methodRemoveBreakOrTrace |
4188 "turn off tracing of the current method" |
5303 "turn off tracing of the current method" |
4189 |
5304 |
4190 |sel| |
5305 |sel| |
4191 |
5306 |
4192 currentMethod notNil ifTrue:[ |
5307 (currentMethod notNil and:[currentMethod isWrapped]) |
4193 currentMethod isWrapped ifTrue:[ |
5308 ifTrue:[ |
4194 currentMethod := MessageTracer unwrapMethod:currentMethod. |
5309 currentMethod := MessageTracer unwrapMethod:currentMethod. |
4195 sel := methodListView selection. |
5310 sel := methodListView selection. |
4196 self updateMethodListWithScroll:false. |
5311 self updateMethodListWithScroll:false. |
4197 methodListView selection:sel. |
5312 methodListView selection:sel. |
4198 self initializeMethodMenu |
5313 currentClass changed:#methodDictionary with:currentSelector. |
4199 ]. |
|
4200 ] |
5314 ] |
4201 ! |
5315 ! |
4202 |
5316 |
4203 methodBreakPoint |
5317 methodBreakPoint |
4204 "set a breakpoint on the current method" |
5318 "set a breakpoint on the current method" |
4214 methodListView selection:sel |
5328 methodListView selection:sel |
4215 ]. |
5329 ]. |
4216 ] |
5330 ] |
4217 ! |
5331 ! |
4218 |
5332 |
4219 methodTrace |
|
4220 "turn on tracing of the current method" |
|
4221 |
|
4222 |sel| |
|
4223 |
|
4224 currentMethod notNil ifTrue:[ |
|
4225 currentMethod isWrapped ifFalse:[ |
|
4226 currentMethod := MessageTracer traceMethod:currentMethod. |
|
4227 self initializeMethodMenu2. |
|
4228 sel := methodListView selection. |
|
4229 self updateMethodListWithScroll:false. |
|
4230 methodListView selection:sel |
|
4231 ]. |
|
4232 ] |
|
4233 ! |
|
4234 |
|
4235 methodTraceSender |
5333 methodTraceSender |
4236 "turn on tracing of the current method" |
5334 "turn on tracing of the current method" |
4237 |
5335 |
4238 |sel| |
5336 |sel| |
4239 |
5337 |
4240 currentMethod notNil ifTrue:[ |
5338 (currentMethod notNil and:[currentMethod isWrapped not]) |
4241 currentMethod isWrapped ifFalse:[ |
5339 ifTrue:[ |
4242 currentMethod := MessageTracer traceMethodSender:currentMethod. |
5340 currentMethod := MessageTracer traceMethodSender:currentMethod. |
4243 self initializeMethodMenu2. |
5341 sel := methodListView selection. |
4244 sel := methodListView selection. |
5342 self updateMethodListWithScroll:false. |
4245 self updateMethodListWithScroll:false. |
5343 methodListView selection:sel. |
4246 methodListView selection:sel |
5344 currentClass changed:#methodDictionary with:currentSelector. |
4247 ]. |
5345 ] |
4248 ] |
5346 ! |
5347 |
|
5348 methodMenuForWrappedMethod |
|
5349 |labels| |
|
5350 |
|
5351 labels := resources array:#( |
|
5352 'fileOut' |
|
5353 'printOut' |
|
5354 '-' |
|
5355 'SPAWN_METHOD' |
|
5356 '-' |
|
5357 'senders ...' |
|
5358 'implementors ...' |
|
5359 'globals ...' |
|
5360 " |
|
5361 'strings ...' |
|
5362 'apropos ...' |
|
5363 " |
|
5364 '-' |
|
5365 'local senders ...' |
|
5366 'local implementors ...' |
|
5367 " |
|
5368 'local strings ...' |
|
5369 " |
|
5370 '-' |
|
5371 'remove break/trace' |
|
5372 '-' |
|
5373 'new method' |
|
5374 'change category ...' |
|
5375 'remove'). |
|
5376 |
|
5377 ^ PopUpMenu |
|
5378 labels:labels |
|
5379 selectors:#(methodFileOut |
|
5380 methodPrintOut |
|
5381 nil |
|
5382 methodSpawn |
|
5383 nil |
|
5384 methodSenders |
|
5385 methodImplementors |
|
5386 methodGlobalReferends |
|
5387 " |
|
5388 methodStringSearch |
|
5389 methodAproposSearch |
|
5390 " |
|
5391 nil |
|
5392 methodLocalSenders |
|
5393 methodLocalImplementors |
|
5394 " |
|
5395 methodLocalStringSearch |
|
5396 " |
|
5397 nil |
|
5398 methodRemoveBreakOrTrace |
|
5399 nil |
|
5400 methodNewMethod |
|
5401 methodChangeCategory |
|
5402 methodRemove) |
|
5403 receiver:self |
|
5404 for:methodListView |
|
4249 ! ! |
5405 ! ! |
4250 |
5406 |
4251 !SystemBrowser methodsFor:'class-method menu'! |
5407 !SystemBrowser methodsFor:'variable list menu'! |
5408 |
|
5409 initializeVariableListMenu |
|
5410 |varMenu| |
|
5411 |
|
5412 varMenu := (PopUpMenu labels:(resources array:#( |
|
5413 'instvar refs ...' |
|
5414 'classvar refs ...' |
|
5415 'all instvar refs ...' |
|
5416 'all classvar refs ...' |
|
5417 '-' |
|
5418 'instvar mods ...' |
|
5419 'classvar mods ...' |
|
5420 'all instvar mods ...' |
|
5421 'all classvar mods ...' |
|
5422 )) |
|
5423 selectors:#( |
|
5424 instVarRefs |
|
5425 classVarRefs |
|
5426 allInstVarRefs |
|
5427 allClassVarRefs |
|
5428 nil |
|
5429 instVarMods |
|
5430 classVarMods |
|
5431 allInstVarMods |
|
5432 allClassVarMods |
|
5433 ) |
|
5434 receiver:self |
|
5435 for:self). |
|
5436 |
|
5437 variableListView isNil ifTrue:[ |
|
5438 classListView notNil ifTrue:[ |
|
5439 |menu| |
|
5440 |
|
5441 menu := classListView middleButtonMenu. |
|
5442 menu addLabel:(resources string:'variable search') |
|
5443 selector:#variables |
|
5444 before:#classRefs. |
|
5445 menu subMenuAt:#variables put:varMenu. |
|
5446 ] |
|
5447 ] ifFalse:[ |
|
5448 variableListView middleButtonMenu:varMenu |
|
5449 ] |
|
5450 |
|
5451 ! |
|
5452 |
|
5453 variableSelection:lineNr |
|
5454 "variable selection changed" |
|
5455 |
|
5456 |name idx| |
|
5457 |
|
5458 name := variableListView selectionValue. |
|
5459 name isNil ifTrue:[ |
|
5460 self unhilightMethodCategories. |
|
5461 self unhilightMethods. |
|
5462 self autoSearch:nil. |
|
5463 ^ self |
|
5464 ]. |
|
5465 |
|
5466 " |
|
5467 first, check if the selected variable is really the one |
|
5468 we get - reselect if its hidden (for example, a class variable |
|
5469 with the same name could be defined in a subclass) |
|
5470 " |
|
5471 idx := variableListView list findLast:[:entry | entry = name]. |
|
5472 idx ~~ lineNr ifTrue:[ |
|
5473 "select it - user will see whats going on" |
|
5474 variableListView selection:idx |
|
5475 ]. |
|
5476 |
|
5477 "search for methods in the current category, which access the selected |
|
5478 variable, and highlight them" |
|
5479 |
|
5480 self hilightMethodsInMethodCategoryList:true inMethodList:true. |
|
5481 self autoSearch:name. |
|
5482 |
|
5483 |
|
5484 ! |
|
5485 |
|
5486 enterBoxForVariableSearch:title |
|
5487 |box sel| |
|
5488 |
|
5489 box := self enterBoxForCodeSelectionTitle:title okText:'browse'. |
|
5490 variableListView notNil ifTrue:[ |
|
5491 codeView hasSelection ifFalse:[ |
|
5492 (sel := variableListView selectionValue) notNil ifTrue:[ |
|
5493 (sel startsWith:'---') ifFalse:[ |
|
5494 box initialText:sel |
|
5495 ] |
|
5496 ] |
|
5497 ] |
|
5498 ]. |
|
5499 ^ box |
|
5500 ! |
|
5501 |
|
5502 allClassOrInstVarRefsTitle:title access:access mods:modifications |
|
5503 "show an enterbox for instVar to search for" |
|
5504 |
|
5505 self doClassMenu:[ |
|
5506 |box| |
|
5507 |
|
5508 box := self enterBoxForVariableSearch:title. |
|
5509 box action:[:aVariableName | |
|
5510 self withCursor:(Cursor questionMark) do:[ |
|
5511 |homeClass| |
|
5512 |
|
5513 homeClass := self findClassOfVariable:aVariableName |
|
5514 accessWith:access. |
|
5515 (self class) browseInstRefsTo:aVariableName |
|
5516 under:homeClass |
|
5517 modificationsOnly:modifications |
|
5518 ] |
|
5519 ]. |
|
5520 box showAtPointer |
|
5521 ] |
|
5522 ! |
|
5523 |
|
5524 instVarRefsOrModsTitle:title mods:mods |
|
5525 "show an enterbox for instvar to search for" |
|
5526 |
|
5527 self doClassMenu:[ |
|
5528 |box| |
|
5529 |
|
5530 box := self enterBoxForVariableSearch:title. |
|
5531 box action:[:aString | |
|
5532 self withCursor:(Cursor questionMark) do:[ |
|
5533 self class browseInstRefsTo:aString |
|
5534 in:(Array with:currentClass) |
|
5535 modificationsOnly:mods |
|
5536 ] |
|
5537 ]. |
|
5538 box showAtPointer |
|
5539 ] |
|
5540 ! |
|
5541 |
|
5542 allClassVarMods |
|
5543 "show an enterbox for classVar to search for" |
|
5544 |
|
5545 self allClassOrInstVarRefsTitle:'class variable to browse modifications of:' |
|
5546 access:#classVarNames |
|
5547 mods:true |
|
5548 ! |
|
5549 |
|
5550 instVarMods |
|
5551 "show an enterbox for instVar to search for" |
|
5552 |
|
5553 self instVarRefsOrModsTitle:'instance variable to browse modifications of:' |
|
5554 mods:true |
|
5555 ! |
|
5556 |
|
5557 instVarRefs |
|
5558 "show an enterbox for instVar to search for" |
|
5559 |
|
5560 self instVarRefsOrModsTitle:'instance variable to browse references to:' |
|
5561 mods:false |
|
5562 ! |
|
5563 |
|
5564 classVarRefsOrModsTitle:title mods:mods |
|
5565 "show an enterbox for classVar to search for" |
|
5566 |
|
5567 self doClassMenu:[ |
|
5568 |box| |
|
5569 |
|
5570 box := self enterBoxForVariableSearch:title. |
|
5571 box action:[:aString | |
|
5572 self withCursor:(Cursor questionMark) do:[ |
|
5573 self class browseClassRefsTo:aString |
|
5574 in:(Array with:currentClass) |
|
5575 modificationsOnly:mods |
|
5576 ] |
|
5577 ]. |
|
5578 box showAtPointer |
|
5579 ] |
|
5580 ! |
|
5581 |
|
5582 allInstVarRefs |
|
5583 "show an enterbox for instVar to search for" |
|
5584 |
|
5585 self allClassOrInstVarRefsTitle:'instance variable to browse references to:' |
|
5586 access:#instVarNames |
|
5587 mods:false |
|
5588 ! |
|
5589 |
|
5590 classVarRefs |
|
5591 "show an enterbox for classVar to search for" |
|
5592 |
|
5593 self classVarRefsOrModsTitle:'class variable to browse references to:' |
|
5594 mods:false |
|
5595 ! |
|
5596 |
|
5597 classVarMods |
|
5598 "show an enterbox for classVar to search for" |
|
5599 |
|
5600 self classVarRefsOrModsTitle:'class variable to browse modifications of:' |
|
5601 mods:true |
|
5602 ! |
|
5603 |
|
5604 allInstVarMods |
|
5605 "show an enterbox for instVar to search for" |
|
5606 |
|
5607 self allClassOrInstVarRefsTitle:'instance variable to browse modifications of:' |
|
5608 access:#instVarNames |
|
5609 mods:true |
|
5610 ! |
|
5611 |
|
5612 allClassVarRefs |
|
5613 "show an enterbox for classVar to search for" |
|
5614 |
|
5615 self allClassOrInstVarRefsTitle:'class variable to browse references to:' |
|
5616 access:#classVarNames |
|
5617 mods:false |
|
5618 ! ! |
|
5619 |
|
5620 !SystemBrowser methodsFor:'class-method list menu'! |
|
4252 |
5621 |
4253 initializeClassMethodMenu |
5622 initializeClassMethodMenu |
4254 |labels| |
5623 |labels| |
4255 |
5624 |
4256 labels := resources array:#( |
5625 labels := resources array:#( |
4327 ^ self warn:'cannot create: %1' with:fileName |
5696 ^ self warn:'cannot create: %1' with:fileName |
4328 ]. |
5697 ]. |
4329 self withWaitCursorDo:[ |
5698 self withWaitCursorDo:[ |
4330 list := classMethodListView list. |
5699 list := classMethodListView list. |
4331 list do:[:line | |
5700 list do:[:line | |
4332 self label:('System Browser writing: ' , line). |
5701 self busyLabel:'writing: ' with:line. |
4333 |
5702 |
4334 classString := self classFromClassMethodString:line. |
5703 classString := self classFromClassMethodString:line. |
4335 selectorString := self selectorFromClassMethodString:line. |
5704 selectorString := self selectorFromClassMethodString:line. |
4336 |
5705 |
4337 ((classString ~= 'Metaclass') and:[classString endsWith:'class']) ifTrue:[ |
5706 ((classString ~= 'Metaclass') and:[classString endsWith:'class']) ifTrue:[ |
4352 box yesText:'continue' noText:'abort'. |
5721 box yesText:'continue' noText:'abort'. |
4353 (box confirm:('fileOut error: ' , ex errorString , |
5722 (box confirm:('fileOut error: ' , ex errorString , |
4354 '\\continue anyway ?') withCRs) ifTrue:[ |
5723 '\\continue anyway ?') withCRs) ifTrue:[ |
4355 ex proceed |
5724 ex proceed |
4356 ]. |
5725 ]. |
4357 self label:'System Browser'. |
5726 self normalLabel. |
4358 ^ self |
5727 ^ self |
4359 ] do:[ |
5728 ] do:[ |
4360 cls fileOutMethod:mth on:outStream. |
5729 cls fileOutMethod:mth on:outStream. |
4361 ] |
5730 ] |
4362 ] |
5731 ] |
4365 self normalLabel. |
5734 self normalLabel. |
4366 ] |
5735 ] |
4367 ] |
5736 ] |
4368 ! ! |
5737 ! ! |
4369 |
5738 |
4370 !SystemBrowser methodsFor:'dependencies'! |
5739 SystemBrowser initialize! |
4371 |
|
4372 update |
|
4373 "handle changes from other browsers" |
|
4374 |
|
4375 |oldClassCategory oldClassName oldMethodCategory oldMethod oldSelector| |
|
4376 |
|
4377 self updateClassCategoryListWithScroll:false. |
|
4378 " |
|
4379 self updateClassListWithScroll:false. |
|
4380 " |
|
4381 ^ self. |
|
4382 |
|
4383 oldClassCategory := currentClassCategory. |
|
4384 currentClass notNil ifTrue:[ |
|
4385 oldClassName := currentClass name |
|
4386 ]. |
|
4387 oldMethodCategory := currentMethodCategory. |
|
4388 oldMethod := currentMethod. |
|
4389 methodListView notNil ifTrue:[ |
|
4390 oldMethod notNil ifTrue:[ |
|
4391 oldSelector := methodListView selectionValue |
|
4392 ] |
|
4393 ]. |
|
4394 |
|
4395 classCategoryListView notNil ifTrue:[ |
|
4396 classCategoryListView setContents:(self listOfAllClassCategories). |
|
4397 oldClassCategory notNil ifTrue:[ |
|
4398 classCategoryListView selectElement:oldClassCategory |
|
4399 ]. |
|
4400 classCategoryListView selection isNil ifTrue:[ |
|
4401 currentClassCategory := nil. |
|
4402 self switchToClass:nil. |
|
4403 oldClassName := nil |
|
4404 ] |
|
4405 ]. |
|
4406 classListView notNil ifTrue:[ |
|
4407 self updateClassListWithScroll:false. |
|
4408 oldClassName notNil ifTrue:[ |
|
4409 classListView selectElement:oldClassName |
|
4410 ]. |
|
4411 classListView selection isNil ifTrue:[ |
|
4412 self switchToClass:nil. |
|
4413 currentMethodCategory := nil. |
|
4414 oldMethodCategory := nil |
|
4415 ] |
|
4416 ]. |
|
4417 methodCategoryListView notNil ifTrue:[ |
|
4418 self updateMethodCategoryListWithScroll:false. |
|
4419 oldMethodCategory notNil ifTrue:[ |
|
4420 methodCategoryListView selectElement:oldMethodCategory |
|
4421 ]. |
|
4422 methodCategoryListView selection isNil ifTrue:[ |
|
4423 currentMethodCategory := nil. |
|
4424 currentMethod := nil. |
|
4425 oldSelector := nil |
|
4426 ] |
|
4427 ]. |
|
4428 methodListView notNil ifTrue:[ |
|
4429 self updateMethodListWithScroll:false. |
|
4430 oldSelector notNil ifTrue:[ |
|
4431 methodListView selectElement:oldSelector |
|
4432 ]. |
|
4433 methodListView selection isNil ifTrue:[ |
|
4434 currentMethod := nil |
|
4435 ] |
|
4436 ]. |
|
4437 self updateCodeView |
|
4438 ! |
|
4439 |
|
4440 update:something with:someArgument from:changedObject |
|
4441 (changedObject == Smalltalk) ifTrue:[self update. ^ self]. |
|
4442 changedObject isBehavior ifTrue:[ |
|
4443 (currentClass notNil and:[changedObject name = currentClass name]) ifTrue:[ |
|
4444 currentClass := Smalltalk at:(currentClass name asSymbol). |
|
4445 showInstance ifTrue:[ |
|
4446 actualClass := currentClass |
|
4447 ] ifFalse:[ |
|
4448 actualClass := currentClass class |
|
4449 ]. |
|
4450 self updateMethodCategoryListWithScroll:false. |
|
4451 "dont update codeView ...." |
|
4452 "self update" |
|
4453 ^ self |
|
4454 ] |
|
4455 ] |
|
4456 ! ! |