2 COPYRIGHT (c) 2007 by eXept Software AG
5 This software is furnished under a license and may be used
6 only in accordance with the terms of that license and with the
7 inclusion of the above copyright notice. This software may not
8 be provided or otherwise made available to, or used by, any
9 other person. No title to or ownership of the software is
12 "{ Package: 'stx:libtool2' }"
14 "{ NameSpace: Tools }"
16 ToolApplicationModel subclass:#ViewTreeInspectorApplication
17 instanceVariableNames:'model treeView hasSingleSelectionHolder clickedItem clickedPoint
18 motionAction process followFocusChannel showNamesHolder
19 inspectorView inspectorModeIndexHolder path
20 isCatchingEventsChannel'
23 category:'Interface-Smalltalk'
26 Object subclass:#MenuDesc
27 instanceVariableNames:'title value action'
30 privateIn:ViewTreeInspectorApplication
33 HierarchicalItem subclass:#ViewTreeItem
34 instanceVariableNames:'widget isDrawnShown exists xOffsetAdditionalName'
35 classVariableNames:'HandleExtent'
37 privateIn:ViewTreeInspectorApplication
40 ValueModel subclass:#ViewTreeModel
41 instanceVariableNames:'lockSema selectedSuperItems selection hiddenLevel listOfItems
42 inputEventAction mappedViewAction beforeSelectionChangedAction
43 icons timedUpdateTask selectOnClickHolder testModeChannel
44 hasTargetWidgetChannel catchEvents'
47 privateIn:ViewTreeInspectorApplication
50 HierarchicalList subclass:#ItemList
51 instanceVariableNames:'treeModel eventHook eventHookInitialized showWidgetNames'
54 privateIn:ViewTreeInspectorApplication::ViewTreeModel
57 !ViewTreeInspectorApplication class methodsFor:'documentation'!
61 COPYRIGHT (c) 2007 by eXept Software AG
64 This software is furnished under a license and may be used
65 only in accordance with the terms of that license and with the
66 inclusion of the above copyright notice. This software may not
67 be provided or otherwise made available to, or used by, any
68 other person. No title to or ownership of the software is
75 Small application showing a ViewTreeModel use.
77 It displays a hierarchical list of a selected TopView and
78 all its contained subViews.
79 Useful to have a look at subcomponents - to see how views
84 model <ViewTreeModel> the used ViewTreeModel
85 clickedItem <ViewTreeItem> item under the clickedPoint (motion action)
86 clickedPoint <Point> point where the motion action started from.
87 motionAction <Action> (oneArg-) action called durring buttonMotion.
99 !ViewTreeInspectorApplication class methodsFor:'initialization'!
102 "add myself to the launcher menu
104 self installInLauncher.
108 "add myself to the launcher menu"
112 NewLauncher isNil ifTrue:[^ self].
113 "/ cg - disabled. the icon is too ugly.
116 icon := ToolbarIconLibrary inspectLocals20x20Icon magnifiedTo:28@28.
118 menuItem := MenuItem new
119 label: 'View Tree Inspector';
120 value: [ ViewTreeInspectorApplication open];
123 nameKey: #viewInspect.
125 menuItem startGroup:#right.
126 NewLauncher addMenuItem:menuItem in:'toolbar'
127 position:#( #before #help)
131 self installInLauncher
132 self removeFromLauncher
137 "add myself to the launcher menu
139 self installInLauncher.
141 self installInLauncher
142 self removeFromLauncher
147 "remove myself from the launcher menu
149 NewLauncher isNil ifTrue:[^ self].
150 NewLauncher removeUserTool:#viewInspect
153 self installInLauncher
154 self removeFromLauncher
159 "class is about to be unloaded - remove myself from the launcher menu
161 self removeFromLauncher.
165 !ViewTreeInspectorApplication class methodsFor:'help specs'!
170 ^super flyByHelpSpec addPairsFrom:#(
173 'Release picked view and uncatch events\(currently locked for widget selection)'
176 'Lock view and catch events for widget selection\(currently unlocked)'
181 !ViewTreeInspectorApplication class methodsFor:'image specs'!
184 "This resource specification was automatically generated
185 by the ImageEditor of ST/X."
187 "Do not manually edit this!! If it is corrupted,
188 the ImageEditor may not be able to read the specification."
191 self crossHairIcon inspect
192 ImageEditor openOnClass:self andSelector:#crossHairIcon
193 Icon flushCachedIcons
199 constantNamed:'Tools::ViewTreeInspectorApplication class crossHairIcon'
200 ifAbsentPut:[(Depth1Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@F0@@XL@@>>@A8O@A>?@B,Z B(J @@@@B(J B,Z A>?@A8O@@>>@@XL@@F0@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[255 255 255 0 0 0]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@G0@@_<@@?>@A??@C?? C?? G??0G<_0G<_0G<_0G??0C?? C?? A??@@?>@@_<@@G0@@@@@@@@@@@@@@@@@') ; yourself); yourself]
204 "This resource specification was automatically generated
205 by the ImageEditor of ST/X."
207 "Do not manually edit this!! If it is corrupted,
208 the ImageEditor may not be able to read the specification."
211 self lockViewIcon inspect
212 ImageEditor openOnClass:self andSelector:#lockViewIcon
213 Icon flushCachedIcons
219 constantNamed:'Tools::ViewTreeInspectorApplication lockViewIcon'
220 ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
221 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
222 @@@@@@@@@@@@@@A8^G!!7O3ACP5*P@@A8^G @@@@@@@@@@@A8^@@@OE0/!!P0S#0@@^G @@@@@@@@@@@B (@D''D#48"1.CX5H@(J@@@@@@@@@@@@B (B(>SAT"
223 ''%!!/P7,@(J@@@@@@@@@@@@@%IB0#M"H%IRTQV5P@IRT@@@@@@@@@@@ANSX:U]PANS$8:T80@S$8@@@@@@@@@@@AN&UYWK(EYQ@\FUPQHXT8@@@@@@@@@@@AN
224 HC2!!TVY:Y#-%I*IKMD8@@@@@@@@@@@A$\@83XBEG%).GGX _!!&P@@@@@@@@@@@AO[P5+ &(WPYN@["!!E\$<@@@@@@@@@@@B_F''FQPAXX_!!&TGH4HB9<@@@@@
225 @@@@@@B_%3HCJ7=BKPU,Q)01B9<@@@@@@@@@@@@PBP8T_F!!''JPI)_Y"D&!!@@@@@@@@@@@@@$B)I9TGXO''WQIWQ93W0@@@@@@@@@@@@@$"U=JR$)JR$)JR$)_
226 "P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
227 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[132 141 152 147 150 154 250 223 1 246 214 0 205 172 133 238 195 0 213 180 146 217 186 150 188 136 0 206 151 0 183 125 9 208 208 202 196 204 214 255 255 210 255 255 219 210 178 65 242 242 235 106 112 117 96 107 126 250 255 255 255 241 0 154 154 151 255 227 0 67 35 0 52 17 0 253 211 0 208 159 0 167 178 193 222 168 0 248 231 45 208 174 26 199 152 26 225 184 36 255 249 75 220 220 215 77 88 108 241 241 235 245 245 239 255 250 109 242 249 255 255 255 142 255 237 1 142 148 162 242 212 1 143 154 176 174 133 0 222 189 144 169 179 192 177 184 193 184 129 0 255 255 194 253 241 60 210 210 205 214 214 209 77 83 92 230 230 225 98 106 114 243 243 238 117 117 114 255 252 115 255 255 255 115 123 147 130 140 156 152 156 159 241 210 0 53 18 0 151 116 0 162 170 184 218 187 150 193 143 4 220 165 0 206 188 46 181 130 21 204 173 44 206 206 201 208 167 44 72 84 108 240 240 234 244 244 238 243 243 237 212 182 79 255 255 126 131 135 141 119 133 159 132 141 163 195 162 126 219 188 133 218 185 135 180 180 176 221 190 150 175 181 191 176 183 196 181 189 201 202 170 38 209 209 204 207 207 202 251 241 74 229 229 224 238 238 233 226 234 245 244 244 237 255 251 113 255 255 124 255 241 2 255 234 3 249 219 0 255 249 29 252 243 30 227 181 0 212 165 5 222 170 0 173 179 194 216 171 19 255 255 198 208 208 203 156 90 7 206 175 50 91 91 95 211 180 71 242 242 237 246 246 241 212 182 80 255 255 123 129 137 152 255 239 8 251 223 0 59 25 0 251 215 0 228 183 0 222 191 149 249 238 43 177 186 197 187 129 0 186 194 206 209 209 203 249 238 67 255 255 211 226 226 221 235 235 229 100 103 111 76 93 127 255 255 112 88 104 139 130 135 148 149 155 158 247 218 0 224 194 126 255 217 0 228 184 0 13 30 68 161 138 32 204 152 0 255 255 53 206 155 18 207 207 201 255 250 72 255 255 82 209 176 59 232 232 227 243 243 236 245 245 240 255 255 115 255 255 251]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@G8@@O<@@_>@@^^@@\N@@\N@@?? @?? @?? @?? @?? @?? @?? @?? @_?@@@@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
231 "This resource specification was automatically generated
232 by the ImageEditor of ST/X."
234 "Do not manually edit this!! If it is corrupted,
235 the ImageEditor may not be able to read the specification."
238 self pickWindowIcon inspect
239 ImageEditor openOnClass:self andSelector:#pickWindowIcon
240 Icon flushCachedIcons
246 constantNamed:'Tools::ViewTreeInspectorApplication class pickWindowIcon'
247 ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
248 ,;N3,;N3,;N3,;N3,;N3,;N3,;N3,3H<P38;M3P,H2@^GA(VEQHQCP0KA D<[&-%XU=WST%BN#D!!GQ$TD@(IBP\BQF)+Z6E_U4-FPCX+G1,WEA@JBP$HAT23
249 ,;N3,;N3,;N3,;N$():Z&IRR&1!!^,;N3,;N3,;N3,;N$)JJ^&)"T$),0W[N3,;N3,;N3,;N3,:R"'')*X%IJWK523,;N3,;N3,0@@@KN3)JJ^&)"T$"5Z,;N3
250 ,;N3@@B3-KL@@JJ^&)"T$)D*V[N3,;N3@KN3-KR4)JH@&)"T$)*MJE"3,;N3,0B3)JJ4&*R"@I*X%IJZ#RYV,;N3,0B3@JR"-JR"-I(@%IJV%H %U[N3,;L@
251 -@B4-KR4-KR4@IRR%IJEIER3,;N3@KL@)JJ4():4&@BO#9RR!!RIS,;N3,;L@,:R"-JJ^& BT#8>O#8H"T+N3,;N3@KN$@@@@'')(@%H>O#(>AH%F3,;N3,;L@
252 @JR4'' @@%IJO#8>O RIO,;N3,;N3):P@@@BX%IJO#8>O#7<"S*63,;N$():Z&IRR&IRR#8>O#8=>H"&-,;N$():Z&IRR&)"T$(>O#8>O @<)R$!!GQTD?OS$8
253 MSL.I2H"H"H"H"HO,;N3,;N3,;N3,;N3,;N3,;N3,;N3,0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 0 50 164 0 50 171 0 137 0 0 206 0 1 50 177 2 56 178 3 64 241 3 67 246 3 73 255 4 74 255 5 63 191 7 66 194 10 71 196 10 79 255 12 59 167 12 82 255 14 77 199 18 83 201 19 88 255 21 91 255 23 89 204 27 95 206 28 97 255 29 72 179 30 100 255 32 101 209 36 106 255 36 107 211 39 109 255 41 113 214 45 115 255 45 119 216 48 118 255 50 87 176 50 125 219 51 88 176 51 88 177 52 89 178 52 90 178 53 90 178 53 127 212 54 91 179 54 123 255 54 131 221 55 92 180 55 95 181 56 93 180 56 94 181 57 127 255 57 149 229 58 99 184 58 137 224 61 104 187 63 132 255 63 143 226 64 108 190 66 113 193 66 135 255 67 149 229 68 157 232 69 117 196 71 155 231 72 122 199 72 141 255 75 126 202 75 144 255 75 160 234 77 163 236 78 131 206 80 149 255 81 136 209 84 140 212 84 153 255 87 145 215 88 157 255 91 168 235 93 161 255 94 154 222 96 157 223 96 165 255 97 159 225 98 160 225 98 162 226 99 163 227 100 165 228 101 166 229 101 170 255 102 167 230 103 169 231 104 170 232 104 173 255 105 172 233 105 174 234 106 175 235 109 178 255 112 180 255 117 186 255 119 187 255 122 154 245 125 160 253 125 193 255 126 161 253 126 194 255 127 162 254 130 165 254 132 200 255 132 201 255 133 60 36 135 170 255 139 207 255 140 175 255 144 179 255 149 184 255 153 188 255 157 192 255 162 196 255 166 200 255 170 204 255 174 208 255 174 218 230 177 212 255 181 215 255 185 219 255 188 222 255 191 225 255 212 211 224 218 217 230 219 219 230 220 220 231 222 221 232 223 223 233 225 224 234 225 225 234 226 226 237 227 226 235 227 227 236 227 227 238 228 228 237 229 229 239 231 230 238 231 231 238 231 231 240 232 232 241 233 232 239 233 233 240 234 234 242 235 234 241 236 236 243 237 236 242 237 237 244 238 237 243 238 238 244 239 238 243 239 239 245 240 239 244 241 240 245 241 241 246 241 241 247 242 242 246 242 242 247 243 243 247 243 243 248 244 244 248 244 244 249 245 244 247 246 246 249 246 246 250 247 246 249 247 247 250 248 248 251 249 249 250 249 249 251 250 250 251 250 250 252 251 251 252 251 251 253 253 253 254 254 254 255 255 255 255 0 0 0]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@C????????????????????????????????????????????????????????????????????????????????@@@C') ; yourself); yourself]
257 "This resource specification was automatically generated
258 by the ImageEditor of ST/X."
260 "Do not manually edit this!! If it is corrupted,
261 the ImageEditor may not be able to read the specification."
264 self pickWindowIcon2 inspect
265 ImageEditor openOnClass:self andSelector:#pickWindowIcon2
266 Icon flushCachedIcons
272 constantNamed:'Tools::ViewTreeInspectorApplication class pickWindowIcon2'
273 ifAbsentPut:[(Depth8Image new) width: 22; height: 23; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
274 @CH<O#,7MB0#HA8\F!!XUD!!DMC@,F@P@<[&U!!W5]MRTH:LRD]FQPPB $IA0H@QF)+XU=WR4Y@M",_F1\TD@(IBP E@D23,;N3,;N3,;N3,;N"'')*X%IJ[F@A^
275 ,;N3,;N3,0@@@@@@():Z&IRR&3@@W+N3,;N3@@B3,0B3)@@@&)"T$),0@E63,;N3@KN3@@@@@@B"'' BX%IJWK0A\,;N3@KN3,;N3@JR"'')*X@IRR&24@V+N3
276 @KN3,;L@@@@@@I:Z&IP@$),*@E&3,0B3,;N3,:P@():Z&IRT@IJ[J@AX,0B3@KL@,;L@@@B^& BT@IP@&2X@U+L@,0B3@KL@)JJ^@I @%@BT@I,%@EV3@@@@
277 @@@@@JR"'' @@@@@@@@B[I@AT,0B3@KL@)@B$()8@&@BZ@IP@&2H@T;L@,0B3@JR$@@@@%I @& BT@I,"@EJ3,0B3,:R$)I8@&IRX%I*X@IJ[H AQ,;L@,:R$
278 )@@@@@@@&IRO#0BO RH@S;N3,0B$)JR"'' BX%I"T#0BO#7<"@D:-,;N$@JR$@@@@@@BR#0BO#8=>H AN+[N$)JH@@I"T@I"T@@BO#8>O_"H@JZ63)JJ^&) @
279 @@@@@IJO#8>O#8@O@B&3,;N3,;N3,;N3,;N"'')*X%IJ[C0@)R$]EPS<=NS 5L28''H"H"H"H"H <b') ; colorMapFromArray:#[0 0 0 0 50 164 0 50 171 0 137 0 0 206 0 1 50 177 2 56 178 3 64 241 3 67 246 3 73 255 4 74 255 5 63 191 7 66 194 10 71 196 10 79 255 12 59 167 12 82 255 14 77 199 18 83 201 19 88 255 21 91 255 23 89 204 27 95 206 28 97 255 29 72 179 30 100 255 32 101 209 36 106 255 36 107 211 39 109 255 41 113 214 45 115 255 45 119 216 48 118 255 50 87 176 50 125 219 51 88 176 51 88 177 52 89 178 52 90 178 53 90 178 53 127 212 54 91 179 54 123 255 54 131 221 55 92 180 55 95 181 56 93 180 56 94 181 57 127 255 57 149 229 58 99 184 58 137 224 61 104 187 63 132 255 63 143 226 64 108 190 66 113 193 66 135 255 67 149 229 68 157 232 69 117 196 71 155 231 72 122 199 72 141 255 75 126 202 75 144 255 75 160 234 77 163 236 78 131 206 80 149 255 81 136 209 84 140 212 84 153 255 87 145 215 88 157 255 91 168 235 93 161 255 94 154 222 96 157 223 96 165 255 97 159 225 98 160 225 98 162 226 99 163 227 100 165 228 101 166 229 101 170 255 102 167 230 103 169 231 104 170 232 104 173 255 105 172 233 105 174 234 106 175 235 109 178 255 112 180 255 117 186 255 119 187 255 122 154 245 125 160 253 125 193 255 126 161 253 126 194 255 127 162 254 130 165 254 132 200 255 132 201 255 133 60 36 135 170 255 139 207 255 140 175 255 144 179 255 149 184 255 153 188 255 157 192 255 162 196 255 166 200 255 170 204 255 174 208 255 174 218 230 177 212 255 181 215 255 185 219 255 188 222 255 191 225 255 212 211 224 218 217 230 219 219 230 220 220 231 222 221 232 223 223 233 225 224 234 225 225 234 226 226 237 227 226 235 227 227 236 227 227 238 228 228 237 229 229 239 231 230 238 231 231 238 231 231 240 232 232 241 233 232 239 233 233 240 234 234 242 235 234 241 236 236 243 237 236 242 237 237 244 238 237 243 238 238 244 239 238 243 239 239 245 240 239 244 241 240 245 241 241 246 241 241 247 242 242 246 242 242 247 243 243 247 243 243 248 244 244 248 244 244 249 245 244 247 246 246 249 246 246 250 247 246 249 247 247 250 248 248 251 249 249 250 249 249 251 250 250 251 250 250 252 251 251 252 251 251 253 253 253 254 254 254 255 255 255 255]; mask:((Depth1Image new) width: 22; height: 23; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<_??<') ; yourself); yourself]
283 "This resource specification was automatically generated
284 by the ImageEditor of ST/X."
286 "Do not manually edit this!! If it is corrupted,
287 the ImageEditor may not be able to read the specification."
290 self releaseViewIcon inspect
291 ImageEditor openOnClass:self andSelector:#releaseViewIcon
292 Icon flushCachedIcons
297 constantNamed:'Tools::ViewTreeInspectorApplication releaseViewIcon'
298 ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
299 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
300 @@@@@@@@@@@@@@A8^G!!7O3ACP5*P@@A8^G @@@@@@@@@@@A8^@@@OE0/!!P0S#0@@^G @@@@@@@@@@@B (@@''D#48"1.CX5H@(J@@@@@@@@@@@@B (@@@@@@"
301 ''%!!/P7,@(J@@@@@@@@@@@@@%I@@@@BH%IRTQV5P@IRT@@@@@@@@@@@ANSP@@@@ANS$8:T80@S$8@@@@@@@@@@@AN&UYWK(EYQ@\FUPQHXT8@@@@@@@@@@@AN
302 HC2!!TVY:Y#-%I*IKMD8@@@@@@@@@@@A$\@83XBEG%).GGX _!!&P@@@@@@@@@@@AO[P5+ &(WPYN@["!!E\$<@@@@@@@@@@@B_F''FQPAXX_!!&TGH4HB9<@@@@@
303 @@@@@@B_%3HCJ7=BKPU,Q)01B9<@@@@@@@@@@@@PBP8T_F!!''JPI)_Y"D&!!@@@@@@@@@@@@@$B)I9TGXO''WQIWQ93W0@@@@@@@@@@@@@$"U=JR$)JR$)JR$)_
304 "P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
305 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[132 141 152 147 150 154 250 223 1 246 214 0 205 172 133 238 195 0 213 180 146 217 186 150 188 136 0 206 151 0 183 125 9 208 208 202 196 204 214 255 255 210 255 255 219 210 178 65 242 242 235 106 112 117 96 107 126 250 255 255 255 241 0 154 154 151 255 227 0 67 35 0 52 17 0 253 211 0 208 159 0 167 178 193 222 168 0 248 231 45 208 174 26 199 152 26 225 184 36 255 249 75 220 220 215 77 88 108 241 241 235 245 245 239 255 250 109 242 249 255 255 255 142 255 237 1 142 148 162 242 212 1 143 154 176 174 133 0 222 189 144 169 179 192 177 184 193 184 129 0 255 255 194 253 241 60 210 210 205 214 214 209 77 83 92 230 230 225 98 106 114 243 243 238 117 117 114 255 252 115 255 255 255 115 123 147 130 140 156 152 156 159 241 210 0 53 18 0 151 116 0 162 170 184 218 187 150 193 143 4 220 165 0 206 188 46 181 130 21 204 173 44 206 206 201 208 167 44 72 84 108 240 240 234 244 244 238 243 243 237 212 182 79 255 255 126 131 135 141 119 133 159 132 141 163 195 162 126 219 188 133 218 185 135 180 180 176 221 190 150 175 181 191 176 183 196 181 189 201 202 170 38 209 209 204 207 207 202 251 241 74 229 229 224 238 238 233 226 234 245 244 244 237 255 251 113 255 255 124 255 241 2 255 234 3 249 219 0 255 249 29 252 243 30 227 181 0 212 165 5 222 170 0 173 179 194 216 171 19 255 255 198 208 208 203 156 90 7 206 175 50 91 91 95 211 180 71 242 242 237 246 246 241 212 182 80 255 255 123 129 137 152 255 239 8 251 223 0 59 25 0 251 215 0 228 183 0 222 191 149 249 238 43 177 186 197 187 129 0 186 194 206 209 209 203 249 238 67 255 255 211 226 226 221 235 235 229 100 103 111 76 93 127 255 255 112 88 104 139 130 135 148 149 155 158 247 218 0 224 194 126 255 217 0 228 184 0 13 30 68 161 138 32 204 152 0 255 255 53 206 155 18 207 207 201 255 250 72 255 255 82 209 176 59 232 232 227 243 243 236 245 245 240 255 255 115 255 255 251]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@G8@@O<@@O>@@@^@@@N@@@N@@?? @?? @?? @?? @?? @?? @?? @?? @_?@@@@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
308 !ViewTreeInspectorApplication class methodsFor:'interface specs'!
311 "This resource specification was automatically generated
312 by the UIPainter of ST/X."
314 "Do not manually edit this!! If it is corrupted,
315 the UIPainter may not be able to read the specification."
318 UIPainter new openOnClass:Tools::ViewTreeInspectorApplication andSelector:#windowSpec
319 Tools::ViewTreeInspectorApplication new openInterface:#windowSpec
320 Tools::ViewTreeInspectorApplication open
330 label: 'View Tree Inspector'
331 name: 'View Tree Inspector'
333 max: (Point 1024 9999)
334 bounds: (Rectangle 0 0 693 643)
342 layout: (LayoutFrame 0 0.0 0 0 0 1.0 40 0)
346 (VariableVerticalPanelSpec
347 name: 'VariableVerticalPanel1'
348 layout: (LayoutFrame 0 0.0 40 0.0 0 1.0 0 1.0)
353 name: 'PathAndListPane'
359 layout: (LayoutFrame 0 0 0 0 0 1 25 0)
365 layout: (LayoutFrame 0 0 0 0 0 1 0 1)
369 acceptOnPointerLeave: true
370 emptyFieldReplacementText: 'No View Selected'
376 (HierarchicalListViewSpec
378 layout: (LayoutFrame 0 0 25 0 0 1 0 1)
381 menu: middleButtonMenu
382 hasHorizontalScrollBar: true
383 hasVerticalScrollBar: true
384 miniScrollerHorizontal: true
385 miniScrollerVertical: false
386 listModel: listOfItems
387 multipleSelectOk: true
390 showLeftIndicators: false
391 indicatorSelector: indicatorClicked:
392 useDefaultIcons: false
393 postBuildCallback: postBuildTree:
406 layout: (LayoutFrame 0 0.0 0 0 0 1.0 25 0)
407 model: inspectorModeIndexHolder
414 layout: (LayoutFrame 0 0 26 0 0 1 0 1)
415 postBuildCallback: postBuildInspectorView:
416 viewClassName: 'InspectorView'
425 handles: (Any 0.5 1.0)
433 !ViewTreeInspectorApplication class methodsFor:'menu specs'!
436 "This resource specification was automatically generated
437 by the MenuEditor of ST/X."
439 "Do not manually edit this!! If it is corrupted,
440 the MenuEditor may not be able to read the specification."
444 MenuEditor new openOnClass:Tools::ViewTreeInspectorApplication andSelector:#menu
445 (Menu new fromLiteralArrayEncoding:(Tools::ViewTreeInspectorApplication menu)) startUp
460 itemValue: doPickView
463 enabled: hasTargetWidgetChannel
464 label: 'Release Picked View'
477 hideMenuOnActivated: false
478 indication: testModeChannel
481 enabled: testModeChannel
482 label: 'Follow Focus'
483 hideMenuOnActivated: false
484 indication: followFocusChannel
490 label: 'Select on Click'
491 hideMenuOnActivated: false
492 indication: selectOnClickHolder
498 label: 'Show Name of Widgets'
499 hideMenuOnActivated: false
500 indication: showNamesHolder
512 itemValue: closeRequest
520 enabled: hasSingleSelectionHolder
522 submenuChannel: middleButtonMenu
530 enabled: hasSingleSelectionHolder
536 enabled: hasSingleSelectionHolder
538 itemValue: doInspect:
545 enabled: hasTargetWidgetChannel
546 label: 'All Components'
548 submenuChannel: submenuComponents:
568 enabled: hasSingleSelectionHolder
571 argument: application
574 enabled: hasSingleSelectionHolder
576 itemValue: doInspect:
577 argument: application
583 enabled: canBrowseWindowSpecMethod
584 label: 'Browse Window Spec Method'
585 itemValue: doBrowseWindowSpecMethod
588 enabled: canEditWindowSpec
589 label: 'Edit Window Spec'
590 itemValue: doEditWindowSpec
596 enabled: hasTargetWidgetChannel
597 label: 'All Applications'
598 submenuChannel: submenuApplications:
611 enabled: hasSingleSelectionHolder
613 itemValue: doDebugProcess
616 enabled: hasSingleSelectionHolder
618 itemValue: doInspect:
625 label: 'Open Process Monitor'
626 itemValue: doOpenProcessMonitor
635 startGroup: conditionalRight
640 label: 'Documentation'
641 itemValue: openDocumentation
647 label: 'About this Application...'
648 itemValue: openAboutThisApplication
662 "This resource specification was automatically generated
663 by the MenuEditor of ST/X."
665 "Do not manually edit this!! If it is corrupted,
666 the MenuEditor may not be able to read the specification."
669 MenuEditor new openOnClass:ViewTreeApplication andSelector:#middleButtonMenu
670 (Menu new fromLiteralArrayEncoding:(ViewTreeApplication middleButtonMenu)) startUp
681 submenuChannel: submenuGeometry:
687 submenuChannel: submenuInterface:
693 submenuChannel: submenuVisibility:
700 label: 'Browse View Class'
706 label: 'Browse Model Class'
713 label: 'Browse Application Class'
716 isVisible: hasApplication
717 argument: #application
720 label: 'Browse Controller Class'
723 isVisible: hasController
724 argument: #controller
730 label: 'Inspect View'
731 itemValue: doInspect:
736 label: 'Inspect Window Group'
737 itemValue: doInspect:
742 label: 'Inspect Model'
743 itemValue: doInspect:
749 label: 'Inspect Application'
750 itemValue: doInspect:
752 isVisible: hasApplication
753 argument: #application
756 label: 'Inspect Controller'
757 itemValue: doInspect:
759 isVisible: hasController
760 argument: #controller
782 label: 'Instance Variables'
784 submenuChannel: submenuInspector:
794 enabled: selectedComponentHasChildren
795 label: 'Applications'
798 submenuChannel: submenuApplications:
802 enabled: selectedComponentHasChildren
806 submenuChannel: submenuComponents:
816 "This resource specification was automatically generated
817 by the MenuEditor of ST/X."
819 "Do not manually edit this!! If it is corrupted,
820 the MenuEditor may not be able to read the specification."
824 MenuEditor new openOnClass:Tools::ViewTreeInspectorApplication andSelector:#toolbarMenu
825 (Menu new fromLiteralArrayEncoding:(Tools::ViewTreeInspectorApplication toolbarMenu)) startUp
834 enabled: hasTargetWidgetChannel
838 labelImage: (ResourceRetriever ToolbarIconLibrary reloadIcon)
844 label: 'Pick a View and Catch Events'
845 itemValue: doPickView
846 translateLabel: false
848 hideMenuOnActivated: false
849 labelImage: (ResourceRetriever #'Tools::ViewTreeInspectorApplication' pickWindowIcon2)
852 enabled: hasTargetWidgetChannel
853 isVisible: isNotCatchingEventsChannel
854 label: 'Catch Events of Picked View'
855 activeHelpKey: doCatchEvents
856 itemValue: doCatchEvents
857 nameKey: doCatchEvents
859 labelImage: (ResourceRetriever nil releaseViewIcon)
862 enabled: hasTargetWidgetChannel
863 isVisible: isCatchingEventsChannel
864 label: 'Release Picked View and Uncatch Events'
865 activeHelpKey: doUncatchEvents
866 itemValue: doUncatchEvents
867 nameKey: doUncatchEvents
869 labelImage: (ResourceRetriever nil lockViewIcon)
875 enabled: hasSingleSelectionHolder
876 label: 'Browse Application'
878 translateLabel: false
880 hideMenuOnActivated: false
881 labelImage: (ResourceRetriever ToolbarIconLibrary systemBrowser24x24Icon2)
882 argument: application
885 enabled: hasSingleSelectionHolder
886 label: 'Inspect Application'
887 itemValue: doInspect:
888 translateLabel: false
890 hideMenuOnActivated: false
891 labelImage: (ResourceRetriever ToolbarIconLibrary inspect22x24Icon)
892 argument: application
900 !ViewTreeInspectorApplication class methodsFor:'startup'!
911 openInPickModeAndRelease
912 "release the pick-lock after picking"
916 app := self openInPickMode.
922 "show a particular window's topView hierarchy,
923 select the given view"
929 app showWindow:aView.
933 !ViewTreeInspectorApplication methodsFor:'actions'!
935 indicatorClicked:anIndex
938 item := model listOfItems at:anIndex ifAbsent:nil.
941 ( (sensor := self window sensor) notNil
942 and:[(sensor ctrlDown or:[sensor shiftDown])]
944 item recursiveToggleExpand
951 !ViewTreeInspectorApplication methodsFor:'aspects'!
953 canBrowseWindowSpecMethod
954 ^ self hasSingleSelectionHolder value and:[ self windowSpecMethodOfSelection notNil ]
958 ^ self hasSingleSelectionHolder value and:[ self windowSpecMethodOfSelection notNil ]
962 "boolean holder, which indicates whether selection changed dependend on the focus view"
967 hasSingleSelectionHolder
968 "boolean holder, true if one item is selected"
970 ^ hasSingleSelectionHolder
973 hasTargetWidgetChannel
974 "answer the channel which is set to true if a target widget exists"
976 ^ model hasTargetWidgetChannel
980 "what is shown in the inspector:
988 (inspectorModeIndexHolder value == 1) ifTrue:[ ^#widget].
989 (inspectorModeIndexHolder value == 2) ifTrue:[ ^#application].
990 (inspectorModeIndexHolder value == 3) ifTrue:[ ^#group].
991 (inspectorModeIndexHolder value == 4) ifTrue:[ ^#sensor].
992 (inspectorModeIndexHolder value == 5) ifTrue:[ ^#model].
995 "Created: / 30-07-2013 / 07:44:59 / cg"
998 inspectorModeIndexHolder
999 "what is shown in the inspector:
1007 ^ inspectorModeIndexHolder
1009 "Created: / 30-07-2013 / 07:44:07 / cg"
1013 ^ #('Widget' 'Application' 'WindowGroup' 'Sensor' 'Model')
1015 "Created: / 30-07-2013 / 09:42:16 / cg"
1018 isCatchingEventsChannel
1019 ^ isCatchingEventsChannel
1022 isNotCatchingEventsChannel
1023 ^ BlockValue forLogicalNot:self isCatchingEventsChannel
1027 "returns the hierarchical list of items"
1033 "returns my selection model, a ViewTreeModel"
1039 <resource: #uiAspect>
1042 path := PluggableAdaptor
1044 getter:[ :model | model path ]
1045 setter:[ :model :newValue | ]
1049 "Modified: / 19-05-2014 / 18:40:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
1053 "boolean holder, which indicates whether the selection will change on click"
1055 ^ model selectOnClickHolder
1059 "boolean holder, which indicates whether application names or widget names
1060 as additional text are shown for the items"
1066 "answer a boolean channel which describes the behaviour how to process
1067 events on the target view.
1069 false: all input events are eaten and the selection is shown on the target view.
1070 true: no input events are eaten and no selection is shown on the target view."
1072 ^ model testModeChannel
1075 windowSpecMethodOfSelection
1076 |item view app spec builder specSelector implementors|
1078 item := model selectedItem.
1079 item isNil ifTrue:[^ nil].
1081 view := item widget.
1082 view isNil ifTrue:[^ nil].
1084 app := view application.
1085 app isNil ifTrue:[^ nil].
1087 builder := app builder.
1088 builder isNil ifTrue:[^ nil].
1090 spec := builder spec.
1091 spec isNil ifTrue:[^ nil].
1093 specSelector := spec name.
1094 specSelector isNil ifTrue:[^ nil].
1096 (app class theNonMetaclass canUnderstand:specSelector) ifTrue:[
1097 ^ app class theNonMetaclass lookupMethodFor:specSelector.
1099 (app class theMetaclass canUnderstand:specSelector) ifTrue:[
1100 ^ app class theMetaclass lookupMethodFor:specSelector.
1103 "/ maybe a simple dialog given a spec
1104 app masterApplication notNil ifTrue:[
1105 (app masterApplication class theNonMetaclass canUnderstand:specSelector) ifTrue:[
1106 ^ app masterApplication class theNonMetaclass lookupMethodFor:specSelector.
1108 (app masterApplication class theMetaclass canUnderstand:specSelector) ifTrue:[
1109 ^ app masterApplication class theMetaclass lookupMethodFor:specSelector.
1113 implementors := Smalltalk allImplementorsOf: specSelector.
1114 implementors size == 1 ifTrue:[
1115 ^ implementors first compiledMethodAt:specSelector.
1121 !ViewTreeInspectorApplication methodsFor:'change & update'!
1123 inspectorModeIndexHolderChanged
1124 self updateInspector
1126 "Created: / 30-07-2013 / 09:21:51 / cg"
1132 item := model selectedItem.
1133 item notNil ifTrue:[
1136 view := item widget.
1138 view id isNil ifTrue:[
1144 state := 'invisible'
1147 info := '%1 [%2] - %3' bindWith:(view class name)
1148 with:(view name ? '') with:state allBold.
1152 hasSingleSelectionHolder value:(view notNil).
1153 self updateInspector
1155 "Modified: / 30-07-2013 / 09:21:27 / cg"
1158 update:something with:someArgument from:aModel
1161 aModel == showNamesHolder ifTrue:[
1162 oldSelection := model selectedItem.
1163 model selectedItem:nil.
1164 self listOfItems showWidgetNames:(aModel value).
1165 model selectedItem:oldSelection.
1169 aModel == model ifTrue:[
1170 self selectionChanged.
1174 super update:something with:someArgument from:aModel.
1180 view := self selectedView.
1181 (view isNil or:[self inspectorMode == #widget]) ifTrue:[
1183 ] ifFalse:[ (self inspectorMode == #group) ifTrue:[
1184 obj := view windowGroup
1185 ] ifFalse:[ (self inspectorMode == #sensor) ifTrue:[
1187 ] ifFalse:[ (self inspectorMode == #model) ifTrue:[
1190 obj := view application.
1192 inspectorView inspect:obj.
1193 inspectorView headLineLabel:(obj class nameWithoutPrefix)
1195 "Created: / 30-07-2013 / 09:21:16 / cg"
1198 !ViewTreeInspectorApplication methodsFor:'event processing'!
1200 processButtonMotionEvent:ev
1203 motionAction isNil ifTrue:[^ self].
1205 (rootView := model rootView) isNil ifTrue:[
1206 clickedItem := motionAction := nil.
1210 click := rootView device
1211 translatePoint:((ev x)@ (ev y))
1215 click = clickedPoint ifFalse:[
1216 (clickedItem isNil or:[(click dist:clickedPoint) > 5.0]) ifTrue:[
1217 motionAction value:click
1222 processButtonPressEvent:ev
1223 |rootView sensor lastRectangle|
1225 rootView := model rootView.
1226 sensor := model rootView sensor.
1227 clickedItem := model listOfItems detectItemRespondsToView:(ev view).
1229 (sensor ctrlDown or:[sensor shiftDown]) ifTrue:[
1230 clickedItem notNil ifTrue:[
1231 self selectOnClickHolder value ifTrue:[
1232 model toggleSelectItem:clickedItem
1235 clickedItem := motionAction := nil.
1239 clickedPoint := rootView device translatePoint:((ev x)@ (ev y)) fromView:(ev view) toView:rootView.
1240 lastRectangle := nil.
1243 rootView := model rootView device rootView.
1244 rootView := model rootView.
1248 lastRectangle notNil ifTrue:[ rootView displayRectangle:lastRectangle ]
1249 ifFalse:[ rootView clippedByChildren:false ].
1252 rootView clippedByChildren:true.
1253 motionAction := nil.
1255 lastRectangle := Rectangle origin:(clickedPoint min:p) corner:(clickedPoint max:p).
1256 rootView displayRectangle:lastRectangle.
1264 processButtonReleaseEvent:anEvent
1265 |rootView rectangle newItems widget origin|
1267 (rootView := model rootView) isNil ifTrue:[
1268 clickedItem := motionAction := nil.
1271 motionAction isNil ifTrue:[ ^ self ].
1272 clickedItem notNil ifTrue:[ ^ model selectItem:clickedItem ].
1274 rectangle := motionAction value:nil.
1275 rectangle isNil ifTrue:[^ self].
1277 newItems := OrderedCollection new.
1279 model rootItem recursiveDo:[:anItem|
1280 widget := anItem widget.
1281 origin := widget originRelativeTo:rootView.
1283 (rectangle containsRect:(Rectangle origin:origin extent:(widget extent))) ifTrue:[
1284 newItems add:anItem.
1287 model value:newItems.
1290 processEvent:anEvent
1293 anEvent isKeyPressEvent ifTrue:[ self processKeyPressEvent:anEvent. ^ self ].
1294 anEvent isButtonEvent ifFalse:[ ^ self ].
1296 button := anEvent button.
1298 (button == 2 or:[button == #menu]) ifTrue:[
1299 motionAction isNil ifTrue:[
1300 anEvent isButtonPressEvent ifTrue:[
1301 self selectOnClickHolder value ifTrue:[
1302 menu := self middleButtonMenu value.
1303 menu notNil ifTrue:[
1305 menu:(Menu new fromLiteralArrayEncoding:menu)
1316 anEvent isButtonPressEvent ifTrue:[ self processButtonPressEvent:anEvent. ^ self ].
1317 anEvent isButtonMotionEvent ifTrue:[ self processButtonMotionEvent:anEvent. ^ self ].
1319 anEvent isButtonReleaseEvent ifTrue:[
1320 self selectOnClickHolder value ifTrue:[
1321 self processButtonReleaseEvent:anEvent
1324 clickedItem := motionAction := nil.
1326 anEvent type == #'buttonMultiPress:x:y:' ifTrue:[
1327 self selectOnClickHolder value ifTrue:[
1328 self doInspect:#view.
1333 processKeyPressEvent:anEvent
1334 |item prnt idx key max next|
1337 key isSymbol ifFalse:[^ self].
1339 key == #Delete ifTrue:[ ^ self doDestroy ].
1340 key == #InspectIt ifTrue:[ ^ self doInspect:#view ].
1343 or:[key == #CursorDown
1344 or:[key == #CursorLeft
1345 or:[key == #CursorRight]]]
1349 item := model selectedItem.
1352 ^ model selectedItem:(model first ? model rootItem)
1355 prnt := item parent.
1358 (key == #CursorUp or:[key == #CursorLeft]) ifTrue:[item := model listOfItems last]
1359 ifFalse:[item := item at:1 ifAbsent:item].
1361 ^ model selectedItem:item
1363 key == #CursorLeft ifTrue:[ ^ model selectedItem:prnt ].
1365 key == #CursorRight ifTrue:[
1366 next := item at:1 ifAbsent:nil.
1367 next notNil ifTrue:[ model selectedItem:next ].
1373 key == #CursorUp ifTrue:[
1374 idx := prnt identityIndexOf:item.
1375 idx == 1 ifTrue:[idx := max + 1].
1376 model selectedItem:(prnt at:idx - 1).
1380 key == #CursorDown ifTrue:[
1381 idx := prnt identityIndexOf:item.
1382 idx == max ifTrue:[idx := 0].
1383 model selectedItem:(prnt at:idx + 1).
1388 processMappedView:aView
1391 parent := self listOfItems detectItemRespondsToView:aView.
1392 parent isNil ifTrue:[ ^ self ].
1394 NotFoundSignal handle:[:ex|
1395 "contained subvies used by spec are not yet created;
1396 thus we have to wait until last used subview is build
1400 anchor := parent class buildViewsFrom:(parent widget).
1402 anchor notNil ifTrue:[
1403 parent updateFromChildren:anchor children.
1407 !ViewTreeInspectorApplication methodsFor:'initialization & release'!
1410 "release the grapped application"
1413 super closeDownViews.
1418 "setup my model and channels"
1422 hasSingleSelectionHolder := false asValue.
1423 followFocusChannel := false asValue.
1424 isCatchingEventsChannel := false asValue.
1425 inspectorModeIndexHolder := 1 asValue.
1426 inspectorModeIndexHolder onChangeSend:#inspectorModeIndexHolderChanged to:self.
1428 model := ViewTreeModel new.
1429 model inputEventAction:[:ev| self processEvent:ev ].
1430 model mappedViewAction:[:vw| self processMappedView:vw ].
1431 model application:self.
1432 model addDependent:self.
1435 showNamesHolder := false asValue.
1436 showNamesHolder addDependent:self.
1438 "Modified: / 30-07-2013 / 09:20:08 / cg"
1441 postBuildInspectorView:anInspector
1442 inspectorView := anInspector.
1446 treeView := aTree scrolledView.
1447 "/ treeView hasConstantHeight:true.
1451 "release the grapped application"
1457 !ViewTreeInspectorApplication methodsFor:'menu queries'!
1460 "returns true if the current selected view has an application"
1464 view := self selectedView.
1465 ^ (view notNil and:[view application notNil])
1469 "returns true if the current selected item's view has a controller
1470 other than nil or the view itself"
1474 view := self selectedView.
1476 view notNil ifTrue:[
1477 controller := view controller.
1478 ^ (controller notNil and:[controller ~~ view])
1484 "returns true if the current selected view has a model"
1488 view := self selectedView.
1489 ^ (view notNil and:[view model notNil])
1492 !ViewTreeInspectorApplication methodsFor:'menu specs'!
1495 "returns the middleButton menu for the single selected item or nil"
1498 model selectedItem notNil
1499 ifTrue:[self class middleButtonMenu]
1504 submenuApplications:aMenu
1505 |applications menu item list addBlock|
1507 item := aMenu selection nameKey == #single ifTrue:[model selectedItem]
1508 ifFalse:[model rootItem].
1509 item isNil ifTrue:[^ nil].
1511 applications := IdentityDictionary new.
1513 addBlock := [:el| |cls ctr|
1514 cls := self resolveApplicationClassFor:el.
1517 ctr := applications at:cls ifAbsent:0.
1518 applications at:cls put:(ctr + 1).
1521 item recursiveDo:addBlock.
1522 addBlock value:item.
1524 applications isEmpty ifTrue:[^ nil ].
1525 list := SortedCollection sortBlock:[:a :b| a title < b title ].
1527 applications keysAndValuesDo:[:cls :ctr|
1528 list add:(MenuDesc title:(cls name)
1529 value:(ctr printString)
1530 action:[self doSelectNextOfApplicationClass:cls startingIn:item]
1534 menu := MenuDesc buildFromList:list onGC:aMenu.
1536 el hideMenuOnActivated:false
1541 submenuComponents:aMenu
1542 |widgets list total menu item|
1544 item := aMenu selection nameKey == #single ifTrue:[model selectedItem]
1545 ifFalse:[model rootItem].
1546 item isNil ifTrue:[^ nil].
1548 widgets := IdentityDictionary new.
1551 item recursiveDo:[:el| |cls ctr|
1556 ctr := widgets at:cls ifAbsent:0.
1557 widgets at:cls put:(ctr + 1).
1561 total == 0 ifTrue:[^ nil].
1562 list := SortedCollection sortBlock:[:a :b| a title < b title ].
1564 widgets keysAndValuesDo:[:cls :ctr|
1565 list add:(MenuDesc title:(cls name)
1566 value:(ctr printString)
1567 action:[self doSelectNextOfClass:cls startingIn:item]
1570 list := list asOrderedCollection.
1571 list add:(MenuDesc separator).
1572 list add:(MenuDesc title:'Total' value:(total printString)).
1573 menu := MenuDesc buildFromList:list onGC:aMenu.
1575 el hideMenuOnActivated:false
1580 submenuGeometry:aMenu
1581 "builds and returns the geometry submenu"
1583 |view point inst list x y|
1585 view := self selectedView.
1586 view isNil ifTrue:[^ nil].
1588 list := OrderedCollection new.
1591 point := view relativeOrigin.
1592 point isNil ifTrue:[ point := view origin ].
1597 (x == point x and:[y == point y]) ifTrue:[ inst := point ]
1598 ifFalse:[ inst := '%1 --> (%2@%3)' bindWith:point with:x with:y ].
1600 list add:(MenuDesc title:'origin' value:inst).
1603 point := view relativeCorner.
1604 point isNil ifTrue:[ point := view corner ].
1609 (x == point x and:[y == point y]) ifTrue:[ inst := point ]
1610 ifFalse:[ inst := '%1 --> (%2@%3)' bindWith:point with:x with:y ].
1612 list add:(MenuDesc title:'corner' value:inst).
1615 (point := view relativeExtent) isNil ifTrue:[point := view extent].
1616 list add:(MenuDesc title:'extent' value:point).
1619 list add:(MenuDesc title:'pref. extent' value:(view preferredExtent)).
1620 list add:(MenuDesc separator).
1623 inst := 'l:%1 r:%2 t:%3 b:%4' bindWith:(view leftInset)
1624 with:(view rightInset)
1625 with:(view topInset)
1626 with:(view bottomInset).
1628 list add:(MenuDesc title:'insets' value:inst).
1629 list add:(MenuDesc title:'borderWidth' value:(view borderWidth)).
1630 list add:(MenuDesc title:'level' value:(view level)).
1631 list add:(MenuDesc separator).
1633 (inst := view layout) notNil ifTrue:[ inst := inst displayString ].
1634 list add:(MenuDesc title:'layout' value:inst).
1636 (inst := view transformation) notNil ifTrue:[ inst := inst displayString ].
1637 list add:(MenuDesc title:'transformation' value:inst).
1639 ^ MenuDesc buildFromList:list onGC:aMenu
1642 submenuInspector:aMenu
1643 "builds and returns the inspector submenu"
1645 |view list n names label value indices|
1647 view := self selectedView.
1648 view isNil ifTrue:[^ nil].
1650 n := view class instSize.
1651 n > 0 ifFalse:[^ nil ].
1653 list := OrderedCollection new:n.
1654 names := view class allInstVarNames.
1655 indices := (1 to:names size) asArray.
1656 names sortWith:indices.
1658 1 to:n do:[:i| |action|
1659 label := (names at:i) printString.
1660 value := view instVarAt:(indices at:i).
1661 value isNil ifTrue:[
1665 value := value displayString contractAtEndTo:40.
1666 action := [(view instVarAt:i) inspect].
1668 list add:(MenuDesc title:label value:value action:action).
1671 ^ MenuDesc buildFromList:list onGC:aMenu
1673 "Modified: / 31-07-2013 / 13:12:52 / cg"
1676 submenuInterface:aMenu
1677 "builds and returns the interface submenu"
1679 |view label inst value list|
1681 view := self selectedView.
1682 view isNil ifTrue:[^ nil].
1684 list := OrderedCollection new.
1686 inst := view controller.
1692 inst == view ifTrue:[
1693 label := '== view itself'
1695 label := inst displayString.
1696 value := [view controller inspect].
1699 list add:(MenuDesc title:'controller' value:label action:value).
1701 inst := view delegate.
1702 inst notNil ifTrue:[
1703 list add:(MenuDesc title:'delegate' value:(inst displayString) action:[ view delegate inspect ]).
1706 inst := view application.
1708 inst notNil ifTrue:[
1711 list add:(MenuDesc title:'application' value:inst action:[ view application inspect ]).
1713 topAppl := inst topApplication.
1715 (topAppl notNil and:[topAppl ~~ inst]) ifTrue:[
1716 list add:(MenuDesc title:'topApplication' value:topAppl action:[ inst topApplication inspect ]).
1719 list add:(MenuDesc separator).
1721 (view respondsTo:#'model') ifTrue:[
1725 ifTrue:[ label := value := nil ]
1726 ifFalse:[ label := inst displayString.
1727 label := label,(self aspectLabelFor:inst inApplicationOf:view).
1728 value := [ view model inspect ].
1731 list add:(MenuDesc title:'model' value:label action:value).
1733 (inst notNil and:[view respondsTo:#modelInterface]) ifTrue:[
1734 view modelInterface keysAndValuesDo:[:key : val|
1735 val isNil ifTrue:[ label := nil ]
1736 ifFalse:[ label := val displayString ].
1738 list add:(MenuDesc title:(' - ', key) value:label ).
1743 (view respondsTo:#enableChannel) ifTrue:[
1744 inst := view enableChannel.
1746 inst isNil ifTrue:[ label := value := nil ]
1747 ifFalse:[ label := inst displayString.
1748 label := label,(self aspectLabelFor:inst inApplicationOf:view).
1749 value := [ view enableChannel inspect ].
1752 list add:(MenuDesc title:'enableChannel' value:label action:value).
1755 #( #action #pressAction #releaseAction ) do:[:actionSelector |
1756 (view respondsTo:actionSelector) ifTrue:[
1757 inst := view perform:actionSelector.
1760 ifTrue:[ label := value := nil ]
1761 ifFalse:[ label := inst displayString.
1762 value := [ (view perform:actionSelector) inspect ].
1765 list add:(MenuDesc title:actionSelector"'action'" value:label action:value).
1769 list last isSeparator ifFalse:[ list add:(MenuDesc separator) ].
1771 (view respondsTo:#listHolder) ifTrue:[
1772 inst := view listHolder.
1774 inst isNil ifTrue:[ label := value := nil ]
1775 ifFalse:[ label := inst class printString.
1776 label := label,(self aspectLabelFor:inst inApplicationOf:view).
1777 value := [ view listHolder inspect ].
1779 list add:(MenuDesc title:'listHolder' value:label action:value).
1782 (view respondsTo:#list) ifTrue:[
1785 inst isNil ifTrue:[ label := value := nil ]
1786 ifFalse:[ label := '%1 [%2]' bindWith:(inst class printString) with:(inst size).
1787 label := label,(self aspectLabelFor:inst inApplicationOf:view).
1788 value := [ view list inspect ].
1791 list add:(MenuDesc title:'list' value:label action:value).
1794 list last isSeparator ifTrue:[ list removeLast ].
1795 ^ MenuDesc buildFromList:list onGC:aMenu
1797 "Modified: / 31-07-2013 / 13:09:55 / cg"
1800 submenuVisibility:aMenu
1801 "builds and returns the geometry submenu"
1805 view := self selectedView.
1806 view isNil ifTrue:[^ nil].
1808 list := OrderedCollection new.
1810 list add:(MenuDesc title:'device' value:(view device printString)).
1811 list add:(MenuDesc title:'drawableId' value:(view id)).
1812 list add:(MenuDesc title:'gcId' value:(view gcId)).
1814 list add:(MenuDesc separator).
1816 list add:(MenuDesc title:'shown' value:(view shown)).
1817 list add:(MenuDesc title:'realized' value:(view realized)).
1819 list add:(MenuDesc separator).
1821 list add:(MenuDesc title:'hiddenOnRealize' value:(view isHiddenOnRealize)).
1823 (value := view visibilityChannel) isNil ifTrue:[
1824 list add:(MenuDesc title:'visibilityChannel' value:'------').
1826 list add:(MenuDesc title:'visibilityChannel'
1827 value:(value displayString)
1828 action:[view visibilityChannel inspect]).
1831 ^ MenuDesc buildFromList:list onGC:aMenu
1834 !ViewTreeInspectorApplication methodsFor:'private'!
1836 aspectLabelFor:aModel inApplicationOf:aView
1839 aModel isNil ifTrue:[^ ''].
1840 aView isNil ifTrue:[^ ''].
1841 (app := aView application) isNil ifTrue:[^ ''].
1842 app builder bindings keysAndValuesDo:[:aspect :value |
1843 value == aModel ifTrue:[^ ' [aspect: ',aspect,']'].
1845 app class allInstVarNames do:[:nm |
1846 (app instVarNamed:nm) == aModel ifTrue:[^ ' [instvar: ',nm,']']
1851 "Created: / 27-04-2012 / 14:22:09 / cg"
1855 |rootView focusView|
1857 rootView := model rootView.
1859 (rootView notNil and:[rootView shown]) ifTrue:[
1860 focusView := rootView windowGroup focusView.
1862 focusView isNil ifTrue:[^ self ].
1864 self selectView:focusView
1868 |currentItem viewItem|
1870 currentItem := model selectedItem.
1872 (currentItem notNil and:[currentItem widget == aView]) ifTrue:[
1875 viewItem := model listOfItems recursiveDetect:[:el| el widget == aView ].
1877 viewItem notNil ifTrue:[
1878 model selectItem:viewItem.
1882 setRootItem:aRootItemOrNil
1885 aRootItemOrNil isNil ifTrue:[
1888 "/ expand tree to level 3
1889 aRootItemOrNil do:[:aRootChild|
1890 aRootChild do:[:aSubChild| aSubChild expand ].
1893 aRootItemOrNil expand.
1895 process isNil ifTrue:[
1896 theProcess := process :=
1899 |update testModeChannel|
1902 testModeChannel := model testModeChannel.
1904 [process == theProcess] whileTrue:[
1905 Delay waitForSeconds:0.5.
1907 (treeView notNil and:[process == theProcess and:[treeView shown]]) ifTrue:[
1908 (testModeChannel value == true and:[followFocusChannel value == true]) ifTrue:[
1909 self selectFocusView.
1912 self updateShownStatus.
1914 update := update not.
1918 priority:(Processor userSchedulingPriority).
1919 theProcess name:'ViewTreeInspector - Focus Follower'.
1923 model rootItem:aRootItemOrNil.
1925 "Modified: / 25-07-2013 / 12:03:44 / cg"
1929 |rootItem min max visState listIdx visY0 visY1 height damage|
1931 rootItem := model rootItem.
1932 (rootItem notNil and:[rootItem widget shown]) ifFalse:[^ self].
1937 rootItem recursiveEachVisibleItemDo:[:anItem|
1938 visState := (anItem widget shown).
1940 visState ~~ anItem isDrawnShown ifTrue:[
1941 anItem isDrawnShown:visState.
1942 listIdx := treeView identityIndexOf:anItem.
1944 listIdx > 0 ifTrue:[
1945 max := max max:listIdx.
1946 min := min min:listIdx.
1950 max < min ifTrue:[^ self].
1953 visY0 := (treeView yVisibleOfLine:min) max:0.
1954 visY1 := (treeView yVisibleOfLine:max) min:(treeView height).
1955 height := visY1 - visY0.
1958 treeView shown ifTrue:[
1959 damage := Rectangle left:0 top:visY0 width:(treeView width) height:height.
1960 treeView invalidateDeviceRectangle:damage repairNow:false.
1965 !ViewTreeInspectorApplication methodsFor:'selection'!
1968 "answer the selected view or nil"
1972 item := model selectedItem.
1973 item notNil ifTrue:[ ^ item widget ].
1977 !ViewTreeInspectorApplication methodsFor:'testing'!
1979 resolveApplicationClassFor:aTreeItem
1980 aTreeItem isApplicationClass ifTrue:[
1981 ^ aTreeItem applicationClass
1986 selectedComponentHasChildren
1989 item := model selectedItem.
1990 ^ (item notNil and:[item hasChildren])
1993 !ViewTreeInspectorApplication methodsFor:'user operations'!
1998 #model browse model class
1999 #application browse application class
2000 #controller browse controller class
2004 (inst := self objectToInspectOrBrowse:what) isNil ifTrue:[^ self].
2005 inst class browserClass openInClass:(inst class) selector:nil
2007 "Modified: / 28-08-2013 / 23:57:42 / cg"
2010 doBrowseWindowSpecMethod
2013 mthd := self windowSpecMethodOfSelection.
2014 NewSystemBrowser openInClass:mthd mclass selector:mthd selector
2018 model catchEvents:true.
2019 isCatchingEventsChannel value:true.
2020 "/ ((builder componentAt:'toolbarMenu') itemAt:#doUncatchEvents)
2022 "/ label:(self class releaseViewIcon);
2023 "/ activeHelpKey:#doUncatchEvents.
2027 "open debugger on the window process"
2031 view := self selectedView.
2032 view isNil ifTrue:[^ nil].
2034 Debugger openOn:view windowGroup process
2038 "destroy the current selected view"
2042 item := model selectedItem.
2043 item isNil ifTrue:[ ^ self].
2045 parent := item parent.
2047 parent isNil ifTrue:[
2049 model withSelectionHiddenDo:[item deleteAll].
2053 model withSelectionHiddenDo:[
2056 idx := parent identityIndexOf:item.
2058 idx == parent size ifTrue:[
2059 nsel := parent at:(idx - 1) ifAbsent:parent
2061 nsel := parent at:(idx + 1)
2066 parent isLayoutContainer ifTrue:[
2067 parent widget sizeChanged:nil
2076 mthd := self windowSpecMethodOfSelection.
2077 UIPainter openOnClass:mthd mclass andSelector:mthd selector
2081 "flash the selected view"
2085 view := self selectedView.
2086 view isNil ifTrue:[ ^ self].
2089 model withSelectionHiddenDo:[
2090 view perform:#flash ifNotUnderstood:nil.
2098 #group inspect windowGroup
2099 #model inspect model
2100 #application inspect application
2101 #controller inspect controller
2102 #process inspect application's process
2107 (inst := self objectToInspectOrBrowse:what) isNil ifTrue:[^ self].
2110 "Modified: / 28-08-2013 / 23:58:27 / cg"
2113 doOpenProcessMonitor
2114 (ProcessMonitorV2 ? ProcessMonitor) open
2116 "Created: / 25-07-2013 / 12:34:23 / cg"
2120 "pick a window's topView"
2122 |screen clickedView topWindow cursor|
2126 cursor := Cursor fromImage:(self class crossHairIcon).
2128 screen := Screen current.
2129 clickedView := screen viewFromPoint:(screen pointFromUserShowing:cursor).
2130 clickedView isNil ifTrue:[^ self].
2132 topWindow := clickedView topView.
2134 ( topWindow == Screen current rootView
2135 or:[topWindow == self window topView]
2140 self showWindow:clickedView.
2146 model rootView notNil ifTrue:[
2147 model rootView withAllSubViewsDo:[:v | v "redraw; "invalidate].
2151 doSelectNextElementStartingIn:anItem forWhich:aBlock
2152 |startItem firstFound searchNext|
2154 startItem := model last.
2155 searchNext := startItem notNil.
2158 anItem recursiveDo:[:el|
2159 el == startItem ifTrue:[
2162 (aBlock value:el) ifTrue:[
2163 searchNext ifFalse:[^ model selectItem:el].
2165 firstFound isNil ifTrue:[
2171 firstFound notNil ifTrue:[
2173 model selectItem:firstFound
2177 doSelectNextOfApplicationClass:aClass startingIn:anItem
2178 self doSelectNextElementStartingIn:anItem forWhich:[:el | (self resolveApplicationClassFor:el) == aClass].
2181 doSelectNextOfClass:aClass startingIn:anItem
2182 self doSelectNextElementStartingIn:anItem forWhich:[:el | el widget class == aClass].
2186 "release the inspected window (no longer catch its events)"
2188 model catchEvents:false.
2189 isCatchingEventsChannel value:false.
2190 "/ ((builder componentAt:'toolbarMenu') itemAt:#doUncatchEvents)
2191 "/ label:(self class releaseViewIcon);
2193 "/ activeHelpKey:#doCatchEvents.
2198 "release current picked window and contained subwindows"
2200 self setRootItem:nil.
2203 objectToInspectOrBrowse:what
2206 #group inspect windowGroup
2207 #model inspect model
2208 #application inspect application
2209 #controller inspect controller
2210 #process inspect application's process
2214 view := self selectedView.
2215 view isNil ifTrue:[^ nil].
2217 what == #group ifTrue:[ inst := view windowGroup ]
2218 ifFalse:[what == #model ifTrue:[ inst := view model ]
2219 ifFalse:[what == #application ifTrue:[ inst := view application ]
2220 ifFalse:[what == #controller ifTrue:[ inst := view controller ]
2221 ifFalse:[what == #process ifTrue:[ inst := view windowGroup process ]
2222 ifFalse:[what == #sensor ifTrue:[ inst := view sensor ]
2223 ifFalse:[inst := view ]]]]]].
2225 (inst isNil and:[what == #application]) ifTrue:[
2226 inst := view topView
2230 "Modified: / 28-08-2013 / 23:58:27 / cg"
2234 HTMLDocumentView openFullOnDocumentationFile:'tools/misc/TOP.html#VIEWTREEINSPECTOR'
2238 "show a particular window's topView hierarchy,
2239 select the given view"
2243 topWindow := aView topView.
2246 self setRootItem:(ViewTreeItem buildViewsFrom:topWindow).
2247 self selectView:aView.
2250 !ViewTreeInspectorApplication::MenuDesc class methodsFor:'building'!
2252 buildFromList:aList onGC:aMenu
2253 |tabSpec menu w menuPanel|
2256 aList do:[:el| w := w max:(el widthOn:aMenu) ].
2258 tabSpec := TabulatorSpecification new.
2259 tabSpec unit:#pixel.
2260 tabSpec positions:#(0 1.5 ).
2261 tabSpec align:#(#left #left).
2264 tabSpec positions:(Array with:0 with:w).
2269 menu addItem:(el asMenuItemWithTabulatorSpecification:tabSpec).
2271 menuPanel := MenuPanel menu:menu.
2275 !ViewTreeInspectorApplication::MenuDesc class methodsFor:'instance creation'!
2281 title:aTitle value:aValue
2282 ^ self title:aTitle value:aValue action:nil
2285 title:aTitle value:aValue action:anAction
2286 ^ self new title:aTitle value:aValue action:anAction
2289 !ViewTreeInspectorApplication::MenuDesc methodsFor:'accessing'!
2295 !ViewTreeInspectorApplication::MenuDesc methodsFor:'building'!
2297 asMenuItemWithTabulatorSpecification:aTabSpec
2300 title isNil ifTrue:[ ^ MenuItem label:value ]. "/ separator
2302 array := Array with:(title, ':') with:'------'.
2304 value notNil ifTrue:[
2305 array at:2 put:(value printString, ' ')
2309 label:(MultiColListEntry fromStrings:array tabulatorSpecification:aTabSpec)
2313 !ViewTreeInspectorApplication::MenuDesc methodsFor:'instance creation'!
2315 title:aTitle value:aValue action:anAction
2318 title := aTitle withoutSeparators.
2321 aValue notNil ifTrue:[
2322 value := aValue printString.
2324 value size > 70 ifTrue:[
2325 value := value copyFrom:1 to:70.
2326 value := value, '...'
2331 !ViewTreeInspectorApplication::MenuDesc methodsFor:'queries'!
2338 title isNil ifTrue:[^ 5]. "/ separator
2342 !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'building'!
2344 buildViewsFrom:aView
2345 "build the items starting from a source view;
2348 |item subViews subItems|
2350 aView isNil ifTrue:[^ nil].
2352 item := self forView:aView.
2353 subViews := aView subViews.
2355 subViews notEmptyOrNil ifTrue:[
2356 subItems := OrderedCollection new.
2357 subViews do:[:aSubView|
2358 subItems add:(self buildViewsFrom:aSubView).
2360 item children:subItems.
2365 !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'documentation'!
2369 ViewTreeItems represants a pickable object within a ViewTreeModel.
2370 The class is used to build up the hierarchical tree.
2372 [Instance variables:]
2373 widget <View> the widget represented by the item
2374 spec <UISpecification> the UISpecification or nil
2377 HandleExtent <Point> keeps the extent of a handle
2393 !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'initialization'!
2396 "set the extent of the Handle
2398 HandleExtent := 6@6.
2401 !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'instance creation'!
2406 item := self basicNew initialize.
2412 self error:'not allowed'.
2416 on:aView withSpec:aSpec
2419 item := self basicNew initialize.
2420 item on:aView withSpec:aSpec.
2424 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing'!
2429 widget notNil ifTrue:[
2430 appl := widget application.
2431 appl notNil ifTrue:[^ appl class ].
2437 "returns true if the last display operations was done during the widget was shown
2442 isDrawnShown:aBoolean
2443 isDrawnShown := aBoolean.
2447 "returns the widget assigned to the root or nil
2453 "returns the spec-class assigned to the item
2459 "returns the assigned treeModel, an instance of ViewTreeModel
2465 "returns the widget assigned to the item
2470 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing layout'!
2472 boundsRelativeToRoot
2473 "returns the bounds relative to the root widget
2475 ^ self originRelativeToRoot extent:(widget extent)
2478 cornerRelativeToRoot
2479 "returns the corner relative to the root widget
2481 ^ self originRelativeToRoot + (widget extent)
2485 "returns the extent of the widget
2491 "returns the type of layout assigned to the wiget; nil if the
2492 superView cannot resize its sub widgets
2494 |layout specClass superView|
2496 (superView := widget superView) isNil ifTrue:[
2500 specClass := superView specClass.
2502 (specClass notNil and:[specClass isLayoutContainer]) ifTrue:[
2503 ^ specClass canResizeSubComponents ifTrue:[#Extent] ifFalse:[nil]
2506 (layout := widget geometryLayout) isNil ifTrue:[
2510 layout isLayout ifTrue:[
2511 layout isLayoutFrame ifTrue:[ ^ #LayoutFrame ].
2512 layout isAlignmentOrigin ifTrue:[ ^ #AlignmentOrigin ].
2513 layout isLayoutOrigin ifTrue:[ ^ #LayoutOrigin ].
2515 layout isRectangle ifTrue:[ ^ #Rectangle ].
2516 layout isPoint ifTrue:[ ^ #Point ].
2519 Transcript showCR:'UNSUPPORTRD LAYOUT: ', layout printString.
2523 originRelativeToRoot
2524 "returns the origin relative to the root widget
2526 ^ widget originRelativeTo:(self rootView)
2529 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing optimize'!
2532 "redefined: optimize
2538 |subViews list item|
2540 children size ~~ 0 ifTrue:[
2543 isExpanded := false.
2544 subViews := widget subViews.
2546 subViews size == 0 ifTrue:[^ false].
2548 list := OrderedCollection new.
2550 subViews do:[:aSubView|
2551 item := self class buildViewsFrom:aSubView.
2560 "redefined: returns list of children
2565 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'displaying'!
2567 additionalLabelForItem:anItem
2568 "answer an additional label for an Item"
2570 parent notNil ifTrue:[
2571 ^ parent additionalLabelForItem:anItem
2576 displayIcon:anIcon atX:x y:y on:aGC
2579 super displayIcon:anIcon atX:x y:y on:aGC.
2581 self exists ifFalse:[
2582 aGC paint:(Color red).
2585 y1 := y + anIcon height - 2.
2591 aGC displayLineFromX:x0 y:y0 toX:(x0 + w) y:y1.
2592 aGC displayLineFromX:x0 y:y1 toX:(x0 + w) y:y0.
2598 displayOn:aGC x:x y:y h:h
2599 |labelHeight additionalName label isValidAndShown|
2601 label := self label.
2602 label isEmptyOrNil ifTrue:[^ self].
2604 widget id isNil ifTrue:[
2605 isDrawnShown := false.
2607 self exists ifFalse:[
2608 xOffsetAdditionalName := nil.
2610 isValidAndShown := false.
2612 isValidAndShown := widget shown.
2614 isValidAndShown ifFalse:[
2615 label := Text string:label emphasis:#italic.
2616 label colorizeAllWith:Color gray.
2619 labelHeight := self heightOn:aGC.
2620 self displayLabel:label h:labelHeight on:aGC x:x y:y h:h.
2622 xOffsetAdditionalName notNil ifTrue:[
2623 additionalName := self additionalLabelForItem:self.
2625 additionalName notNil ifTrue:[
2626 self displayLabel:additionalName
2627 h:labelHeight on:aGC
2628 x:(x + xOffsetAdditionalName)
2632 xOffsetAdditionalName := nil.
2637 recursiveAdditionalNameBehaviourChanged
2638 width := xOffsetAdditionalName := nil.
2640 children notNil ifTrue:[
2641 children do:[:each| each recursiveAdditionalNameBehaviourChanged ]
2646 "return the width of the receiver, if it is to be displayed on aGC
2650 width isNil ifTrue:[
2651 width := self widthOf:(self label) on:aGC.
2654 additionalName := self additionalLabelForItem:self.
2656 additionalName notNil ifTrue:[
2657 xOffsetAdditionalName := width + 10.
2658 width := xOffsetAdditionalName + (self widthOf:additionalName on:aGC).
2661 xOffsetAdditionalName := nil.
2667 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'enumerating'!
2669 handlesDo:aTwoArgAction
2670 "evaluate the two arg block on each handle; the arguments to the block is
2671 the rectangle relative to the rootView and the handle type which is
2672 set to nil if not resizeable.
2674 TYPES: type position( X - Y )
2675 -------------------------
2685 nil ** handle not pickable **
2687 |type relOrg relCrn maxExt rootView w h
2688 xL "{ Class:SmallInteger }"
2689 xC "{ Class:SmallInteger }"
2690 xR "{ Class:SmallInteger }"
2691 yT "{ Class:SmallInteger }"
2692 yC "{ Class:SmallInteger }"
2693 yB "{ Class:SmallInteger }"
2695 rootView := self rootView.
2696 relOrg := widget originRelativeTo:rootView.
2697 relOrg isNil ifTrue:[ ^ self ]. "/ widget destroyed
2699 relOrg := relOrg - (HandleExtent // 2).
2700 relCrn := relOrg + widget extent.
2701 maxExt := rootView extent - HandleExtent.
2703 xL := relOrg x max:0.
2704 xR := relCrn x min:(maxExt x).
2707 yT := relOrg y max:0.
2708 yB := relCrn y min:(maxExt y).
2711 type := self layoutType.
2712 w := HandleExtent x.
2713 h := HandleExtent y.
2715 (type == #LayoutFrame or:[type == #Rectangle]) ifTrue:[
2716 aTwoArgAction value:(Rectangle left:xL top:yT width:w height:h) value:#LT.
2717 aTwoArgAction value:(Rectangle left:xL top:yC width:w height:h) value:#LC.
2718 aTwoArgAction value:(Rectangle left:xL top:yB width:w height:h) value:#LB.
2719 aTwoArgAction value:(Rectangle left:xC top:yT width:w height:h) value:#CT.
2720 aTwoArgAction value:(Rectangle left:xC top:yB width:w height:h) value:#CB.
2721 aTwoArgAction value:(Rectangle left:xR top:yT width:w height:h) value:#RT.
2722 aTwoArgAction value:(Rectangle left:xR top:yC width:w height:h) value:#RC.
2723 aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:#RB.
2727 aTwoArgAction value:(Rectangle left:xL top:yT width:w height:h) value:nil.
2728 aTwoArgAction value:(Rectangle left:xL top:yB width:w height:h) value:nil.
2729 aTwoArgAction value:(Rectangle left:xR top:yT width:w height:h) value:nil.
2731 type == #Extent ifTrue:[
2732 aTwoArgAction value:(Rectangle left:xC top:yB width:w height:h) value:#CB.
2733 aTwoArgAction value:(Rectangle left:xR top:yC width:w height:h) value:#RC.
2734 aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:#RB.
2737 aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:nil.
2740 recursiveEachVisibleItemDo:anOneArgBlock
2741 "recursive evaluate the block on each child which is visible
2743 (isExpanded and:[children size > 0]) ifTrue:[
2744 children do:[:aChild|
2745 anOneArgBlock value:aChild.
2746 aChild recursiveEachVisibleItemDo:anOneArgBlock.
2751 subViewsDo:aOneArgBlock
2752 "evaluate aBlock for all subviews other than InputView's
2756 subViews := widget subViews.
2758 subViews notNil ifTrue:[
2759 subViews do:aOneArgBlock
2763 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'initialization'!
2770 "setup default attributes
2773 isDrawnShown := false.
2774 isExpanded := false.
2775 children := OrderedCollection new.
2778 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations delete'!
2781 "delete self and all contained items; the assigned views are destroyed
2782 in case of rootView, only the children are deleted
2784 parent isHierarchicalItem ifTrue:[
2795 "delete all contained items; the assigned views are destroyed
2797 children size == 0 ifTrue:[^ self].
2800 self nonCriticalDo:[:el| el widget destroy ].
2805 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations layout'!
2808 "convert the layout of the widget to a LayoutFrame;
2810 |extent layout newLyt lftFrc lftOff topFrc topOff|
2812 layout := widget geometryLayout.
2814 layout isNil ifTrue:[
2815 ^ widget bounds asLayout
2818 layout isLayout ifFalse:[
2819 layout isRectangle ifTrue:[
2820 ^ LayoutFrame leftOffset:(layout left) rightOffset:(layout right)
2821 topOffset:(layout top) bottomOffset:(layout bottom)
2823 layout isPoint ifTrue:[
2824 extent := widget extent.
2825 ^ LayoutFrame leftOffset:(layout x) rightOffset:(layout x + extent x)
2826 topOffset:(layout y) bottomOffset:(layout y + extent y)
2829 Transcript showCR:'UNSUPPORTRD LAYOUT: ', layout printString.
2833 layout isLayoutFrame ifTrue:[ ^ layout copy ].
2835 lftFrc := layout leftFraction.
2836 lftOff := layout leftOffset.
2837 topFrc := layout topFraction.
2838 topOff := layout topOffset.
2839 extent := widget extent.
2841 newLyt := LayoutFrame leftFraction:lftFrc offset:lftOff
2842 rightFraction:lftFrc offset:(lftOff + extent x)
2843 topFraction:topFrc offset:topOff
2844 bottomFraction:topFrc offset:(topOff + extent y).
2846 ( layout isAlignmentOrigin
2847 and:[(layout leftAlignmentFraction ~= 0 or:[layout topAlignmentFraction ~= 0])]
2851 svRc := widget superView viewRectangle.
2852 prBd := widget preferredBounds.
2854 dlta := ( ((layout rectangleRelativeTo:svRc preferred:prBd) corner)
2855 - ((newLyt rectangleRelativeTo:svRc preferred:prBd) corner)
2858 newLyt leftOffset:(lftOff + dlta x).
2859 newLyt rightOffset:(lftOff + extent x + dlta x).
2860 newLyt topOffset:(topOff + dlta y).
2861 newLyt bottomOffset:(topOff + extent y + dlta y).
2867 "move the widget n pixele left and right
2871 self isMoveable ifFalse:[ ^ self ].
2873 (layout := widget geometryLayout) isNil ifTrue:[
2875 widget origin:(widget origin + (l@t)).
2879 layout := layout copy.
2881 layout isLayout ifTrue:[
2882 layout leftOffset:(layout leftOffset + l)
2883 topOffset:(layout topOffset + t).
2885 layout isLayoutFrame ifTrue:[
2886 layout rightOffset:(layout rightOffset + l).
2887 layout bottomOffset:(layout bottomOffset + t).
2891 layout isRectangle ifTrue:[
2892 layout setLeft:(layout left + l).
2893 layout setTop:(layout top + t).
2895 layout isPoint ifFalse:[^ self].
2896 layout x:(layout x + l) y:(layout y + t).
2899 widget geometryLayout:layout.
2902 resizeLeft:l top:t right:r bottom:b
2903 "resize the widget measured in pixels
2907 self isResizeable ifFalse:[
2911 (layout := widget geometryLayout) isNil ifTrue:[
2913 (r == l and:[b == t]) ifFalse:[
2914 widget extent:(widget computeExtent + ((r-l) @ (b-t))).
2919 layout isLayout ifTrue:[
2920 layout := layout copy.
2922 layout leftOffset:(layout leftOffset + l)
2923 topOffset:(layout topOffset + t).
2925 layout isLayoutFrame ifTrue:[
2926 layout bottomOffset:(layout bottomOffset + b).
2927 layout rightOffset:(layout rightOffset + r).
2930 layout isRectangle ifFalse:[^ self].
2931 layout := layout copy.
2933 layout left:(layout left + l)
2934 right:(layout right + r)
2935 top:(layout top + t)
2936 bottom:(layout bottom + b).
2938 widget geometryLayout:layout.
2941 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations update'!
2950 list isNil ifTrue:[list := OrderedCollection new].
2954 list notNil ifTrue:[
2955 list do:[:el| self remove:el ].
2959 updateFromChildren:mergedList
2960 "update my children against the list of items derived from
2964 mergedList size == 0 ifTrue:[ ^ self removeAll ].
2965 children size == 0 ifTrue:[ ^ self addAll:mergedList ].
2968 self nonCriticalDo:[:el| |wdg|
2970 mergedList detect:[:e2| e2 widget == wdg ] ifNone:[ self remove:el ].
2973 mergedList keysAndValuesDo:[:i :el| |wdg e2|
2976 e2 := self at:i ifAbsent:nil.
2978 (e2 isNil or:[e2 widget ~~ wdg]) ifTrue:[
2979 self add:el beforeIndex:i
2985 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'printing & storing'!
2988 "get the icon used for presentation
2992 specClass := self specClass.
2993 specClass isNil ifTrue:[^ nil].
2995 model := self treeModel.
2997 model notNil ifTrue:[
2998 ^ model iconAt:specClass ifNonePut:[specClass icon]
3004 "get the label used for presentation
3010 "append a a printed representation of the item to aStream
3012 aStream nextPutAll:(self string)
3018 ^ widget class name.
3021 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'queries'!
3024 "returns true if the layout of the widget can be changed and the
3025 layout is not organized by its superView
3030 canResizeSubComponents
3031 "returns true if the widget can resize its sub components
3035 specClass := self specClass.
3037 specClass notNil ifTrue:[
3038 ^ specClass canResizeSubComponents
3044 widget id notNil ifTrue:[^ true ].
3046 exists ~~ false ifTrue:[
3049 widget superView notNil ifTrue:[
3050 (parent isHierarchicalItem and:[parent exists]) ifTrue:[
3051 exists := (parent widget subViews includesIdentical:widget).
3061 cls := widget class.
3063 ^ ( cls == ApplicationSubView
3064 or:[cls == ApplicationWindow
3065 or:[cls == SubCanvas]]
3072 model := self treeModel.
3073 model notNil ifTrue:[^ model isSelected:self].
3077 supportsSubComponents
3078 "returns true if the widget supports sub components
3082 widget isScrollWrapper ifTrue:[
3085 specClass := self specClass.
3087 specClass notNil ifTrue:[
3088 ^ specClass supportsSubComponents
3093 !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'testing'!
3096 "returns true if the widget is in a layout container
3100 sv := widget superView.
3103 specClass := sv specClass.
3105 specClass notNil ifTrue:[
3106 ^ specClass isLayoutContainer
3113 "answer whether corresponding view instances of the spec class can contain
3114 (and arrange) other view
3118 specClass := self specClass.
3120 specClass notNil ifTrue:[
3121 ^ specClass isLayoutContainer
3127 "returns true if the widget is not in a layout container
3129 self isInLayoutContainer ifFalse:[
3130 ^ widget superView notNil
3136 "returns true if the widget is resizeable
3140 sv := widget superView.
3143 specClass := sv specClass.
3145 specClass notNil ifTrue:[
3146 ^ specClass canResizeSubComponents
3152 !ViewTreeInspectorApplication::ViewTreeModel class methodsFor:'documentation'!
3156 Instances of ViewTreeModel can be used as model on a View and all
3157 it contained subviews for a HierarchicalListView.
3158 The model keeps two values, the hierarchical representation of the views
3159 and subviews (ViewTreeItems) and the selection, a list of selected ViewTreeItems's.
3160 It shows the selected items highlighted.
3163 [Instance variables:]
3164 lockSema <Semaphore> lock selection notifications and redraws
3166 testModeChannel <ValueHolder> true, than running in test mode.
3168 hasTargetWidgetChannel <ValueHolder> true, than any target view is grapped
3170 selection <Sequence or nil> selected items or nil
3172 hiddenLevel <Integer> internal use; redrawing the selection
3173 only is done if the counter is 0.
3175 listOfItems <HierarchicalList> hiearchical list build from existing items.
3177 selectedSuperItems <Sequence> list of selected super items; items selected
3178 but not contained in another selected item.
3180 inputEventAction <Action> called for each InputEvent
3182 mappedViewAction <Action> called for a new mapped view which
3183 can not be found in the current item list.
3185 beforeSelectionChangedAction <Action> called before the selection changed
3197 example 1: pick any window and show views and contained views
3199 |top sel model panel|
3201 model := ViewTreeModel new.
3202 top := StandardSystemView new; extent:440@400.
3203 sel := ScrollableView for:HierarchicalListView miniScroller:true origin:0.0@0.0 corner:1.0@1.0 in:top.
3206 panel := HorizontalPanelView origin:0.0@1.0 corner:1.0@1.0 in:top.
3208 panel horizontalLayout:#fitSpace.
3210 Button label:'Exit' action:[model rootItem:nil. top destroy] in:panel.
3211 Button label:'Pick Views' action:[ |win|
3212 ( (win := Screen current viewFromUser) notNil
3213 and:[(win := win topView) ~~ Screen current rootView
3216 model rootItem:(ViewTreeItem buildViewsFrom:win)
3222 sel multipleSelectOk:true.
3223 sel list:model listOfItems.
3227 sel doubleClickAction:[:i| |el|
3228 el := model listOfItems at:i.
3229 el spec notNil ifTrue:[ el spec inspect ] ifFalse:[ el widget inspect ]
3231 sel indicatorAction:[:i| (model listOfItems at:i) toggleExpand ].
3233 model inputEventAction:[:anEvent| |item|
3234 anEvent isButtonEvent ifTrue:[
3235 anEvent isButtonPressEvent ifTrue:[
3236 model selectedItem:(model listOfItems detectItemRespondsToView:(anEvent view)).
3238 anEvent type == #'buttonMultiPress:x:y:' ifTrue:[
3239 (item := model selectedItem) notNil ifTrue:[item widget inspect]
3246 [[top shown] whileTrue:[Delay waitForSeconds:0.5]. model rootItem:nil] forkAt:8
3252 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing'!
3254 application:anApplication
3255 listOfItems application:anApplication.
3258 catchEvents:aBoolean
3259 catchEvents := aBoolean.
3261 self redrawUnselected:selection andLock:false checkTestMode:false.
3266 "Return a XPath like path to this item"
3270 selection isNil ifTrue:[ ^ nil ].
3271 selection isCollection ifTrue:[
3272 selection size ~~ 1 ifTrue:[ ^ nil ].
3273 view := selection anElement widget.
3275 view := selection widget.
3277 views := OrderedCollection new.
3278 [ view notNil ] whileTrue:[
3280 view := view superView.
3283 ^ String streamContents:[ :s|
3284 views reverseDo:[:each |
3286 s nextPutAll: each name asString "storeString".
3290 "Created: / 19-05-2014 / 18:15:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
3294 "get the rootItem the event viewer is established on
3300 "set the rootItem the event viewer is established on
3304 timedUpdateTask := nil.
3308 anItem notNil ifTrue:[ expanded := anItem isExpanded ]
3309 ifFalse:[ expanded := false ].
3312 listOfItems root:anItem.
3314 anItem notNil ifTrue:[
3315 timedUpdateTask := Process for:[ self timedUpdateTaskCycle ] priority:8.
3316 timedUpdateTask name:'Update'.
3317 timedUpdateTask resume.
3321 (expanded and:[anItem notNil]) ifTrue:[
3328 "get the top widget the event viewer is established on, a View
3330 ^ listOfItems rootView
3333 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing actions'!
3335 beforeSelectionChangedAction
3336 "none argument action which is called before
3337 the selection changed
3339 ^ beforeSelectionChangedAction
3342 beforeSelectionChangedAction:aNoneArgBlock
3343 "none argument action which is called before
3344 the selection changed
3346 beforeSelectionChangedAction := aNoneArgBlock.
3350 "called for each input event; the argument to the action is the WindowEvent
3355 inputEventAction:aOneArgActionTheEvent
3356 "called for each input event; the argument to the action is the WindowEvent
3358 inputEventAction := aOneArgActionTheEvent.
3362 "called for a new mapped view which can not be found
3363 in the current item list
3368 mappedViewAction:aOneArgBlockTheMappedView
3369 "called for a new mapped view which can not be found
3370 in the current item list
3372 mappedViewAction := aOneArgBlockTheMappedView
3375 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing look'!
3377 iconAt:aKey ifNonePut:aNoneArgBlock
3380 icon := icons at:aKey ifAbsent:nil.
3381 icon notNil ifTrue:[^ icon].
3383 icon := aNoneArgBlock value.
3384 icon isNil ifTrue:[^ nil].
3386 view := self rootView.
3387 view isNil ifTrue:[^ icon].
3389 icon := icon copy onDevice:(view device).
3390 icon isImage ifTrue:[
3391 icon clearMaskedPixels.
3393 icons at:aKey put:icon.
3397 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing visibility'!
3400 "show the selection if signaled; increments hiddenLevel
3401 see: #waitHiddenLevel
3403 (hiddenLevel := hiddenLevel - 1) < 1 ifTrue:[
3405 self invalidateSelection.
3410 "hide the selection until signaled; increments hiddenLevel
3411 see: #signalHiddenLevel
3413 self redrawUnselected:selection andLock:true
3416 withSelectionHiddenDo:aNoneArgumentBlock
3417 "apply block with selection hidden
3420 [ self waitHiddenLevel.
3422 aNoneArgumentBlock value
3424 ] valueNowOrOnUnwindDo:[
3425 self signalHiddenLevel.
3429 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'aspects'!
3431 hasTargetWidgetChannel
3432 "answer the channel which is set to true if a target widget exists"
3434 ^ hasTargetWidgetChannel
3438 "hiearchical list build from existing items"
3444 "boolean holder, which indicates whether the selection will change on click
3446 ^ selectOnClickHolder
3450 "answer a boolean channel which describes the behaviour how to process
3451 events on the target view.
3453 false: all input events are eaten and the selection is shown on the target view.
3454 true: no input events are eaten and no selection is shown on the target view."
3459 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'change & update'!
3462 hasTargetWidgetChannel value:(self rootItem notNil).
3465 timedUpdateTaskCycle
3468 myTaskId := timedUpdateTask.
3470 listOfItems root notNil ifTrue:[
3471 view := listOfItems root widget.
3474 [ view notNil ] whileTrue:[
3475 Delay waitForSeconds:0.5.
3477 (myTaskId == timedUpdateTask and:[view id notNil]) ifFalse:[
3480 (view sensor hasUserEvent:#updateChildren for:self) ifFalse:[
3481 view sensor pushUserEvent:#updateChildren for:self.
3485 timedUpdateTask == myTaskId ifTrue:[
3486 timedUpdateTask := nil.
3487 listOfItems root:nil.
3491 update:something with:someArgument from:aModel
3493 aModel == testModeChannel ifTrue:[
3494 (hiddenLevel == 0 and:[selection size > 0]) ifTrue:[
3495 testModeChannel value ifTrue:[
3496 self redrawUnselected:selection andLock:false checkTestMode:false.
3498 self invalidateSelection.
3503 super update:something with:someArgument from:aModel.
3509 rootItem := listOfItems root.
3510 rootItem isNil ifTrue:[^ self].
3512 rootItem exists ifFalse:[
3513 listOfItems root:nil.
3515 rootItem updateChildren.
3519 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'event processing'!
3521 processEvent:anEvent
3522 "catch and process all WindowEvents for the rootComponent and its contained
3523 widgets; redraw selection in case of damage...
3524 return true, if the event was eaten"
3526 |evView item rootView testMode|
3528 catchEvents ifFalse:[^ false].
3530 evView := anEvent view.
3531 evView isNil ifTrue:[
3532 (anEvent isMessageSendEvent not or:[anEvent receiver ~~ self]) ifTrue:[
3538 rootView := listOfItems rootView.
3539 rootView isNil ifTrue:[ ^ false ].
3541 anEvent isConfigureEvent ifTrue:[
3542 hiddenLevel == 0 ifTrue:[
3543 self redrawUnselected:selection andLock:false.
3548 "/ check whether view is contained within the rootView
3549 (evView == rootView or:[evView isComponentOf:rootView]) ifFalse:[
3553 anEvent isInputEvent ifFalse:[
3554 anEvent isDamage ifTrue:[
3555 hiddenLevel == 0 ifTrue:[self invalidateSelection].
3559 anEvent isMapEvent ifTrue:[
3560 mappedViewAction notNil ifTrue:[
3561 item := listOfItems recursiveDetect:[:el| el widget == evView].
3562 item isNil ifTrue:[ mappedViewAction value:evView ]
3567 anEvent type == #terminate ifTrue:[
3568 item := listOfItems recursiveDetect:[:el| el widget == evView].
3569 item notNil ifTrue:[ self processTerminateForItem:item ].
3574 testMode := testModeChannel value.
3576 anEvent isFocusEvent ifTrue:[
3577 evView == rootView ifTrue:[
3578 self invalidateSelection
3582 anEvent isPointerEnterLeaveEvent ifTrue:[ ^ testMode not ].
3585 inputEventAction notNil ifTrue:[ inputEventAction value:anEvent ].
3587 anEvent isButtonPressEvent ifTrue:[
3588 selectOnClickHolder value ifTrue:[
3589 self selectItem:(listOfItems detectItemRespondsToView:evView).
3594 (hiddenLevel ~~ 0 and:[anEvent isButtonReleaseEvent]) ifTrue:[
3596 self signalHiddenLevel.
3602 processTerminateForItem:anItem
3603 "received terminate for an item
3608 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'initialization'!
3611 "setup the default attributes
3616 lockSema := RecursionLock new.
3617 listOfItems := ItemList new on:self.
3618 selectedSuperItems := #().
3619 icons := IdentityDictionary new.
3620 catchEvents := true.
3622 hasTargetWidgetChannel := false asValue.
3623 selectOnClickHolder := true asValue.
3625 testModeChannel := false asValue.
3626 testModeChannel addDependent:self.
3629 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'private selection'!
3632 "invalidate the current selection
3636 testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode
3639 and:[selection notNil
3640 and:[(topView := listOfItems rootView) notNil
3641 and:[topView shown]]]
3643 topView sensor pushUserEvent:#redrawSelection for:self withArguments:#()
3647 recursiveRepair:theDamages startIn:aView relativeTo:aRootView
3648 "repair all views and contained views, which intersects the damage.
3649 !!!! all damages repaired are removed from the list of damages !!!!
3651 |color relOrg damage subViews repaired
3652 bwWidth "{ Class:SmallInteger }"
3653 x "{ Class:SmallInteger }"
3654 y "{ Class:SmallInteger }"
3655 w "{ Class:SmallInteger }"
3656 h "{ Class:SmallInteger }"
3657 relOrgX "{ Class:SmallInteger }"
3658 relOrgY "{ Class:SmallInteger }"
3659 width "{ Class:SmallInteger }"
3660 height "{ Class:SmallInteger }"
3661 size "{ Class:SmallInteger }"
3663 (aView shown and:[theDamages notEmpty]) ifFalse:[ ^ self ].
3665 subViews := aView subViews.
3667 subViews size ~~ 0 ifTrue:[
3668 subViews reverseDo:[:v| self recursiveRepair:theDamages startIn:v relativeTo:aRootView ].
3669 theDamages isEmpty ifTrue:[ ^ self ].
3672 relOrg := aView originRelativeTo:aRootView.
3673 bwWidth := aView borderWidth.
3674 size := theDamages size.
3676 "/ compute relative origin starting from border left@top
3677 relOrgX := relOrg x - bwWidth.
3678 relOrgY := relOrg y - bwWidth.
3679 width := aView width + bwWidth + bwWidth.
3680 height := aView height + bwWidth + bwWidth.
3682 size to:1 by:-1 do:[:anIndex|
3683 repaired := damage := theDamages at:anIndex.
3685 "/ compute the rectangle into the view
3686 y := damage top - relOrgY.
3687 x := damage left - relOrgX.
3691 x < 0 ifTrue:[ w := w + x. x := 0. repaired := nil ].
3692 y < 0 ifTrue:[ h := h + y. y := 0. repaired := nil ].
3693 x + w > width ifTrue:[ w := width - x. repaired := nil ].
3694 y + h > height ifTrue:[ h := height - y. repaired := nil ].
3696 (w > 0 and:[h > 0]) ifTrue:[
3697 bwWidth ~~ 0 ifTrue:[
3698 color isNil ifTrue:[
3699 "/ must force redraw of border
3700 color := aView borderColor.
3701 aView borderColor:(Color colorId:1).
3702 aView borderColor:color.
3707 (x := x - bwWidth) < 0 ifTrue:[w := w + x. x := 0].
3708 (y := y - bwWidth) < 0 ifTrue:[h := h + y. y := 0].
3710 h > 0 ifFalse:[w := 0]. "/ later testing on width only
3714 aView clearRectangleX:x y:y width:w height:h.
3715 aView exposeX:x y:y width:w height:h
3717 repaired notNil ifTrue:[ theDamages removeFromIndex:anIndex toIndex:anIndex ].
3723 "redraw all items selected
3727 testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode
3730 and:[(size := selection size) > 0
3731 and:[(topView := listOfItems rootView) notNil
3733 and:[(topView sensor hasEvent:#redrawSelection for:self) not]]]]
3743 list size > 0 ifTrue:[
3744 topView paint:(Color black).
3745 topView clippedByChildren:false.
3747 list keysAndValuesReverseDo:[:anIndex :anItem|
3748 (anIndex == 1 and:[size > 1]) ifTrue:[ topView paint:(Color red) ].
3750 anItem handlesDo:[:aRect :what|
3751 what isNil ifTrue:[topView displayRectangle:aRect]
3752 ifFalse:[topView fillRectangle:aRect]
3755 topView clippedByChildren:true.
3760 redrawUnselected:aList andLock:doLock
3761 "redraw all items unselected; if doLock is true, the hiddenLevel
3762 is incremented and thus the select mechanism is locked.
3764 self redrawUnselected:aList andLock:doLock checkTestMode:true.
3767 redrawUnselected:aList andLock:doLock checkTestMode:checkTestMode
3768 "redraw all items unselected; if doLock is true, the hiddenLevel
3769 is incremented and thus the select mechanism is locked.
3771 |rootView damages subViews x y w h|
3774 hiddenLevel := hiddenLevel + 1.
3775 hiddenLevel ~~ 1 ifTrue:[^ self].
3777 hiddenLevel ~~ 0 ifTrue:[^ self].
3779 checkTestMode ifTrue:[
3780 testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode
3784 and:[(rootView := listOfItems rootView) notNil
3785 and:[rootView shown]]
3791 damages := OrderedCollection new:(8 * aList size).
3794 item handlesDo:[:handle :what|
3795 damages reverseDo:[:el|
3796 (el intersects:handle) ifTrue:[
3797 damages removeIdentical:el.
3799 handle left:(handle left min:el left)
3800 right:(handle right max:el right)
3801 top:(handle top min:el top)
3802 bottom:(handle bottom max:el bottom)
3815 rootView clearRectangleX:x y:y width:w height:h.
3816 rootView exposeX:x y:y width:w height:h.
3819 (subViews := rootView subViews) notNil ifTrue:[
3820 subViews reverseDo:[:v| self recursiveRepair:damages startIn:v relativeTo:rootView ].
3825 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'queries'!
3828 "answer false, all input events are eaten and the selection is shown on the target view.
3829 answer true, no input events are eaten and no selection is shown on the target view."
3831 ^ testModeChannel value
3834 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection accessing'!
3837 "returns the selected item at an index or nil
3839 selection notNil ifTrue:[
3840 ^ selection at:anIndex ifAbsent:nil
3845 at:anIndex ifAbsent:aBlock
3846 "returns the selected item at an index or the result of the block
3848 selection notNil ifTrue:[
3849 ^ selection at:anIndex ifAbsent:aBlock
3855 "returns the first selected item or nil
3861 "returns the last selected item or nil
3863 ^ selection notNil ifTrue:[selection last] ifFalse:[nil]
3867 "returns the single selected item or nil (size ~~ 1 nil is returned)
3869 ^ selection size == 1 ifTrue:[selection at:1] ifFalse:[nil]
3873 "returs the list of selected superItems; items selected
3874 but not contained in another selected item.
3876 ^ selectedSuperItems
3880 "returns the number of items selected
3885 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection adding & removing'!
3888 "add an item to the current selection
3892 item isNil ifTrue:[^ item].
3895 selection isNil ifTrue:[
3896 newSelect := Array with:item.
3898 (self includes:item) ifFalse:[
3899 newSelect := selection copyWith:item
3903 newSelect size ~~ selection size ifTrue:[
3905 self value:newSelect
3911 addAll:aCollectionOfItems
3912 "add a collection of items to the current selection
3916 aCollectionOfItems size == 0 ifTrue:[ ^ aCollectionOfItems ].
3919 selection isNil ifTrue:[
3920 newSelect := Array withAll:aCollectionOfItems.
3922 newSelect := OrderedCollection withAll:selection.
3924 aCollectionOfItems do:[:el|
3925 (selection includesIdentical:el) ifFalse:[newSelect add:el]
3928 self value:newSelect.
3930 ^ aCollectionOfItems
3934 "clear the selection
3940 "remove the item from the current selection
3944 item isNil ifTrue:[^ nil].
3947 (selection notNil and:[selection includesIdentical:item]) ifTrue:[
3948 selection size == 1 ifTrue:[ newSelect := nil ]
3949 ifFalse:[ newSelect := selection copyWithout:item ].
3951 self value:newSelect
3958 "clear the selection
3964 "remove all items of the collection from the current selection
3968 selection isNil ifTrue:[ ^ loItems ].
3969 loItems size == 0 ifTrue:[ ^ loItems ].
3972 selection notNil ifTrue:[
3973 newSelect := selection select:[:el| (loItems includesIdentical:el) not ].
3974 self value:newSelect.
3985 root := listOfItems root.
3990 newSelection := OrderedCollection new.
3991 root recursiveDo:[:el| newSelection add:el ].
3993 self value:newSelection.
3997 "set the current selection to the item
4003 "set the current selection to the root item
4005 self value:(self rootItem).
4009 "set the current selection to the item
4011 self selectItem:anItem.
4014 toggleSelectItem:anItem
4015 "toggle selection-state of the item; add or remove the item from the
4018 anItem notNil ifTrue:[
4019 (self includes:anItem) ifTrue:[self remove:anItem]
4020 ifFalse:[self add:anItem]
4025 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection enumerating'!
4028 "for each element in the selection, evaluate the argument, aBlock
4029 and return a new collection with the results
4033 res := OrderedCollection new.
4034 self do:[:el| res add:(aBlock value:el)].
4039 "evaluate the argument, aBlock for each item in the selection
4043 cashedSelection := selection.
4044 cashedSelection isNil ifTrue:[^ nil].
4045 ^ cashedSelection do:aOneArgBlock
4048 from:start do:aOneArgBlock
4049 "evaluate the argument, aBlock for the items starting at index start
4053 cashedSelection := selection.
4054 cashedSelection isNil ifTrue:[^ nil].
4055 ^ cashedSelection from:start do:aOneArgBlock
4058 from:start to:stop do:aOneArgBlock
4059 "evaluate the argument, aBlock for the items with index start to
4060 stop in the selection.
4064 cashedSelection := selection.
4065 cashedSelection isNil ifTrue:[^ nil].
4066 ^ cashedSelection from:start to:stop do:aOneArgBlock
4069 reverseDo:aOneArgBlock
4070 "evaluate the argument, aBlock for each item in the selection
4074 cashedSelection := selection.
4075 cashedSelection isNil ifTrue:[^ nil].
4076 ^ cashedSelection reverseDo:aOneArgBlock
4080 "return a new collection with all elements from the selection, for which
4081 the argument aBlock evaluates to true.
4085 res := OrderedCollection new.
4086 self do:[:el| (aBlock value:el) ifTrue:[res add:el] ].
4090 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection protocol'!
4092 changed:aParameter with:oldSelection
4093 "update the visibility staus of the current selection
4095 |unselected rootView rootItem selSize|
4097 selSize := selection size.
4099 selSize == 0 ifTrue:[
4100 selectedSuperItems := #().
4102 selSize == 1 ifTrue:[
4103 selectedSuperItems := Array with:(selection at:1).
4105 rootItem := listOfItems root.
4107 (selection includesIdentical:rootItem) ifTrue:[
4108 selectedSuperItems := Array with:rootItem.
4110 selectedSuperItems := OrderedCollection new:selSize.
4112 selection do:[:anItem|
4113 anItem parentsDetect:[:el| selection includesIdentical:el ]
4114 ifNone:[ selectedSuperItems add:anItem ].
4121 and:[(rootView := listOfItems rootView) notNil
4122 and:[rootView shown]]
4124 selSize == 0 ifTrue:[
4125 "/ must redraw the old selection unselected
4126 self redrawUnselected:oldSelection andLock:false
4128 self invalidateSelection.
4130 oldSelection size ~~ 0 ifTrue:[
4131 "/ must redraw all elements no longer in the selection
4132 unselected := oldSelection select:[:el| (selection includesIdentical:el) not ].
4133 self redrawUnselected:unselected andLock:false.
4137 super changed:aParameter with:oldSelection.
4140 setValue:aNewSelection
4141 "set the selection without notifying
4147 aNewSelection notNil ifTrue:[
4149 aNewSelection isCollection ifFalse:[
4150 (selection size == 1 and:[selection first == aNewSelection]) ifTrue:[
4151 newSelect := selection
4153 newSelect := Array with:aNewSelection.
4156 aNewSelection notEmpty ifTrue:[
4157 aNewSelection size ~~ selection size ifTrue:[
4158 newSelect := aNewSelection copy.
4160 idx := selection findFirst:[:el| (aNewSelection includesIdentical:el) not ].
4162 idx ~~ 0 ifTrue:[newSelect := aNewSelection copy]
4163 ifFalse:[newSelect := selection ].
4169 newSelect ~~ selection ifTrue:[
4170 beforeSelectionChangedAction value.
4171 selection := newSelect.
4172 selection notNil ifTrue:[selection do:[:el| el makeVisible]]
4177 "set my value & send change notifications to my dependents.
4178 Send the change message even if the value didn't change.
4183 oldSelection := selection.
4184 self setValue:aValue.
4185 self changed:#value with:oldSelection
4190 "returns the current selection
4196 "change the current selection and send change notifications to my
4197 dependents if it changed.
4202 oldSelection := selection.
4203 self setValue:aValue.
4205 oldSelection == selection ifFalse:[
4206 self changed:#value with:oldSelection
4211 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection searching'!
4214 "evaluate the argument, aBlock for each item in the selection until
4215 the block returns true; in this case return the element which caused
4216 the true evaluation.
4217 If none of the evaluations returns true, an error is raised
4219 ^ self detect:aBlock ifNone:[self errorNotFound]
4222 detect:aBlock ifNone:exceptionBlock
4223 "evaluate the argument, aBlock for each item in the selection until the
4224 block returns true; in this case return the element which caused the
4226 If none of the evaluations returns true, the result of the evaluation
4227 of the exceptionBlock is returned
4231 cashedSelection := selection.
4232 cashedSelection isNil ifTrue:[ ^ exceptionBlock value ].
4233 ^ cashedSelection detect:aBlock ifNone:exceptionBlock
4237 "evaluate the argument, aBlock for each item in the selection until
4238 the block returns true; in this case return the element which caused
4239 the true evaluation. The items are processed in reverse order.
4240 If none of the evaluations returns true, an error is raised
4242 ^ self detectLast:aBlock ifNone:[self errorNotFound]
4245 detectLast:aBlock ifNone:exceptionBlock
4246 "evaluate the argument, aBlock for each item in the selection until
4247 the block returns true; in this case return the element which caused
4248 the true evaluation. The items are processed in reverse order.
4249 If none of the evaluations returns true, the result of the evaluation
4250 of the exceptionBlock is returned
4254 cashedSelection := selection.
4255 cashedSelection isNil ifTrue:[ ^ exceptionBlock value ].
4256 ^ cashedSelection detectLast:aBlock ifNone:exceptionBlock
4259 !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection testing'!
4262 "returns true if the item is in the current selection
4266 cashedSelection := selection.
4267 cashedSelection isNil ifTrue:[^ false].
4268 ^ cashedSelection includesIdentical:anItem
4271 includesAll:aCollection
4272 "return true, if all items of the collection are included in the current selection
4276 aCollection size ~~ 0 ifTrue:[
4277 cashedSelection := selection.
4278 cashedSelection isNil ifTrue:[ ^ false ].
4280 aCollection do:[:el|
4281 (cashedSelection includesIdentical:el) ifFalse:[^ false]
4287 includesAny:aCollection
4288 "return true, if the any item of the collection is in the current selection
4292 aCollection notNil ifTrue:[
4293 cashedSelection := selection.
4295 cashedSelection notNil ifTrue:[
4296 aCollection do:[:el|
4297 (cashedSelection includesIdentical:el) ifTrue:[^ true]
4304 includesIdentical:anItem
4305 "returns true if the item is in the current selection
4307 ^ self includes:anItem
4311 "returns true if the current selection is empty
4313 ^ selection size == 0
4317 "returns true if the item is in the current selection
4319 ^ self includes:anItem
4323 "returns true if the current selection is not empty
4325 ^ selection size ~~ 0
4328 !ViewTreeInspectorApplication::ViewTreeModel::ItemList class methodsFor:'documentation'!
4332 Kind of HierarchicalList class which contains all the visible
4333 ViewTreeItem's and the root, the anchor of the hierarchical list.
4335 [Instance variables:]
4336 treeModel <ViewTreeModel> all events are delegated to
4337 eventHook <BlockValue> save and resore the pre/post -EventHook
4350 !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'accessing'!
4353 "set the root item; delegate events to my treeModel
4357 theRoot == root ifTrue:[^ self].
4359 rootView := self rootView.
4362 rootView notNil ifTrue:[ |wgrp|
4363 wgrp := rootView windowGroup.
4365 wgrp notNil ifTrue:[
4366 wgrp removePreEventHook:treeModel.
4367 wgrp removePostEventHook:self.
4372 rootView := self rootView.
4374 rootView notNil ifTrue:[
4375 "must setup a task because there might not exist a windowGroup at the moment
4379 [rootView == self rootView] whileTrue:[
4380 wgrp := rootView windowGroup.
4381 wgrp notNil ifTrue:[
4383 wgrp addPreEventHook:treeModel.
4384 wgrp addPostEventHook:self.
4386 Delay waitForMilliseconds:100.
4390 ] forkAt:(Processor userSchedulingPriority + 2).
4392 treeModel notNil ifTrue:[
4393 treeModel targetWidgetChanged.
4400 "returns the widget assigned to the root or nil
4402 ^ root notNil ifTrue:[root widget] ifFalse:[nil]
4406 "returne the treeModel, a ViewTreeModel
4411 !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'accessing look'!
4413 additionalLabelForItem:anItem
4414 "answer the additional lable for an item or nil"
4416 |widget l applClass applClassName key|
4418 widget := anItem widget.
4421 showWidgetNames == true ifTrue:[
4422 l := '"', widget name, '"'
4425 anItem isApplicationClass ifTrue:[
4426 applClass := anItem applicationClass.
4427 applClass notNil ifTrue:[
4428 applClassName := '[', applClass name allBold, ']'.
4429 l := (l isNil ifTrue:[''] ifFalse:[l , ' ']) , applClassName
4433 application notNil ifTrue:[
4434 key := application builder namedComponents keyAtValue:widget ifAbsent:nil.
4444 "answer true if the additional text is the widget name
4445 otherwise the name of the application"
4447 ^ showWidgetNames ? true
4450 showWidgetNames:aBoolean
4451 "set true if the additional text is the widget name
4452 otherwise the name of the application"
4454 self showWidgetNames == aBoolean ifFalse:[
4455 showWidgetNames := aBoolean.
4457 root notNil ifTrue:[
4458 root recursiveAdditionalNameBehaviourChanged.
4464 !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'event processing'!
4466 processEvent:anEvent
4469 ^ treeModel isInTestMode not
4472 !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'instance creation'!
4475 "set the model, a ViewTreeModel
4477 treeModel := aModel.
4479 "/ showWidgetNames := false.
4480 showWidgetNames := true.
4483 !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'searching'!
4485 detectItemRespondsToView:aView
4486 "returns the bottom-most item which contains the view
4490 root notNil ifTrue:[
4492 topView := root widget.
4494 [ view notNil ] whileTrue:[
4495 topView == view ifTrue:[^ root].
4496 item := root recursiveDetect:[:el| el widget == view ].
4497 item notNil ifTrue:[^ item].
4498 view := view superView
4504 recursiveDetect:aOneOrgBlock
4505 "recursive find the first child, for which evaluation
4506 of the block returns true; if none nil is returned
4508 root notNil ifTrue:[
4509 (aOneOrgBlock value:root) ifTrue:[ ^ root ].
4510 ^ root recursiveDetect:aOneOrgBlock
4515 !ViewTreeInspectorApplication class methodsFor:'documentation'!
4526 ViewTreeInspectorApplication initialize!
4527 ViewTreeInspectorApplication::ViewTreeItem initialize!