cg@2748: " cg@2748: COPYRIGHT (c) 2007 by eXept Software AG cg@2748: All Rights Reserved cg@2748: cg@2748: This software is furnished under a license and may be used cg@2748: only in accordance with the terms of that license and with the cg@2748: inclusion of the above copyright notice. This software may not cg@2748: be provided or otherwise made available to, or used by, any cg@2748: other person. No title to or ownership of the software is cg@2748: hereby transferred. cg@2748: " ca@2177: "{ Package: 'stx:libtool2' }" ca@2177: ca@2177: "{ NameSpace: Tools }" ca@2177: cg@2744: ToolApplicationModel subclass:#ViewTreeInspectorApplication ca@2177: instanceVariableNames:'model treeView hasSingleSelectionHolder clickedItem clickedPoint ca@2458: motionAction process followFocusChannel showNamesHolder' ca@2177: classVariableNames:'' ca@2177: poolDictionaries:'' cg@2744: category:'Interface-Smalltalk' ca@2177: ! ca@2177: ca@2177: Object subclass:#MenuDesc ca@2177: instanceVariableNames:'title value action' ca@2177: classVariableNames:'' ca@2177: poolDictionaries:'' cg@2744: privateIn:ViewTreeInspectorApplication cg@2744: ! cg@2744: cg@2744: HierarchicalItem subclass:#ViewTreeItem cg@2744: instanceVariableNames:'widget isDrawnShown exists xOffsetAdditionalName' cg@2744: classVariableNames:'HandleExtent' cg@2744: poolDictionaries:'' cg@2744: privateIn:ViewTreeInspectorApplication ca@2177: ! ca@2177: cg@2744: ValueModel subclass:#ViewTreeModel cg@2744: instanceVariableNames:'lockSema selectedSuperItems selection hiddenLevel listOfItems cg@2744: inputEventAction mappedViewAction beforeSelectionChangedAction cg@2744: icons timedUpdateTask selectOnClickHolder testModeChannel cg@2744: hasTargetWidgetChannel' cg@2744: classVariableNames:'' cg@2744: poolDictionaries:'' cg@2744: privateIn:ViewTreeInspectorApplication cg@2744: ! cg@2744: cg@2744: HierarchicalList subclass:#ItemList cg@2744: instanceVariableNames:'treeModel eventHook eventHookInitialized showWidgetNames' cg@2744: classVariableNames:'' cg@2744: poolDictionaries:'' cg@2744: privateIn:ViewTreeInspectorApplication::ViewTreeModel cg@2744: ! cg@2744: cg@2744: !ViewTreeInspectorApplication class methodsFor:'documentation'! ca@2177: cg@2748: copyright cg@2748: " cg@2748: COPYRIGHT (c) 2007 by eXept Software AG cg@2748: All Rights Reserved cg@2748: cg@2748: This software is furnished under a license and may be used cg@2748: only in accordance with the terms of that license and with the cg@2748: inclusion of the above copyright notice. This software may not cg@2748: be provided or otherwise made available to, or used by, any cg@2748: other person. No title to or ownership of the software is cg@2748: hereby transferred. cg@2748: " cg@2748: ! cg@2748: ca@2177: documentation ca@2177: " ca@2177: Small application showing a ViewTreeModel use. ca@2177: ca@2177: It displays a hierarchical list of a selected TopView and ca@2177: all its contained subViews. ca@2177: Useful to have a look at subcomponents - to see how views ca@2177: are structured. ca@2177: ca@2177: ca@2177: [Instance variables:] ca@2177: model the used ViewTreeModel ca@2177: clickedItem item under the clickedPoint (motion action) ca@2177: clickedPoint point where the motion action started from. ca@2177: motionAction (oneArg-) action called durring buttonMotion. ca@2177: ca@2177: ca@2177: [author:] ca@2177: Claus Atzkern ca@2177: ca@2177: [see also:] ca@2177: ViewTreeModel ca@2177: ViewTreeItem ca@2177: " ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication class methodsFor:'initialization'! ca@2177: ca@2177: initialize ca@2177: "add myself to the launcher menu ca@2177: " ca@2177: self installInLauncher. ca@2177: ! ca@2177: ca@2177: installInLauncher cg@2744: "add myself to the launcher menu" cg@2744: ca@2177: |menuItem icon| ca@2177: ca@2177: NewLauncher isNil ifTrue:[^ self]. cg@2744: "/ cg - disabled. the icon is too ugly. cg@2744: ^ self. ca@2177: ca@2177: icon := ToolbarIconLibrary inspectLocals20x20Icon magnifiedTo:28@28. ca@2177: ca@2177: menuItem := MenuItem new cg@2744: label: 'View Tree Inspector'; cg@2744: value: [ ViewTreeInspectorApplication open]; ca@2177: isButton: true; ca@2177: icon: icon; ca@2177: nameKey: #viewInspect. ca@2177: ca@2177: menuItem startGroup:#right. ca@2177: NewLauncher addMenuItem:menuItem in:'toolbar' ca@2177: position:#( #before #help) ca@2177: space:false. ca@2177: ca@2177: " ca@2177: self installInLauncher ca@2177: self removeFromLauncher ca@2177: " ca@2177: ! ca@2177: ca@2177: postAutoload ca@2177: "add myself to the launcher menu ca@2177: " ca@2177: self installInLauncher. ca@2177: " ca@2177: self installInLauncher ca@2177: self removeFromLauncher ca@2177: " ca@2177: ! ca@2177: ca@2177: removeFromLauncher ca@2177: "remove myself from the launcher menu ca@2177: " ca@2177: NewLauncher isNil ifTrue:[^ self]. ca@2177: NewLauncher removeUserTool:#viewInspect ca@2177: ca@2177: " ca@2177: self installInLauncher ca@2177: self removeFromLauncher ca@2177: " ca@2177: ! ca@2177: ca@2177: unload ca@2177: "class is about to be unloaded - remove myself from the launcher menu ca@2177: " ca@2177: self removeFromLauncher. ca@2177: super unload. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication class methodsFor:'image specs'! cg@2744: cg@2759: crossHairIcon cg@2759: "This resource specification was automatically generated cg@2759: by the ImageEditor of ST/X." cg@2759: cg@2759: "Do not manually edit this!! If it is corrupted, cg@2759: the ImageEditor may not be able to read the specification." cg@2759: cg@2759: " cg@2759: self crossHairIcon inspect cg@2759: ImageEditor openOnClass:self andSelector:#crossHairIcon cg@2759: Icon flushCachedIcons cg@2759: " cg@2759: cg@2759: cg@2759: cg@2759: ^Icon cg@2759: constantNamed:'Tools::ViewTreeInspectorApplication class crossHairIcon' cg@2759: 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] cg@2759: ! cg@2759: cg@2744: pickWindowIcon cg@2744: "This resource specification was automatically generated cg@2744: by the ImageEditor of ST/X." cg@2744: cg@2744: "Do not manually edit this!! If it is corrupted, cg@2744: the ImageEditor may not be able to read the specification." cg@2744: cg@2744: " cg@2744: self pickWindowIcon inspect cg@2744: ImageEditor openOnClass:self andSelector:#pickWindowIcon cg@2744: Icon flushCachedIcons cg@2744: " cg@2744: cg@2744: cg@2744: cg@2744: ^Icon cg@2744: constantNamed:'Tools::ViewTreeInspectorApplication class pickWindowIcon' cg@2744: ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:' cg@2744: ,;N3,;N3,;N3,;N3,;N3,;N3,;N3,3HO#8H"T+N3,;N3@KN$@@@@'')(@%H>O#(>AH%F3,;N3,;L@ cg@2744: @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 cg@2744: 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] cg@2759: ! cg@2759: cg@2759: pickWindowIcon2 cg@2759: "This resource specification was automatically generated cg@2759: by the ImageEditor of ST/X." cg@2759: cg@2759: "Do not manually edit this!! If it is corrupted, cg@2759: the ImageEditor may not be able to read the specification." cg@2759: cg@2759: " cg@2759: self pickWindowIcon2 inspect cg@2759: ImageEditor openOnClass:self andSelector:#pickWindowIcon2 cg@2759: Icon flushCachedIcons cg@2759: " cg@2759: cg@2759: cg@2759: cg@2759: ^Icon cg@2759: constantNamed:'Tools::ViewTreeInspectorApplication class pickWindowIcon2' cg@2759: ifAbsentPut:[(Depth8Image new) width: 22; height: 23; photometric:(#palette); bitsPerSample:(#[8]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:' cg@2759: @CHH AN+[N$)JH@@I"T@I"T@@BO#8>O_"H@JZ63)JJ^&) @ cg@2759: @@@@@IJO#8>O#8@O@B&3,;N3,;N3,;N3,;N"'')*X%IJ[C0@)R$]EPS<=NS 5L28''H"H"H"H"H ca@2177: ca@2177: ^ ca@2177: #(FullSpec ca@2177: name: windowSpec ca@2177: window: ca@2177: (WindowSpec cg@2744: label: 'View Tree Inspector' cg@2757: name: 'View Tree Inspector' ca@2177: min: (Point 10 10) ca@2177: max: (Point 1024 9999) ca@2451: bounds: (Rectangle 0 0 381 654) ca@2177: menu: menu ca@2177: ) ca@2177: component: ca@2177: (SpecCollection ca@2177: collection: ( ca@2177: (MenuPanelSpec ca@2177: name: 'toolbarMenu' cg@2757: layout: (LayoutFrame 0 0.0 0 0 0 1.0 40 0) ca@2177: menu: toolbarMenu ca@2177: textDefault: true ca@2177: ) ca@2177: (HierarchicalListViewSpec ca@2177: name: 'List' cg@2757: layout: (LayoutFrame 0 0.0 40 0.0 0 1.0 0 1.0) ca@2177: level: 1 ca@2177: model: model ca@2177: menu: middleButtonMenu ca@2177: hasHorizontalScrollBar: true ca@2177: hasVerticalScrollBar: true ca@2177: miniScrollerHorizontal: true ca@2177: miniScrollerVertical: false ca@2177: listModel: listOfItems ca@2177: multipleSelectOk: true ca@2177: useIndex: false ca@2177: highlightMode: label ca@2177: showLeftIndicators: false ca@2177: indicatorSelector: indicatorClicked: ca@2177: useDefaultIcons: false ca@2177: postBuildCallback: postBuildTree: ca@2177: ) ca@2177: ) ca@2177: ca@2177: ) ca@2177: ) ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication class methodsFor:'menu specs'! ca@2177: ca@2177: menu ca@2177: "This resource specification was automatically generated ca@2177: by the MenuEditor of ST/X." ca@2177: ca@2177: "Do not manually edit this!! If it is corrupted, ca@2177: the MenuEditor may not be able to read the specification." ca@2177: ca@2177: " ca@2454: MenuEditor new openOnClass:Tools::ViewTreeApplication andSelector:#menu ca@2454: (Menu new fromLiteralArrayEncoding:(Tools::ViewTreeApplication menu)) startUp ca@2177: " ca@2177: ca@2177: ca@2177: ca@2177: ^ ca@2177: #(Menu ca@2177: ( ca@2177: (MenuItem ca@2177: label: 'File' ca@2177: translateLabel: true ca@2177: submenu: ca@2177: (Menu ca@2177: ( ca@2177: (MenuItem ca@2177: label: 'Pick a View' ca@2177: itemValue: doPickViews ca@2177: translateLabel: true ca@2177: ) ca@2177: (MenuItem ca@2455: enabled: hasTargetWidgetChannel ca@2177: label: 'Release Picked View' ca@2177: itemValue: doUnpick ca@2177: translateLabel: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem cg@2744: label: 'Settings' cg@2744: translateLabel: true cg@2744: submenu: cg@2744: (Menu cg@2744: ( cg@2744: (MenuItem cg@2744: label: 'Test Mode' cg@2744: translateLabel: true cg@2744: hideMenuOnActivated: false cg@2744: indication: testModeChannel cg@2744: ) cg@2744: (MenuItem cg@2744: enabled: testModeChannel cg@2744: label: 'Follow Focus' cg@2744: translateLabel: true cg@2744: hideMenuOnActivated: false cg@2744: indication: followFocusChannel cg@2744: ) cg@2744: (MenuItem cg@2744: label: '-' cg@2744: ) cg@2744: (MenuItem cg@2744: label: 'Select on Click' cg@2744: translateLabel: true cg@2744: hideMenuOnActivated: false cg@2744: indication: selectOnClickHolder cg@2744: ) cg@2744: (MenuItem cg@2744: label: '-' cg@2744: ) cg@2744: (MenuItem cg@2744: label: 'Show Name of Widgets' cg@2744: translateLabel: true cg@2744: hideMenuOnActivated: false cg@2744: indication: showNamesHolder cg@2744: ) cg@2744: ) cg@2744: nil cg@2744: nil cg@2744: ) cg@2744: ) cg@2744: (MenuItem cg@2744: label: '-' cg@2744: ) cg@2744: (MenuItem ca@2177: label: 'Exit' ca@2177: itemValue: closeRequest ca@2177: translateLabel: true ca@2177: ) ca@2177: ) ca@2177: nil ca@2177: nil ca@2177: ) ca@2177: ) ca@2177: (MenuItem cg@2744: enabled: hasSingleSelectionHolder cg@2744: label: 'Selection' cg@2744: translateLabel: true cg@2744: submenuChannel: middleButtonMenu cg@2744: ) cg@2744: (MenuItem cg@2744: label: 'Application' ca@2454: translateLabel: true ca@2454: submenu: ca@2454: (Menu ca@2454: ( ca@2454: (MenuItem cg@2744: enabled: hasSingleSelectionHolder cg@2744: label: 'Browse' cg@2744: itemValue: doBrowse: ca@2454: translateLabel: true cg@2744: argument: application ca@2454: ) ca@2454: (MenuItem cg@2744: enabled: hasSingleSelectionHolder cg@2744: label: 'Inspect' cg@2744: itemValue: doInspect: ca@2454: translateLabel: true cg@2744: argument: application ca@2454: ) ca@2454: (MenuItem ca@2454: label: '-' ca@2454: ) ca@2454: (MenuItem cg@2744: enabled: hasTargetWidgetChannel cg@2744: label: 'All Applications' ca@2454: translateLabel: true cg@2744: submenuChannel: submenuApplications: ca@2454: ) ca@2454: ) ca@2454: nil ca@2454: nil ca@2454: ) ca@2454: ) ca@2454: (MenuItem cg@2744: label: 'Widget' ca@2177: translateLabel: true cg@2744: submenu: cg@2744: (Menu cg@2744: ( cg@2744: (MenuItem cg@2744: enabled: hasSingleSelectionHolder cg@2744: label: 'Browse' cg@2744: itemValue: doBrowse: cg@2744: translateLabel: true cg@2744: argument: view cg@2744: ) cg@2744: (MenuItem cg@2744: enabled: hasSingleSelectionHolder cg@2744: label: 'Inspect' cg@2744: itemValue: doInspect: cg@2744: translateLabel: true cg@2744: argument: view cg@2744: ) cg@2744: (MenuItem cg@2744: label: '-' cg@2744: ) cg@2744: (MenuItem cg@2744: enabled: hasTargetWidgetChannel cg@2744: label: 'All Components' cg@2744: translateLabel: true cg@2744: startGroup: right cg@2744: submenuChannel: submenuComponents: cg@2744: ) cg@2744: ) cg@2744: nil cg@2744: nil cg@2744: ) ca@2177: ) ca@2177: (MenuItem cg@2744: label: 'Help' ca@2177: translateLabel: true cg@2744: startGroup: conditionalRight cg@2744: submenu: cg@2744: (Menu cg@2744: ( cg@2744: (MenuItem cg@2744: label: 'Documentation' cg@2744: itemValue: openDocumentation cg@2744: translateLabel: true cg@2744: ) cg@2744: (MenuItem cg@2744: label: '-' cg@2744: ) cg@2744: (MenuItem cg@2744: label: 'About this Application...' cg@2744: itemValue: openAboutThisApplication cg@2744: translateLabel: true cg@2744: ) cg@2744: ) cg@2744: nil cg@2744: nil cg@2744: ) ca@2177: ) ca@2177: ) ca@2177: nil ca@2177: nil ca@2177: ) ca@2177: ! ca@2177: ca@2177: middleButtonMenu ca@2177: "This resource specification was automatically generated ca@2177: by the MenuEditor of ST/X." ca@2177: ca@2177: "Do not manually edit this!! If it is corrupted, ca@2177: the MenuEditor may not be able to read the specification." ca@2177: ca@2177: " ca@2177: MenuEditor new openOnClass:ViewTreeApplication andSelector:#middleButtonMenu ca@2177: (Menu new fromLiteralArrayEncoding:(ViewTreeApplication middleButtonMenu)) startUp ca@2177: " ca@2177: ca@2177: ca@2177: ca@2177: ^ ca@2177: #(Menu ca@2177: ( ca@2177: (MenuItem ca@2177: label: 'Geometry' ca@2177: translateLabel: true ca@2177: submenuChannel: submenuGeometry: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Interface' ca@2177: translateLabel: true ca@2177: submenuChannel: submenuInterface: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Visibility' ca@2177: translateLabel: true ca@2177: submenuChannel: submenuVisibility: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Browse View Class' ca@2177: itemValue: doBrowse: ca@2177: translateLabel: true ca@2177: argument: view ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Browse Model Class' ca@2177: itemValue: doBrowse: ca@2177: translateLabel: true ca@2177: isVisible: hasModel ca@2177: argument: model ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Browse Application Class' ca@2177: itemValue: doBrowse: ca@2177: translateLabel: true ca@2177: isVisible: hasApplication ca@2177: argument: application ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Browse Controller Class' ca@2177: itemValue: doBrowse: ca@2177: translateLabel: true ca@2177: isVisible: hasController ca@2177: argument: controller ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Inspect View' ca@2177: itemValue: doInspect: ca@2177: translateLabel: true ca@2177: argument: view ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Inspect Window Group' ca@2177: itemValue: doInspect: ca@2177: translateLabel: true ca@2177: argument: group ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Inspect Model' ca@2177: itemValue: doInspect: ca@2177: translateLabel: true ca@2177: isVisible: hasModel ca@2177: argument: model ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Inspect Application' ca@2177: itemValue: doInspect: ca@2177: translateLabel: true ca@2177: isVisible: hasApplication ca@2177: argument: application ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Inspect Controller' ca@2177: itemValue: doInspect: ca@2177: translateLabel: true ca@2177: isVisible: hasController ca@2177: argument: controller ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Flash' ca@2177: itemValue: doFlash ca@2177: translateLabel: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Destroy' ca@2177: itemValue: doDestroy ca@2177: translateLabel: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: '-' ca@2177: ) ca@2177: (MenuItem ca@2177: label: 'Instance Variables' ca@2177: translateLabel: true ca@2177: submenuChannel: submenuInspector: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: (MenuItem ca@2177: label: '=' ca@2177: ) ca@2177: (MenuItem ca@2177: label: '' ca@2177: ) ca@2177: (MenuItem ca@2177: enabled: selectedComponentHasChildren ca@2177: label: 'Applications' ca@2177: nameKey: single ca@2177: translateLabel: true ca@2177: submenuChannel: submenuApplications: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: (MenuItem ca@2177: enabled: selectedComponentHasChildren ca@2177: label: 'Components' ca@2177: nameKey: single ca@2177: translateLabel: true ca@2177: submenuChannel: submenuComponents: ca@2177: keepLinkedMenu: true ca@2177: ) ca@2177: ) ca@2177: nil ca@2177: nil ca@2177: ) ca@2177: ! ca@2177: ca@2177: toolbarMenu ca@2177: "This resource specification was automatically generated ca@2177: by the MenuEditor of ST/X." ca@2177: ca@2177: "Do not manually edit this!! If it is corrupted, ca@2177: the MenuEditor may not be able to read the specification." ca@2177: ca@2177: " cg@2757: MenuEditor new openOnClass:Tools::ViewTreeInspectorApplication andSelector:#toolbarMenu cg@2757: (Menu new fromLiteralArrayEncoding:(Tools::ViewTreeInspectorApplication toolbarMenu)) startUp ca@2177: " ca@2177: ca@2177: ca@2177: ca@2177: ^ ca@2177: #(Menu ca@2177: ( ca@2177: (MenuItem cg@2744: label: 'Pick a View' cg@2744: itemValue: doPickViews cg@2744: translateLabel: false cg@2744: isButton: true cg@2744: hideMenuOnActivated: false cg@2759: labelImage: (ResourceRetriever #'Tools::ViewTreeInspectorApplication' pickWindowIcon2) cg@2744: ) cg@2744: (MenuItem cg@2757: enabled: hasTargetWidgetChannel cg@2757: label: 'Release Picked View' cg@2757: isButton: true cg@2757: itemValue: doUnpick cg@2757: translateLabel: true cg@2757: labelImage: (ResourceRetriever ToolbarIconLibrary undoIcon) cg@2757: ) cg@2757: (MenuItem cg@2757: label: '-' cg@2757: ) cg@2757: (MenuItem ca@2454: enabled: hasSingleSelectionHolder cg@2744: label: 'Browse Application' ca@2454: itemValue: doBrowse: ca@2454: translateLabel: false cg@2744: isButton: true cg@2744: hideMenuOnActivated: false ca@2454: labelImage: (ResourceRetriever ToolbarIconLibrary systemBrowser24x24Icon2) ca@2454: argument: application ca@2454: ) ca@2454: (MenuItem ca@2454: enabled: hasSingleSelectionHolder cg@2744: label: 'Inspect Application' ca@2454: itemValue: doInspect: ca@2454: translateLabel: false cg@2744: isButton: true cg@2744: hideMenuOnActivated: false cg@2744: labelImage: (ResourceRetriever ToolbarIconLibrary inspect22x24Icon) ca@2454: argument: application ca@2177: ) ca@2177: ) ca@2177: nil ca@2177: nil ca@2177: ) ca@2177: ! ! ca@2177: cg@2747: !ViewTreeInspectorApplication class methodsFor:'startup'! cg@2747: cg@2747: openInPickMode cg@2747: |app| cg@2747: cg@2747: app := self new. cg@2747: app open. cg@2747: app doPickViews. cg@2747: ! ! cg@2747: cg@2744: !ViewTreeInspectorApplication methodsFor:'actions'! ca@2177: ca@2177: indicatorClicked:anIndex ca@2177: |item sensor| ca@2177: ca@2177: item := model listOfItems at:anIndex ifAbsent:nil. ca@2177: ca@2177: item notNil ifTrue:[ ca@2177: ( (sensor := self window sensor) notNil ca@2177: and:[(sensor ctrlDown or:[sensor shiftDown])] ca@2177: ) ifTrue:[ ca@2177: item recursiveToggleExpand ca@2177: ] ifFalse:[ ca@2177: item toggleExpand ca@2177: ] ca@2177: ]. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'aspects'! ca@2177: ca@2177: followFocusChannel ca@2455: "boolean holder, which indicates whether selection changed dependend on the focus view" ca@2455: ca@2177: ^ followFocusChannel ca@2177: ! ca@2177: ca@2177: hasSingleSelectionHolder ca@2455: "boolean holder, true if one item is selected" ca@2455: ca@2177: ^ hasSingleSelectionHolder ca@2177: ! ca@2177: ca@2455: hasTargetWidgetChannel ca@2455: "answer the channel which is set to true if a target widget exists" ca@2455: ca@2455: ^ model hasTargetWidgetChannel ca@2455: ! ca@2455: ca@2177: listOfItems ca@2455: "returns the hierarchical list of items" ca@2455: ca@2177: ^ model listOfItems ca@2177: ! ca@2177: ca@2177: model ca@2455: "returns my selection model, a ViewTreeModel" ca@2455: ca@2177: ^ model ca@2177: ! ca@2177: ca@2177: selectOnClickHolder ca@2455: "boolean holder, which indicates whether the selection will change on click" ca@2455: ca@2177: ^ model selectOnClickHolder ca@2177: ! ca@2177: ca@2451: showNamesHolder ca@2451: "boolean holder, which indicates whether application names or widget names ca@2455: as additional text are shown for the items" ca@2455: ca@2451: ^ showNamesHolder ca@2451: ! ca@2451: ca@2177: testModeChannel ca@2455: "answer a boolean channel which describes the behaviour how to process ca@2455: events on the target view. ca@2455: ca@2455: false: all input events are eaten and the selection is shown on the target view. ca@2455: true: no input events are eaten and no selection is shown on the target view." ca@2455: ca@2455: ^ model testModeChannel ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'change & update'! ca@2177: ca@2177: selectionChanged ca@2177: |info view item| ca@2177: ca@2177: item := model selectedItem. ca@2177: ca@2177: item notNil ifTrue:[ |state| ca@2177: view := item widget. ca@2177: ca@2177: view id isNil ifTrue:[ ca@2177: state := 'no ID'. ca@2177: ] ifFalse:[ ca@2177: view shown ifTrue:[ ca@2177: state := 'visible'. ca@2177: ] ifFalse:[ ca@2177: state := 'invisible' ca@2177: ]. ca@2177: ]. ca@2177: info := '%1 [%2] - %3' bindWith:(view class name) ca@2177: with:(view name ? '') with:state allBold. ca@2177: ca@2177: ] ifFalse:[ ca@2177: info := '' ca@2177: ]. ca@2177: hasSingleSelectionHolder value:(view notNil). ca@2177: ! ca@2177: ca@2177: update:something with:someArgument from:aModel ca@2454: |oldSelection| ca@2454: ca@2451: aModel == showNamesHolder ifTrue:[ ca@2455: oldSelection := model selectedItem. ca@2454: model selectedItem:nil. ca@2451: self listOfItems showWidgetNames:(aModel value). ca@2454: model selectedItem:oldSelection. ca@2451: ^ self ca@2451: ]. ca@2458: ca@2458: aModel == model ifTrue:[ ca@2458: self selectionChanged. ca@2458: ^ self ca@2458: ]. ca@2458: ca@2177: super update:something with:someArgument from:aModel. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'event processing'! ca@2177: ca@2177: processButtonMotionEvent:ev ca@2455: |click rootView| ca@2455: ca@2455: motionAction isNil ifTrue:[^ self]. ca@2177: ca@2455: (rootView := model rootView) isNil ifTrue:[ ca@2455: clickedItem := motionAction := nil. ca@2455: ^ self ca@2455: ]. ca@2177: ca@2455: click := rootView device ca@2455: translatePoint:((ev x)@ (ev y)) ca@2455: fromView:(ev view) ca@2455: toView:rootView. ca@2455: ca@2455: click = clickedPoint ifFalse:[ ca@2455: (clickedItem isNil or:[(click dist:clickedPoint) > 5.0]) ifTrue:[ ca@2455: motionAction value:click ca@2177: ] ca@2177: ]. ca@2177: ! ca@2177: ca@2177: processButtonPressEvent:ev ca@2455: |rootView sensor lastRectangle| ca@2455: ca@2455: rootView := model rootView. ca@2177: sensor := model rootView sensor. ca@2177: clickedItem := model listOfItems detectItemRespondsToView:(ev view). ca@2177: ca@2177: (sensor ctrlDown or:[sensor shiftDown]) ifTrue:[ ca@2177: clickedItem notNil ifTrue:[ ca@2177: self selectOnClickHolder value ifTrue:[ ca@2177: model toggleSelectItem:clickedItem ca@2177: ]. ca@2177: ]. ca@2177: clickedItem := motionAction := nil. ca@2455: ^ self ca@2455: ]. ca@2177: ca@2455: clickedPoint := rootView device translatePoint:((ev x)@ (ev y)) fromView:(ev view) toView:rootView. ca@2455: lastRectangle := nil. ca@2177: ca@2455: motionAction :=[:p| ca@2455: rootView := model rootView device rootView. ca@2455: rootView := model rootView. ca@2455: clickedItem := nil. ca@2177: ca@2455: rootView xoring:[ ca@2455: lastRectangle notNil ifTrue:[ rootView displayRectangle:lastRectangle ] ca@2455: ifFalse:[ rootView clippedByChildren:false ]. ca@2455: ca@2455: p isNil ifTrue:[ ca@2455: rootView clippedByChildren:true. ca@2455: motionAction := nil. ca@2455: ] ifFalse:[ ca@2455: lastRectangle := Rectangle origin:(clickedPoint min:p) corner:(clickedPoint max:p). ca@2455: rootView displayRectangle:lastRectangle. ca@2177: ]. ca@2455: rootView flush. ca@2455: ]. ca@2455: lastRectangle ca@2455: ]. ca@2177: ! ca@2177: ca@2177: processButtonReleaseEvent:anEvent ca@2177: |rootView rectangle newItems widget origin| ca@2177: ca@2455: (rootView := model rootView) isNil ifTrue:[ ca@2455: clickedItem := motionAction := nil. ca@2455: ^ self ca@2455: ]. ca@2177: motionAction isNil ifTrue:[ ^ self ]. ca@2177: clickedItem notNil ifTrue:[ ^ model selectItem:clickedItem ]. ca@2177: ca@2455: rectangle := motionAction value:nil. ca@2455: rectangle isNil ifTrue:[^ self]. ca@2455: ca@2455: newItems := OrderedCollection new. ca@2177: ca@2455: model rootItem recursiveDo:[:anItem| ca@2455: widget := anItem widget. ca@2455: origin := widget originRelativeTo:rootView. ca@2177: ca@2455: (rectangle containsRect:(Rectangle origin:origin extent:(widget extent))) ifTrue:[ ca@2455: newItems add:anItem. ca@2455: ] ca@2177: ]. ca@2455: model value:newItems. ca@2177: ! ca@2177: ca@2177: processEvent:anEvent ca@2177: |button menu| ca@2177: cg@2758: anEvent isKeyPressEvent ifTrue:[ self processKeyPressEvent:anEvent. ^ self ]. ca@2177: anEvent isButtonEvent ifFalse:[ ^ self ]. ca@2177: ca@2177: button := anEvent button. ca@2177: ca@2177: (button == 2 or:[button == #menu]) ifTrue:[ ca@2177: motionAction isNil ifTrue:[ ca@2177: anEvent isButtonPressEvent ifTrue:[ ca@2177: self selectOnClickHolder value ifTrue:[ ca@2177: menu := self middleButtonMenu value. ca@2177: menu notNil ifTrue:[ cg@2758: menu := MenuPanel cg@2758: menu:(Menu new fromLiteralArrayEncoding:menu) cg@2758: receiver:self. ca@2177: menu startUp. ca@2177: ] ca@2177: ]. ca@2177: ]. ca@2177: clickedItem := nil. ca@2177: ]. ca@2177: ^ self ca@2177: ]. ca@2177: cg@2758: anEvent isButtonPressEvent ifTrue:[ self processButtonPressEvent:anEvent. ^ self ]. cg@2758: anEvent isButtonMotionEvent ifTrue:[ self processButtonMotionEvent:anEvent. ^ self ]. ca@2177: ca@2177: anEvent isButtonReleaseEvent ifTrue:[ ca@2177: self selectOnClickHolder value ifTrue:[ ca@2177: self processButtonReleaseEvent:anEvent ca@2177: ]. ca@2177: ]. ca@2177: clickedItem := motionAction := nil. ca@2177: ca@2177: anEvent type == #'buttonMultiPress:x:y:' ifTrue:[ ca@2177: self selectOnClickHolder value ifTrue:[ ca@2177: self doInspect:#view. ca@2177: ]. ca@2177: ]. ca@2177: ! ca@2177: ca@2177: processKeyPressEvent:anEvent ca@2177: |item prnt idx key max next| ca@2177: ca@2177: key := anEvent key. ca@2177: key isSymbol ifFalse:[^ self]. ca@2177: ca@2177: key == #Delete ifTrue:[ ^ self doDestroy ]. ca@2177: key == #InspectIt ifTrue:[ ^ self doInspect:#view ]. ca@2177: ca@2177: ( key == #CursorUp ca@2177: or:[key == #CursorDown ca@2177: or:[key == #CursorLeft ca@2177: or:[key == #CursorRight]]] ca@2177: ) ifFalse:[ ca@2177: ^ self ca@2177: ]. ca@2177: item := model selectedItem. ca@2177: ca@2177: item isNil ifTrue:[ ca@2177: ^ model selectedItem:(model first ? model rootItem) ca@2177: ]. ca@2177: ca@2177: prnt := item parent. ca@2177: prnt isNil ifTrue:[ ca@2177: "/ is the root item ca@2177: (key == #CursorUp or:[key == #CursorLeft]) ifTrue:[item := model listOfItems last] ca@2177: ifFalse:[item := item at:1 ifAbsent:item]. ca@2177: cg@2758: ^ model selectedItem:item ca@2177: ]. ca@2177: key == #CursorLeft ifTrue:[ ^ model selectedItem:prnt ]. ca@2177: ca@2177: key == #CursorRight ifTrue:[ ca@2177: next := item at:1 ifAbsent:nil. ca@2177: next notNil ifTrue:[ model selectedItem:next ]. cg@2758: ^ self ca@2177: ]. ca@2177: ca@2177: max := prnt size. ca@2177: ca@2177: key == #CursorUp ifTrue:[ ca@2177: idx := prnt identityIndexOf:item. ca@2177: idx == 1 ifTrue:[idx := max + 1]. ca@2177: model selectedItem:(prnt at:idx - 1). cg@2758: ^ self. ca@2177: ]. ca@2177: ca@2177: key == #CursorDown ifTrue:[ ca@2177: idx := prnt identityIndexOf:item. ca@2177: idx == max ifTrue:[idx := 0]. ca@2177: model selectedItem:(prnt at:idx + 1). cg@2758: ^ self. ca@2177: ]. ca@2177: ! ca@2177: ca@2177: processMappedView:aView ca@2177: |parent anchor| ca@2177: ca@2177: parent := self listOfItems detectItemRespondsToView:aView. ca@2177: parent isNil ifTrue:[ ^ self ]. ca@2177: ca@2177: NotFoundSignal handle:[:ex| ca@2177: "contained subvies used by spec are not yet created; ca@2177: thus we have to wait until last used subview is build ca@2177: " ca@2177: anchor := nil. ca@2177: ] do:[ ca@2177: anchor := parent class buildViewsFrom:(parent widget). ca@2177: ]. ca@2177: anchor notNil ifTrue:[ ca@2177: parent updateFromChildren:anchor children. ca@2177: ]. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'initialization & release'! ca@2177: ca@2177: closeDownViews ca@2455: "release the grapped application" ca@2455: ca@2177: process := nil. ca@2177: super closeDownViews. ca@2177: self doUnpick. ca@2177: ! ca@2177: ca@2177: initialize ca@2455: "setup my model and channels" ca@2455: ca@2177: super initialize. ca@2177: ca@2177: hasSingleSelectionHolder := false asValue. ca@2177: followFocusChannel := false asValue. ca@2177: ca@2177: model := ViewTreeModel new. ca@2177: model inputEventAction:[:ev| self processEvent:ev ]. ca@2177: model mappedViewAction:[:vw| self processMappedView:vw ]. ca@2177: model application:self. ca@2458: model addDependent:self. ca@2458: ca@2177: ca@2451: showNamesHolder := false asValue. ca@2451: showNamesHolder addDependent:self. ca@2177: ! ca@2177: ca@2177: postBuildTree:aTree ca@2177: treeView := aTree scrolledView. ca@2177: treeView hasConstantHeight:true. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'menu queries'! ca@2177: ca@2177: hasApplication ca@2455: "returns true if the current selected view has an application" ca@2455: ca@2177: |view| ca@2177: ca@2177: view := self selectedView. ca@2177: ^ (view notNil and:[view application notNil]) ca@2177: ! ca@2177: ca@2177: hasController ca@2177: "returns true if the current selected item's view has a controller ca@2455: other than nil or the view itself" ca@2455: ca@2177: |view controller| ca@2177: ca@2177: view := self selectedView. ca@2177: ca@2177: view notNil ifTrue:[ ca@2177: controller := view controller. ca@2177: ^ (controller notNil and:[controller ~~ view]) ca@2177: ]. ca@2177: ^ false ca@2177: ! ca@2177: ca@2177: hasModel ca@2455: "returns true if the current selected view has a model" ca@2455: ca@2177: |view| ca@2177: ca@2177: view := self selectedView. ca@2177: ^ (view notNil and:[view model notNil]) ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'menu specs'! ca@2177: ca@2177: middleButtonMenu ca@2455: "returns the middleButton menu for the single selected item or nil" ca@2455: cg@2758: ^ [ cg@2758: model selectedItem notNil cg@2758: ifTrue:[self class middleButtonMenu] cg@2758: ifFalse:[nil] ca@2177: ] ca@2177: ! ca@2177: ca@2177: submenuApplications:aMenu ca@2177: |applications menu item list addBlock| ca@2177: ca@2177: item := aMenu selection nameKey == #single ifTrue:[model selectedItem] ca@2177: ifFalse:[model rootItem]. ca@2177: item isNil ifTrue:[^ nil]. ca@2177: ca@2177: applications := IdentityDictionary new. ca@2177: ca@2177: addBlock := [:el| |cls ctr| ca@2177: cls := self resolveApplicationClassFor:el. ca@2177: ca@2177: cls notNil ifTrue:[ ca@2177: ctr := applications at:cls ifAbsent:0. ca@2177: applications at:cls put:(ctr + 1). ca@2177: ]. ca@2177: ]. ca@2177: item recursiveDo:addBlock. ca@2177: addBlock value:item. ca@2177: ca@2177: applications isEmpty ifTrue:[^ nil ]. ca@2177: list := SortedCollection sortBlock:[:a :b| a title < b title ]. ca@2177: ca@2177: applications keysAndValuesDo:[:cls :ctr| ca@2177: list add:(MenuDesc title:(cls name) ca@2177: value:(ctr printString) ca@2177: action:[self doSelectNextOfApplicationClass:cls startingIn:item] ca@2177: ). ca@2177: ]. ca@2177: ca@2177: menu := MenuDesc buildFromList:list onGC:aMenu. ca@2177: menu do:[:el| ca@2177: el hideMenuOnActivated:false ca@2177: ]. ca@2177: ^ menu ca@2177: ! ca@2177: ca@2177: submenuComponents:aMenu ca@2177: |widgets list total menu item| ca@2177: ca@2177: item := aMenu selection nameKey == #single ifTrue:[model selectedItem] ca@2177: ifFalse:[model rootItem]. ca@2177: item isNil ifTrue:[^ nil]. ca@2177: ca@2177: widgets := IdentityDictionary new. ca@2177: total := 0. ca@2177: ca@2177: item recursiveDo:[:el| |cls ctr| ca@2177: cls := el widget. ca@2177: ca@2177: cls notNil ifTrue:[ ca@2177: cls := cls class. ca@2177: ctr := widgets at:cls ifAbsent:0. ca@2177: widgets at:cls put:(ctr + 1). ca@2177: total := total + 1. ca@2177: ]. ca@2177: ]. ca@2177: total == 0 ifTrue:[^ nil]. ca@2177: list := SortedCollection sortBlock:[:a :b| a title < b title ]. ca@2177: ca@2177: widgets keysAndValuesDo:[:cls :ctr| ca@2177: list add:(MenuDesc title:(cls name) ca@2177: value:(ctr printString) ca@2177: action:[self doSelectNextOfClass:cls startingIn:item] ca@2177: ). ca@2177: ]. ca@2177: list := list asOrderedCollection. ca@2177: list add:(MenuDesc separator). ca@2177: list add:(MenuDesc title:'Total' value:(total printString)). ca@2177: menu := MenuDesc buildFromList:list onGC:aMenu. ca@2177: menu do:[:el| ca@2177: el hideMenuOnActivated:false ca@2177: ]. ca@2177: ^ menu ca@2177: ! ca@2177: ca@2177: submenuGeometry:aMenu ca@2455: "builds and returns the geometry submenu" ca@2455: ca@2177: |view point inst list x y| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[^ nil]. ca@2177: ca@2177: list := OrderedCollection new. ca@2177: ca@2177: "/ origin ca@2177: point := view relativeOrigin. ca@2177: point isNil ifTrue:[ point := view origin ]. ca@2177: ca@2177: x := view left. ca@2177: y := view top. ca@2177: ca@2177: (x == point x and:[y == point y]) ifTrue:[ inst := point ] ca@2177: ifFalse:[ inst := '%1 --> (%2@%3)' bindWith:point with:x with:y ]. ca@2177: ca@2177: list add:(MenuDesc title:'origin' value:inst). ca@2177: ca@2177: "/ corner ca@2177: point := view relativeCorner. ca@2177: point isNil ifTrue:[ point := view corner ]. ca@2177: ca@2177: x := view right. ca@2177: y := view bottom. ca@2177: ca@2177: (x == point x and:[y == point y]) ifTrue:[ inst := point ] ca@2177: ifFalse:[ inst := '%1 --> (%2@%3)' bindWith:point with:x with:y ]. ca@2177: ca@2177: list add:(MenuDesc title:'corner' value:inst). ca@2177: ca@2177: "/ extent ca@2177: (point := view relativeExtent) isNil ifTrue:[point := view extent]. ca@2177: list add:(MenuDesc title:'extent' value:point). ca@2177: ca@2177: "/ preferred extent ca@2177: list add:(MenuDesc title:'pref. extent' value:(view preferredExtent)). ca@2177: list add:(MenuDesc separator). ca@2177: ca@2177: "/ view insets ca@2177: inst := 'l:%1 r:%2 t:%3 b:%4' bindWith:(view leftInset) ca@2177: with:(view rightInset) ca@2177: with:(view topInset) ca@2177: with:(view bottomInset). ca@2177: ca@2177: list add:(MenuDesc title:'insets' value:inst). ca@2177: list add:(MenuDesc title:'borderWidth' value:(view borderWidth)). ca@2177: list add:(MenuDesc title:'level' value:(view level)). ca@2177: list add:(MenuDesc separator). ca@2177: ca@2177: (inst := view layout) notNil ifTrue:[ inst := inst displayString ]. ca@2177: list add:(MenuDesc title:'layout' value:inst). ca@2177: ca@2177: (inst := view transformation) notNil ifTrue:[ inst := inst displayString ]. ca@2177: list add:(MenuDesc title:'transformation' value:inst). ca@2177: ca@2177: ^ MenuDesc buildFromList:list onGC:aMenu ca@2177: ! ca@2177: ca@2177: submenuInspector:aMenu ca@2455: "builds and returns the inspector submenu" ca@2455: ca@2177: |view list n names label value| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[^ nil]. ca@2177: ca@2177: n := view class instSize. ca@2177: n > 0 ifFalse:[^ nil ]. ca@2177: ca@2177: list := OrderedCollection new:n. ca@2177: names := view class allInstVarNames. ca@2177: ca@2177: 1 to:n do:[:i| |action| ca@2177: label := (names at:i) printString. ca@2177: value := view instVarAt:i. ca@2177: value isNil ifTrue:[ ca@2177: value := '------'. ca@2177: action := nil. ca@2177: ] ifFalse:[ ca@2177: value := value displayString contractAtEndTo:40. ca@2177: action := [(view instVarAt:i) inspect]. ca@2177: ]. ca@2177: list add:(MenuDesc title:label value:value action:action). ca@2177: ]. ca@2177: ca@2177: ^ MenuDesc buildFromList:list onGC:aMenu ca@2177: ! ca@2177: ca@2177: submenuInterface:aMenu ca@2455: "builds and returns the interface submenu" ca@2455: ca@2177: |view label inst value list| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[^ nil]. ca@2177: ca@2177: list := OrderedCollection new. ca@2177: ca@2177: inst := view controller. ca@2177: value := nil. ca@2177: ca@2177: inst isNil ifTrue:[ ca@2177: label := nil ca@2177: ] ifFalse:[ cg@2758: inst == view ifTrue:[ cg@2758: label := '== view itself' cg@2758: ] ifFalse:[ cg@2758: label := inst displayString. cg@2758: value := [view controller inspect]. cg@2758: ]. ca@2177: ]. ca@2177: list add:(MenuDesc title:'controller' value:label action:value). ca@2177: ca@2177: inst := view delegate. ca@2177: inst notNil ifTrue:[ ca@2177: list add:(MenuDesc title:'delegate' value:(inst displayString) action:[ view delegate inspect ]). ca@2177: ]. ca@2177: ca@2177: inst := view application. ca@2177: cg@2758: inst notNil ifTrue:[ cg@2758: |topAppl| cg@2758: ca@2177: list add:(MenuDesc title:'application' value:inst action:[ view application inspect ]). ca@2177: ca@2177: topAppl := inst topApplication. ca@2177: ca@2177: (topAppl notNil and:[topAppl ~~ inst]) ifTrue:[ ca@2177: list add:(MenuDesc title:'topApplication' value:topAppl action:[ inst topApplication inspect ]). ca@2177: ]. ca@2177: ]. ca@2177: list add:(MenuDesc separator). ca@2177: ca@2177: (view respondsTo:#'model:') ifTrue:[ ca@2177: inst := model. ca@2177: ca@2177: inst isNil ifTrue:[ label := value := nil ] ca@2177: ifFalse:[ label := inst displayString. ca@2177: value := [ view model inspect ]. ca@2177: ]. ca@2177: ca@2177: list add:(MenuDesc title:'model' value:label action:value). ca@2177: ca@2177: (inst notNil and:[view respondsTo:#modelInterface]) ifTrue:[ ca@2177: view modelInterface keysAndValuesDo:[:key : val| ca@2177: val isNil ifTrue:[ label := nil ] ca@2177: ifFalse:[ label := val displayString ]. ca@2177: ca@2177: list add:(MenuDesc title:(' - ', key) value:label ). ca@2177: ] ca@2177: ]. ca@2177: ]. ca@2177: ca@2177: (view respondsTo:#enableChannel) ifTrue:[ ca@2177: inst := view enableChannel. ca@2177: ca@2177: inst isNil ifTrue:[ label := value := nil ] ca@2177: ifFalse:[ label := inst displayString. ca@2177: value := [ view enableChannel inspect ]. ca@2177: ]. ca@2177: ca@2177: list add:(MenuDesc title:'enableChannel' value:label action:value). ca@2177: ]. ca@2177: ca@2177: list last isSeparator ifFalse:[ list add:(MenuDesc separator) ]. ca@2177: ca@2177: (view respondsTo:#listHolder) ifTrue:[ ca@2177: inst := view listHolder. ca@2177: ca@2177: inst isNil ifTrue:[ label := value := nil ] ca@2177: ifFalse:[ label := inst class printString. ca@2177: value := [ view listHolder inspect ]. ca@2177: ]. ca@2177: list add:(MenuDesc title:'listHolder' value:label action:value). ca@2177: ]. ca@2177: ca@2177: (view respondsTo:#list) ifTrue:[ ca@2177: inst := view list. ca@2177: ca@2177: inst isNil ifTrue:[ label := value := nil ] ca@2177: ifFalse:[ label := '%1 [%2]' bindWith:(inst class printString) with:(inst size). ca@2177: value := [ view list inspect ]. ca@2177: ]. ca@2177: ca@2177: list add:(MenuDesc title:'list' value:label action:value). ca@2177: ]. ca@2177: ca@2177: list last isSeparator ifTrue:[ list removeLast ]. ca@2177: ^ MenuDesc buildFromList:list onGC:aMenu ca@2177: ! ca@2177: ca@2177: submenuVisibility:aMenu ca@2455: "builds and returns the geometry submenu" ca@2455: ca@2177: |view list value| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[^ nil]. ca@2177: ca@2177: list := OrderedCollection new. ca@2177: ca@2177: list add:(MenuDesc title:'device' value:(view device printString)). ca@2177: list add:(MenuDesc title:'drawableId' value:(view id)). ca@2177: list add:(MenuDesc title:'gcId' value:(view gcId)). ca@2177: ca@2177: list add:(MenuDesc separator). ca@2177: ca@2177: list add:(MenuDesc title:'shown' value:(view shown)). ca@2177: list add:(MenuDesc title:'realized' value:(view realized)). ca@2177: ca@2177: list add:(MenuDesc separator). ca@2177: ca@2177: list add:(MenuDesc title:'hiddenOnRealize' value:(view isHiddenOnRealize)). ca@2177: ca@2177: (value := view visibilityChannel) isNil ifTrue:[ ca@2177: list add:(MenuDesc title:'visibilityChannel' value:'------'). ca@2177: ] ifFalse:[ ca@2177: list add:(MenuDesc title:'visibilityChannel' ca@2177: value:(value displayString) ca@2177: action:[view visibilityChannel inspect]). ca@2177: ]. ca@2177: cg@2758: ^ MenuDesc buildFromList:list onGC:aMenu ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'private'! ca@2177: ca@2177: selectFocusView ca@2177: |rootView focusItem focusView| ca@2177: ca@2177: rootView := model rootView. ca@2177: ca@2177: (rootView notNil and:[rootView shown]) ifTrue:[ ca@2177: focusView := rootView windowGroup focusView. ca@2177: ]. ca@2177: focusView isNil ifTrue:[^ self ]. ca@2177: ca@2177: focusItem := model selectedItem. ca@2177: ca@2177: (focusItem notNil and:[focusItem widget == focusView]) ifTrue:[ ca@2177: ^ self ca@2177: ]. ca@2177: focusItem := model listOfItems recursiveDetect:[:el| el widget == focusView ]. ca@2177: ca@2177: focusItem notNil ifTrue:[ ca@2177: model selectItem:focusItem. ca@2177: ]. ca@2177: ! ca@2177: ca@2177: setRootItem:aRootItemOrNil ca@2177: |theProcess| ca@2177: ca@2177: aRootItemOrNil isNil ifTrue:[ ca@2177: process := nil. ca@2177: ] ifFalse:[ ca@2177: "/ expand tree to level 3 ca@2177: aRootItemOrNil do:[:aRootChild| ca@2177: aRootChild do:[:aSubChild| aSubChild expand ]. ca@2177: aRootChild expand. ca@2177: ]. ca@2177: aRootItemOrNil expand. ca@2177: ca@2177: process isNil ifTrue:[ ca@2177: theProcess := process := ca@2455: Process for:[ |update testModeChannel| ca@2177: ca@2177: update := false. ca@2455: testModeChannel := model testModeChannel. ca@2177: ca@2455: [process == theProcess] whileTrue:[ ca@2177: Delay waitForSeconds:0.5. ca@2177: ca@2177: (treeView notNil and:[process == theProcess and:[treeView shown]]) ifTrue:[ ca@2455: (testModeChannel value == true and:[followFocusChannel value == true]) ifTrue:[ ca@2177: self selectFocusView. ca@2177: ]. ca@2177: update ifTrue:[ ca@2177: self updateShownStatus. ca@2177: ]. ca@2177: update := update not. ca@2177: ]. ca@2177: ]. ca@2177: ca@2177: ] priority:8. cg@2744: theProcess name:'ViewTreeInspector - Follow Focus'. ca@2177: theProcess resume. ca@2177: ]. ca@2177: ]. ca@2177: model rootItem:aRootItemOrNil. ca@2177: ! ca@2177: ca@2177: updateShownStatus ca@2177: |rootItem min max visState listIdx visY0 visY1 height damage| ca@2177: ca@2177: rootItem := model rootItem. ca@2177: (rootItem notNil and:[rootItem widget shown]) ifFalse:[^ self]. ca@2177: ca@2177: max := 0. ca@2177: min := 9999999. ca@2177: ca@2177: rootItem recursiveEachVisibleItemDo:[:anItem| ca@2177: visState := (anItem widget shown). ca@2177: ca@2177: visState ~~ anItem isDrawnShown ifTrue:[ ca@2177: anItem isDrawnShown:visState. ca@2177: listIdx := treeView identityIndexOf:anItem. ca@2177: ca@2177: listIdx > 0 ifTrue:[ ca@2177: max := max max:listIdx. ca@2177: min := min min:listIdx. ca@2177: ]. ca@2177: ]. ca@2177: ]. ca@2177: max < min ifTrue:[^ self]. ca@2177: max := max + 1. ca@2177: ca@2177: visY0 := (treeView yVisibleOfLine:min) max:0. ca@2177: visY1 := (treeView yVisibleOfLine:max) min:(treeView height). ca@2177: height := visY1 - visY0. ca@2177: ca@2177: height > 2 ifTrue:[ ca@2177: treeView shown ifTrue:[ ca@2177: damage := Rectangle left:0 top:visY0 width:(treeView width) height:height. ca@2177: treeView invalidateDeviceRectangle:damage repairNow:false. ca@2177: ]. ca@2177: ]. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'selection'! ca@2177: ca@2177: selectedView ca@2455: "answer the selected view or nil" ca@2455: ca@2177: |item| ca@2177: ca@2177: item := model selectedItem. ca@2177: item notNil ifTrue:[ ^ item widget ]. ca@2177: ^ nil ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'testing'! ca@2177: ca@2177: resolveApplicationClassFor:aTreeItem ca@2177: aTreeItem isApplicationClass ifTrue:[ ca@2177: ^ aTreeItem applicationClass ca@2177: ]. ca@2177: ^ nil ca@2177: ! ca@2177: ca@2177: selectedComponentHasChildren ca@2177: |item| ca@2177: ca@2177: item := model selectedItem. ca@2177: ^ (item notNil and:[item hasChildren]) ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication methodsFor:'user operations'! ca@2177: ca@2177: doBrowse:what ca@2177: "open browser on: ca@2177: #view browse class ca@2177: #model browse model class ca@2177: #application browse application class ca@2177: #controller browse controller class ca@2177: " ca@2177: |view inst| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[^ self]. ca@2177: ca@2177: what == #view ifTrue:[ inst := view ] ca@2177: ifFalse:[what == #model ifTrue:[ inst := view model ] ca@2177: ifFalse:[what == #application ifTrue:[ inst := view application ] ca@2177: ifFalse:[what == #controller ifTrue:[ inst := view controller ] ca@2177: ifFalse:[ ca@2177: ^ self ca@2177: ]]]]. ca@2177: ca@2177: inst notNil ifTrue:[ ca@2177: inst class browserClass openInClass:(inst class) selector:nil ca@2177: ]. ca@2177: ! ca@2177: ca@2177: doDestroy ca@2455: "destroy the current selected view" ca@2455: ca@2177: |item parent| ca@2177: ca@2177: item := model selectedItem. ca@2177: item isNil ifTrue:[ ^ self]. ca@2177: ca@2177: parent := item parent. ca@2177: ca@2177: parent isNil ifTrue:[ ca@2177: "/ the root ca@2177: model withSelectionHiddenDo:[item deleteAll]. ca@2177: ^ self ca@2177: ]. ca@2177: ca@2177: model withSelectionHiddenDo:[ ca@2177: |idx nsel| ca@2177: ca@2177: idx := parent identityIndexOf:item. ca@2177: ca@2177: idx == parent size ifTrue:[ ca@2177: nsel := parent at:(idx - 1) ifAbsent:parent ca@2177: ] ifFalse:[ ca@2177: nsel := parent at:(idx + 1) ca@2177: ]. ca@2177: model setValue:nil. ca@2177: item delete. ca@2177: ca@2177: parent isLayoutContainer ifTrue:[ ca@2177: parent widget sizeChanged:nil ca@2177: ]. ca@2177: model value:nsel. ca@2177: ]. ca@2177: ! ca@2177: ca@2177: doFlash ca@2455: "flash the selected view" ca@2455: ca@2177: |view| ca@2177: ca@2177: view := self selectedView. ca@2177: view isNil ifTrue:[ ^ self]. ca@2177: ca@2177: view shown ifTrue:[ ca@2177: model withSelectionHiddenDo:[ ca@2177: view perform:#flash ifNotUnderstood:nil. ca@2177: ]. ca@2177: ]. ca@2177: ! ca@2177: ca@2177: doInspect:what ca@2177: "open inspector on: ca@2177: #view inspect class ca@2177: #group inspect windowGroup ca@2177: #model inspect model ca@2177: #application inspect application ca@2177: #controller inspect controller ca@2177: " ca@2177: |inst| ca@2177: ca@2177: inst := self selectedView. ca@2177: inst isNil ifTrue:[^ self]. ca@2177: ca@2177: what == #group ifTrue:[ inst := inst windowGroup ] ca@2177: ifFalse:[what == #model ifTrue:[ inst := inst model ] ca@2177: ifFalse:[what == #application ifTrue:[ inst := inst application ] ca@2177: ifFalse:[what == #controller ifTrue:[ inst := inst controller ]]]]. ca@2177: ca@2177: inst notNil ifTrue:[ inst inspect ]. ca@2177: ! ca@2177: ca@2177: doPickViews ca@2455: "pick a window's topView" ca@2455: cg@2759: |screen window cursor| ca@2177: ca@2177: self doUnpick. ca@2177: cg@2759: cursor := Cursor fromImage:(self class crossHairIcon). cg@2759: cg@2759: screen := Screen current. cg@2759: window := screen viewFromPoint:(screen pointFromUserShowing:cursor). ca@2177: window isNil ifTrue:[^ self]. ca@2177: ca@2177: window := window topView. ca@2177: ca@2177: ( window == Screen current rootView ca@2177: or:[window == self window topView] ca@2177: ) ifTrue:[ ca@2177: ^ self ca@2177: ]. ca@2177: self setRootItem:(ViewTreeItem buildViewsFrom:window). ca@2177: ! ca@2177: ca@2177: doSelectNextOfApplicationClass:aClass startingIn:anItem ca@2177: |startItem firstFound searchNext| ca@2177: ca@2177: startItem := model last. ca@2177: searchNext := startItem notNil. ca@2177: firstFound := nil. ca@2177: ca@2177: anItem recursiveDo:[:el| ca@2177: el == startItem ifTrue:[ ca@2177: searchNext := false ca@2177: ] ifFalse:[ ca@2177: (self resolveApplicationClassFor:el) == aClass ifTrue:[ ca@2177: searchNext ifFalse:[^ model selectItem:el]. ca@2177: ca@2177: firstFound isNil ifTrue:[ ca@2177: firstFound := el ca@2177: ] ca@2177: ] ca@2177: ] ca@2177: ]. ca@2177: firstFound notNil ifTrue:[ ca@2177: self window beep. ca@2177: model selectItem:firstFound ca@2177: ]. ca@2177: ! ca@2177: ca@2177: doSelectNextOfClass:aClass startingIn:anItem ca@2177: |startItem firstFound searchNext| ca@2177: ca@2177: startItem := model last. ca@2177: searchNext := startItem notNil. ca@2177: firstFound := nil. ca@2177: ca@2177: anItem recursiveDo:[:el| ca@2177: el == startItem ifTrue:[ ca@2177: searchNext := false ca@2177: ] ifFalse:[ ca@2177: el widget class == aClass ifTrue:[ ca@2177: searchNext ifFalse:[^ model selectItem:el]. ca@2177: ca@2177: firstFound isNil ifTrue:[ ca@2177: firstFound := el ca@2177: ] ca@2177: ] ca@2177: ] ca@2177: ]. ca@2177: firstFound notNil ifTrue:[ ca@2177: self window beep. ca@2177: model selectItem:firstFound ca@2177: ]. ca@2177: ! ca@2177: ca@2177: doUnpick ca@2455: "release current picked window and contained subwindows" ca@2455: ca@2177: self setRootItem:nil. cg@2744: ! cg@2744: cg@2744: openDocumentation cg@2744: HTMLDocumentView openFullOnDocumentationFile:'tools/misc/TOP.html#VIEWTREEINSPECTOR' ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc class methodsFor:'building'! ca@2177: ca@2177: buildFromList:aList onGC:aMenu ca@2177: |tabSpec menu w menuPanel| ca@2177: ca@2177: w := 0. ca@2177: aList do:[:el| w := w max:(el widthOn:aMenu) ]. ca@2177: ca@2177: tabSpec := TabulatorSpecification new. ca@2177: tabSpec unit:#pixel. ca@2177: tabSpec positions:#(0 1.5 ). ca@2177: tabSpec align:#(#left #left). ca@2177: ca@2177: w := w + 15. ca@2177: tabSpec positions:(Array with:0 with:w). ca@2177: ca@2177: menu := Menu new. ca@2177: ca@2177: aList do:[:el| ca@2177: menu addItem:(el asMenuItemWithTabulatorSpecification:tabSpec). ca@2177: ]. ca@2177: menuPanel := MenuPanel menu:menu. ca@2177: ^ menuPanel ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc class methodsFor:'instance creation'! ca@2177: ca@2177: separator ca@2177: ^ self new ca@2177: ! ca@2177: ca@2177: title:aTitle value:aValue ca@2177: ^ self title:aTitle value:aValue action:nil ca@2177: ! ca@2177: ca@2177: title:aTitle value:aValue action:anAction ca@2177: ^ self new title:aTitle value:aValue action:anAction ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc methodsFor:'accessing'! ca@2177: ca@2177: title ca@2177: ^ title ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc methodsFor:'building'! ca@2177: ca@2177: asMenuItemWithTabulatorSpecification:aTabSpec ca@2177: |array| ca@2177: ca@2177: title isNil ifTrue:[ ^ MenuItem label:value ]. "/ separator ca@2177: ca@2177: array := Array with:(title, ':') with:'------'. ca@2177: ca@2177: value notNil ifTrue:[ ca@2177: array at:2 put:(value printString, ' ') ca@2177: ]. ca@2177: cg@2758: ^ MenuItem cg@2758: label:(MultiColListEntry fromStrings:array tabulatorSpecification:aTabSpec) cg@2758: value:action ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc methodsFor:'instance creation'! ca@2177: ca@2177: title:aTitle value:aValue action:anAction ca@2177: "test for separator ca@2177: " ca@2177: title := aTitle withoutSeparators. ca@2177: action := anAction. ca@2177: ca@2177: aValue notNil ifTrue:[ ca@2177: value := aValue printString. ca@2177: ca@2177: value size > 70 ifTrue:[ ca@2177: value := value copyFrom:1 to:70. ca@2177: value := value, '...' ca@2177: ] ca@2177: ]. ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::MenuDesc methodsFor:'queries'! ca@2177: ca@2177: isSeparator ca@2177: ^ title isNil ca@2177: ! ca@2177: ca@2177: widthOn:aGC ca@2177: title isNil ifTrue:[^ 5]. "/ separator cg@2758: ^ title widthOn:aGC ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'building'! cg@2744: cg@2744: buildViewsFrom:aView cg@2744: "build the items starting from a source view; cg@2744: returns the anhor. cg@2744: " cg@2744: |item subViews subItems| cg@2744: cg@2744: aView isNil ifTrue:[^ nil]. cg@2744: cg@2744: item := self forView:aView. cg@2744: subViews := aView subViews. cg@2744: cg@2744: subViews notEmptyOrNil ifTrue:[ cg@2744: subItems := OrderedCollection new. cg@2744: subViews do:[:aSubView| cg@2744: subItems add:(self buildViewsFrom:aSubView). cg@2744: ]. cg@2744: item children:subItems. cg@2744: ]. cg@2744: ^ item cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'documentation'! cg@2744: cg@2744: documentation cg@2744: " cg@2744: ViewTreeItems represants a pickable object within a ViewTreeModel. cg@2744: The class is used to build up the hierarchical tree. cg@2744: cg@2744: [Instance variables:] cg@2744: widget the widget represented by the item cg@2744: spec the UISpecification or nil cg@2744: cg@2744: [Class variables:] cg@2744: HandleExtent keeps the extent of a handle cg@2744: cg@2744: cg@2744: [author:] cg@2744: Claus Atzkern cg@2744: cg@2744: [see also:] cg@2744: HierarchicalItem cg@2744: ViewTreeModel cg@2744: " cg@2744: ! ca@2177: ca@2177: version ca@2177: ^ '$Header$' ca@2177: ! ! ca@2177: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'initialization'! cg@2744: cg@2744: initialize cg@2744: "set the extent of the Handle cg@2744: " cg@2744: HandleExtent := 6@6. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem class methodsFor:'instance creation'! cg@2744: cg@2744: forView:aView cg@2744: |item| cg@2744: cg@2744: item := self basicNew initialize. cg@2744: item forView:aView. cg@2744: ^ item cg@2744: ! cg@2744: cg@2744: new cg@2744: self error:'not allowed'. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: on:aView withSpec:aSpec cg@2744: |item| cg@2744: cg@2744: item := self basicNew initialize. cg@2744: item on:aView withSpec:aSpec. cg@2744: ^ item cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing'! cg@2744: cg@2744: applicationClass cg@2744: |appl| cg@2744: cg@2744: widget notNil ifTrue:[ cg@2744: appl := widget application. cg@2744: appl notNil ifTrue:[^ appl class ]. cg@2744: ]. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: isDrawnShown cg@2744: "returns true if the last display operations was done during the widget was shown cg@2744: " cg@2744: ^ isDrawnShown cg@2744: ! cg@2744: cg@2744: isDrawnShown:aBoolean cg@2744: isDrawnShown := aBoolean. cg@2744: ! cg@2744: cg@2744: rootView cg@2744: "returns the widget assigned to the root or nil cg@2744: " cg@2744: ^ parent rootView cg@2744: ! cg@2744: cg@2744: specClass cg@2744: "returns the spec-class assigned to the item cg@2744: " cg@2744: ^ widget specClass cg@2744: ! cg@2744: cg@2744: treeModel cg@2744: "returns the assigned treeModel, an instance of ViewTreeModel cg@2744: " cg@2744: ^ parent treeModel cg@2744: ! cg@2744: cg@2744: widget cg@2744: "returns the widget assigned to the item cg@2744: " cg@2744: ^ widget cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing layout'! cg@2744: cg@2744: boundsRelativeToRoot cg@2744: "returns the bounds relative to the root widget cg@2744: " cg@2744: ^ self originRelativeToRoot extent:(widget extent) cg@2744: ! cg@2744: cg@2744: cornerRelativeToRoot cg@2744: "returns the corner relative to the root widget cg@2744: " cg@2744: ^ self originRelativeToRoot + (widget extent) cg@2744: ! cg@2744: cg@2744: extent cg@2744: "returns the extent of the widget cg@2744: " cg@2744: ^ widget extent cg@2744: ! cg@2744: cg@2744: layoutType cg@2744: "returns the type of layout assigned to the wiget; nil if the cg@2744: superView cannot resize its sub widgets cg@2744: " cg@2744: |layout specClass superView| cg@2744: cg@2744: (superView := widget superView) isNil ifTrue:[ cg@2744: ^ #Extent cg@2744: ]. cg@2744: cg@2744: specClass := superView specClass. cg@2744: cg@2744: (specClass notNil and:[specClass isLayoutContainer]) ifTrue:[ cg@2744: ^ specClass canResizeSubComponents ifTrue:[#Extent] ifFalse:[nil] cg@2744: ]. cg@2744: cg@2744: (layout := widget geometryLayout) isNil ifTrue:[ cg@2744: ^ #Extent cg@2744: ]. cg@2744: cg@2744: layout isLayout ifTrue:[ cg@2744: layout isLayoutFrame ifTrue:[ ^ #LayoutFrame ]. cg@2744: layout isAlignmentOrigin ifTrue:[ ^ #AlignmentOrigin ]. cg@2744: layout isLayoutOrigin ifTrue:[ ^ #LayoutOrigin ]. cg@2744: ] ifFalse:[ cg@2744: layout isRectangle ifTrue:[ ^ #Rectangle ]. cg@2744: layout isPoint ifTrue:[ ^ #Point ]. cg@2744: cg@2744: ]. cg@2744: Transcript showCR:'UNSUPPORTRD LAYOUT: ', layout printString. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: originRelativeToRoot cg@2744: "returns the origin relative to the root widget cg@2744: " cg@2744: ^ widget originRelativeTo:(self rootView) cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'accessing optimize'! cg@2744: cg@2744: children cg@2744: "redefined: optimize cg@2744: " cg@2744: ^ children cg@2744: ! cg@2744: cg@2744: hasChildren cg@2744: |subViews list item| cg@2744: cg@2744: children size ~~ 0 ifTrue:[ cg@2744: ^ true cg@2744: ]. cg@2744: isExpanded := false. cg@2744: subViews := widget subViews. cg@2744: cg@2744: subViews size == 0 ifTrue:[^ false]. cg@2744: cg@2744: list := OrderedCollection new. cg@2744: cg@2744: subViews do:[:aSubView| cg@2744: item := self class buildViewsFrom:aSubView. cg@2744: item parent:self. cg@2744: list add:item. cg@2744: ]. cg@2744: children := list. cg@2744: ^ true cg@2744: ! cg@2744: cg@2744: size cg@2744: "redefined: returns list of children cg@2744: " cg@2744: ^ children size cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'displaying'! cg@2744: cg@2744: additionalLabelForItem:anItem cg@2744: "answer an additional item for an Item or nil" cg@2744: cg@2744: parent notNil ifTrue:[ cg@2744: ^ parent additionalLabelForItem:anItem cg@2744: ]. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: displayIcon:anIcon atX:x y:y on:aGC cg@2744: |x0 y0 y1 w| cg@2744: cg@2744: super displayIcon:anIcon atX:x y:y on:aGC. cg@2744: cg@2744: self exists ifFalse:[ cg@2744: aGC paint:(Color red). cg@2744: cg@2744: y0 := y + 1. cg@2744: y1 := y + anIcon height - 2. cg@2744: cg@2744: x0 := x - 1. cg@2744: w := anIcon width. cg@2744: cg@2744: 2 timesRepeat:[ cg@2744: aGC displayLineFromX:x0 y:y0 toX:(x0 + w) y:y1. cg@2744: aGC displayLineFromX:x0 y:y1 toX:(x0 + w) y:y0. cg@2744: x0 := x0 + 1. cg@2744: ]. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: displayOn:aGC x:x y:y h:h cg@2744: |labelHeight additionalName label isValidAndShown| cg@2744: cg@2744: label := self label. cg@2744: label isEmptyOrNil ifTrue:[^ self]. cg@2744: cg@2744: widget id isNil ifTrue:[ cg@2744: isDrawnShown := false. cg@2744: cg@2744: self exists ifFalse:[ cg@2744: xOffsetAdditionalName := nil. cg@2744: ]. cg@2744: isValidAndShown := false. cg@2744: ] ifFalse:[ cg@2744: isValidAndShown := widget shown. cg@2744: ]. cg@2744: isValidAndShown ifFalse:[ cg@2744: label := Text string:label emphasis:#italic cg@2744: ]. cg@2744: cg@2744: labelHeight := self heightOn:aGC. cg@2744: self displayLabel:label h:labelHeight on:aGC x:x y:y h:h. cg@2744: cg@2744: xOffsetAdditionalName notNil ifTrue:[ cg@2744: additionalName := self additionalLabelForItem:self. cg@2744: cg@2744: additionalName notNil ifTrue:[ cg@2744: self displayLabel:additionalName cg@2744: h:labelHeight on:aGC cg@2744: x:(x + xOffsetAdditionalName) cg@2744: y:y cg@2744: h:h. cg@2744: ] ifFalse:[ cg@2744: xOffsetAdditionalName := nil. cg@2744: ]. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: recursiveAdditionalNameBehaviourChanged cg@2744: width := xOffsetAdditionalName := nil. cg@2744: cg@2744: children notNil ifTrue:[ cg@2744: children do:[:each| each recursiveAdditionalNameBehaviourChanged ] cg@2744: ]. cg@2744: ! cg@2744: cg@2744: widthOn:aGC cg@2744: "return the width of the receiver, if it is to be displayed on aGC cg@2744: " cg@2744: |additionalName| cg@2744: cg@2744: width isNil ifTrue:[ cg@2744: width := self widthOf:(self label) on:aGC. cg@2744: width := width + 2. cg@2744: cg@2744: additionalName := self additionalLabelForItem:self. cg@2744: cg@2744: additionalName notNil ifTrue:[ cg@2744: xOffsetAdditionalName := width + 10. cg@2744: width := xOffsetAdditionalName + (self widthOf:additionalName on:aGC). cg@2744: width := width + 2. cg@2744: ] ifFalse:[ cg@2744: xOffsetAdditionalName := nil. cg@2744: ]. cg@2744: ]. cg@2744: ^ width cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'enumerating'! cg@2744: cg@2744: handlesDo:aTwoArgAction cg@2744: "evaluate the two arg block on each handle; the arguments to the block is cg@2744: the rectangle relative to the rootView and the handle type which is cg@2744: set to nil if not resizeable. cg@2744: cg@2744: TYPES: type position( X - Y ) cg@2744: ------------------------- cg@2744: #LT Left - Top cg@2744: #LC Left - Center cg@2744: #LB Left - Bottom cg@2744: #CT Center - Top cg@2744: #CB Center - Bottom cg@2744: #RT Right - Top cg@2744: #RC Right - Center cg@2744: #RB Right - Bottom cg@2744: cg@2744: nil ** handle not pickable ** cg@2744: " cg@2744: |type relOrg relCrn maxExt rootView w h cg@2744: xL "{ Class:SmallInteger }" cg@2744: xC "{ Class:SmallInteger }" cg@2744: xR "{ Class:SmallInteger }" cg@2744: yT "{ Class:SmallInteger }" cg@2744: yC "{ Class:SmallInteger }" cg@2744: yB "{ Class:SmallInteger }" cg@2744: | cg@2744: rootView := self rootView. cg@2744: relOrg := widget originRelativeTo:rootView. cg@2744: relOrg isNil ifTrue:[ ^ self ]. "/ widget destroyed cg@2744: cg@2744: relOrg := relOrg - (HandleExtent // 2). cg@2744: relCrn := relOrg + widget extent. cg@2744: maxExt := rootView extent - HandleExtent. cg@2744: cg@2744: xL := relOrg x max:0. cg@2744: xR := relCrn x min:(maxExt x). cg@2744: xC := xR + xL // 2. cg@2744: cg@2744: yT := relOrg y max:0. cg@2744: yB := relCrn y min:(maxExt y). cg@2744: yC := yB + yT // 2. cg@2744: cg@2744: type := self layoutType. cg@2744: w := HandleExtent x. cg@2744: h := HandleExtent y. cg@2744: cg@2744: (type == #LayoutFrame or:[type == #Rectangle]) ifTrue:[ cg@2744: aTwoArgAction value:(Rectangle left:xL top:yT width:w height:h) value:#LT. cg@2744: aTwoArgAction value:(Rectangle left:xL top:yC width:w height:h) value:#LC. cg@2744: aTwoArgAction value:(Rectangle left:xL top:yB width:w height:h) value:#LB. cg@2744: aTwoArgAction value:(Rectangle left:xC top:yT width:w height:h) value:#CT. cg@2744: aTwoArgAction value:(Rectangle left:xC top:yB width:w height:h) value:#CB. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yT width:w height:h) value:#RT. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yC width:w height:h) value:#RC. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:#RB. cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: aTwoArgAction value:(Rectangle left:xL top:yT width:w height:h) value:nil. cg@2744: aTwoArgAction value:(Rectangle left:xL top:yB width:w height:h) value:nil. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yT width:w height:h) value:nil. cg@2744: cg@2744: type == #Extent ifTrue:[ cg@2744: aTwoArgAction value:(Rectangle left:xC top:yB width:w height:h) value:#CB. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yC width:w height:h) value:#RC. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:#RB. cg@2744: ^ self cg@2744: ]. cg@2744: aTwoArgAction value:(Rectangle left:xR top:yB width:w height:h) value:nil. cg@2744: ! cg@2744: cg@2744: recursiveEachVisibleItemDo:anOneArgBlock cg@2744: "recursive evaluate the block on each child which is visible cg@2744: " cg@2744: (isExpanded and:[children size > 0]) ifTrue:[ cg@2744: children do:[:aChild| cg@2744: anOneArgBlock value:aChild. cg@2744: aChild recursiveEachVisibleItemDo:anOneArgBlock. cg@2744: ] cg@2744: ]. cg@2744: ! cg@2744: cg@2744: subViewsDo:aOneArgBlock cg@2744: "evaluate aBlock for all subviews other than InputView's cg@2744: " cg@2744: |subViews| cg@2744: cg@2744: subViews := widget subViews. cg@2744: cg@2744: subViews notNil ifTrue:[ cg@2744: subViews do:aOneArgBlock cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'initialization'! cg@2744: cg@2744: forView:aView cg@2744: widget := aView. cg@2744: ! cg@2744: cg@2744: initialize cg@2744: "setup default attributes cg@2744: " cg@2744: super initialize. cg@2744: isDrawnShown := false. cg@2744: isExpanded := false. cg@2744: children := OrderedCollection new. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations delete'! cg@2744: cg@2744: delete cg@2744: "delete self and all contained items; the assigned views are destroyed cg@2744: in case of rootView, only the children are deleted cg@2744: " cg@2744: parent isHierarchicalItem ifTrue:[ cg@2744: self criticalDo:[ cg@2744: parent remove:self. cg@2744: widget destroy. cg@2744: ] cg@2744: ] ifFalse:[ cg@2744: self deleteAll cg@2744: ]. cg@2744: ! cg@2744: cg@2744: deleteAll cg@2744: "delete all contained items; the assigned views are destroyed cg@2744: " cg@2744: children size == 0 ifTrue:[^ self]. cg@2744: cg@2744: self criticalDo:[ cg@2744: self nonCriticalDo:[:el| el widget destroy ]. cg@2744: self removeAll cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations layout'! cg@2744: cg@2744: asLayoutFrame cg@2744: "convert the layout of the widget to a LayoutFrame; cg@2744: " cg@2744: |extent layout newLyt lftFrc lftOff topFrc topOff| cg@2744: cg@2744: layout := widget geometryLayout. cg@2744: cg@2744: layout isNil ifTrue:[ cg@2744: ^ widget bounds asLayout cg@2744: ]. cg@2744: cg@2744: layout isLayout ifFalse:[ cg@2744: layout isRectangle ifTrue:[ cg@2744: ^ LayoutFrame leftOffset:(layout left) rightOffset:(layout right) cg@2744: topOffset:(layout top) bottomOffset:(layout bottom) cg@2744: ]. cg@2744: layout isPoint ifTrue:[ cg@2744: extent := widget extent. cg@2744: ^ LayoutFrame leftOffset:(layout x) rightOffset:(layout x + extent x) cg@2744: topOffset:(layout y) bottomOffset:(layout y + extent y) cg@2744: ]. cg@2744: cg@2744: Transcript showCR:'UNSUPPORTRD LAYOUT: ', layout printString. cg@2744: ^ nil cg@2744: ]. cg@2744: cg@2744: layout isLayoutFrame ifTrue:[ ^ layout copy ]. cg@2744: cg@2744: lftFrc := layout leftFraction. cg@2744: lftOff := layout leftOffset. cg@2744: topFrc := layout topFraction. cg@2744: topOff := layout topOffset. cg@2744: extent := widget extent. cg@2744: cg@2744: newLyt := LayoutFrame leftFraction:lftFrc offset:lftOff cg@2744: rightFraction:lftFrc offset:(lftOff + extent x) cg@2744: topFraction:topFrc offset:topOff cg@2744: bottomFraction:topFrc offset:(topOff + extent y). cg@2744: cg@2744: ( layout isAlignmentOrigin cg@2744: and:[(layout leftAlignmentFraction ~= 0 or:[layout topAlignmentFraction ~= 0])] cg@2744: ) ifTrue:[ cg@2744: |svRc prBd dlta| cg@2744: cg@2744: svRc := widget superView viewRectangle. cg@2744: prBd := widget preferredBounds. cg@2744: cg@2744: dlta := ( ((layout rectangleRelativeTo:svRc preferred:prBd) corner) cg@2744: - ((newLyt rectangleRelativeTo:svRc preferred:prBd) corner) cg@2744: ) rounded. cg@2744: cg@2744: newLyt leftOffset:(lftOff + dlta x). cg@2744: newLyt rightOffset:(lftOff + extent x + dlta x). cg@2744: newLyt topOffset:(topOff + dlta y). cg@2744: newLyt bottomOffset:(topOff + extent y + dlta y). cg@2744: ]. cg@2744: ^ newLyt cg@2744: ! cg@2744: cg@2744: moveLeft:l top:t cg@2744: "move the widget n pixele left and right cg@2744: " cg@2744: |layout| cg@2744: cg@2744: self isMoveable ifFalse:[ ^ self ]. cg@2744: cg@2744: (layout := widget geometryLayout) isNil ifTrue:[ cg@2744: "Extent" cg@2744: widget origin:(widget origin + (l@t)). cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: layout := layout copy. cg@2744: cg@2744: layout isLayout ifTrue:[ cg@2744: layout leftOffset:(layout leftOffset + l) cg@2744: topOffset:(layout topOffset + t). cg@2744: cg@2744: layout isLayoutFrame ifTrue:[ cg@2744: layout rightOffset:(layout rightOffset + l). cg@2744: layout bottomOffset:(layout bottomOffset + t). cg@2744: ] cg@2744: cg@2744: ] ifFalse:[ cg@2744: layout isRectangle ifTrue:[ cg@2744: layout setLeft:(layout left + l). cg@2744: layout setTop:(layout top + t). cg@2744: ] ifFalse:[ cg@2744: layout isPoint ifFalse:[^ self]. cg@2744: layout x:(layout x + l) y:(layout y + t). cg@2744: ] cg@2744: ]. cg@2744: widget geometryLayout:layout. cg@2744: ! cg@2744: cg@2744: resizeLeft:l top:t right:r bottom:b cg@2744: "resize the widget measured in pixels cg@2744: " cg@2744: |layout| cg@2744: cg@2744: self isResizeable ifFalse:[ cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: (layout := widget geometryLayout) isNil ifTrue:[ cg@2744: "Extent" cg@2744: (r == l and:[b == t]) ifFalse:[ cg@2744: widget extent:(widget computeExtent + ((r-l) @ (b-t))). cg@2744: ]. cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: layout isLayout ifTrue:[ cg@2744: layout := layout copy. cg@2744: cg@2744: layout leftOffset:(layout leftOffset + l) cg@2744: topOffset:(layout topOffset + t). cg@2744: cg@2744: layout isLayoutFrame ifTrue:[ cg@2744: layout bottomOffset:(layout bottomOffset + b). cg@2744: layout rightOffset:(layout rightOffset + r). cg@2744: ] cg@2744: ] ifFalse:[ cg@2744: layout isRectangle ifFalse:[^ self]. cg@2744: layout := layout copy. cg@2744: cg@2744: layout left:(layout left + l) cg@2744: right:(layout right + r) cg@2744: top:(layout top + t) cg@2744: bottom:(layout bottom + b). cg@2744: ]. cg@2744: widget geometryLayout:layout. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'operations update'! cg@2744: cg@2744: updateChildren cg@2744: |list| cg@2744: cg@2744: self do:[:el| cg@2744: el exists ifTrue:[ cg@2744: el updateChildren. cg@2744: ] ifFalse:[ cg@2744: list isNil ifTrue:[list := OrderedCollection new]. cg@2744: list add:el. cg@2744: ] cg@2744: ]. cg@2744: list notNil ifTrue:[ cg@2744: list do:[:el| self remove:el ]. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: updateFromChildren:mergedList cg@2744: "update my children against the list of items derived from cg@2744: the merged list. cg@2744: " cg@2744: cg@2744: mergedList size == 0 ifTrue:[ ^ self removeAll ]. cg@2744: children size == 0 ifTrue:[ ^ self addAll:mergedList ]. cg@2744: cg@2744: self criticalDo:[ cg@2744: self nonCriticalDo:[:el| |wdg| cg@2744: wdg := el widget. cg@2744: mergedList detect:[:e2| e2 widget == wdg ] ifNone:[ self remove:el ]. cg@2744: ]. cg@2744: cg@2744: mergedList keysAndValuesDo:[:i :el| |wdg e2| cg@2744: wdg := el widget. cg@2744: cg@2744: e2 := self at:i ifAbsent:nil. cg@2744: cg@2744: (e2 isNil or:[e2 widget ~~ wdg]) ifTrue:[ cg@2744: self add:el beforeIndex:i cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'printing & storing'! cg@2744: cg@2744: icon cg@2744: "get the icon used for presentation cg@2744: " cg@2744: |specClass model| cg@2744: cg@2744: specClass := self specClass. cg@2744: specClass isNil ifTrue:[^ nil]. cg@2744: cg@2744: model := self treeModel. cg@2744: cg@2744: model notNil ifTrue:[ cg@2744: ^ model iconAt:specClass ifNonePut:[specClass icon] cg@2744: ]. cg@2744: ^ specClass icon cg@2744: ! cg@2744: cg@2744: label cg@2744: "get the label used for presentation cg@2744: " cg@2744: ^ self string cg@2744: ! cg@2744: cg@2744: printOn:aStream cg@2744: "append a a printed representation of the item to aStream cg@2744: " cg@2744: aStream nextPutAll:(self string) cg@2744: ! cg@2744: cg@2744: string cg@2744: "get the string cg@2744: " cg@2744: ^ widget class name. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'queries'! cg@2744: cg@2744: canChangeLayout cg@2744: "returns true if the layout of the widget can be changed and the cg@2744: layout is not organized by its superView cg@2744: " cg@2744: ^ self isResizeable cg@2744: ! cg@2744: cg@2744: canResizeSubComponents cg@2744: "returns true if the widget can resize its sub components cg@2744: " cg@2744: |specClass| cg@2744: cg@2744: specClass := self specClass. cg@2744: cg@2744: specClass notNil ifTrue:[ cg@2744: ^ specClass canResizeSubComponents cg@2744: ]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: exists cg@2744: widget id notNil ifTrue:[^ true ]. cg@2744: cg@2744: exists ~~ false ifTrue:[ cg@2744: exists := false. cg@2744: cg@2744: widget superView notNil ifTrue:[ cg@2744: (parent isHierarchicalItem and:[parent exists]) ifTrue:[ cg@2744: exists := (parent widget subViews includesIdentical:widget). cg@2744: ]. cg@2744: ]. cg@2744: ]. cg@2744: ^ exists cg@2744: ! cg@2744: cg@2744: isApplicationClass cg@2744: |cls| cg@2744: cg@2744: cls := widget class. cg@2744: cg@2744: ^ ( cls == ApplicationSubView cg@2744: or:[cls == ApplicationWindow cg@2744: or:[cls == SubCanvas]] cg@2744: ) cg@2744: ! cg@2744: cg@2744: isSelected cg@2744: |model| cg@2744: cg@2744: model := self treeModel. cg@2744: model notNil ifTrue:[^ model isSelected:self]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: supportsSubComponents cg@2744: "returns true if the widget supports sub components cg@2744: " cg@2744: |specClass| cg@2744: cg@2744: widget isScrollWrapper ifTrue:[ cg@2744: ^ false cg@2744: ]. cg@2744: specClass := self specClass. cg@2744: cg@2744: specClass notNil ifTrue:[ cg@2744: ^ specClass supportsSubComponents cg@2744: ]. cg@2744: ^ false cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeItem methodsFor:'testing'! cg@2744: cg@2744: isInLayoutContainer cg@2744: "returns true if the widget is in a layout container cg@2744: " cg@2744: |sv specClass| cg@2744: cg@2744: sv := widget superView. cg@2744: cg@2744: sv notNil ifTrue:[ cg@2744: specClass := sv specClass. cg@2744: cg@2744: specClass notNil ifTrue:[ cg@2744: ^ specClass isLayoutContainer cg@2744: ]. cg@2744: ]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: isLayoutContainer cg@2744: "answer whether corresponding view instances of the spec class can contain cg@2744: (and arrange) other view cg@2744: " cg@2744: |specClass| cg@2744: cg@2744: specClass := self specClass. cg@2744: cg@2744: specClass notNil ifTrue:[ cg@2744: ^ specClass isLayoutContainer cg@2744: ]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: isMoveable cg@2744: "returns true if the widget is not in a layout container cg@2744: " cg@2744: self isInLayoutContainer ifFalse:[ cg@2744: ^ widget superView notNil cg@2744: ]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: isResizeable cg@2744: "returns true if the widget is resizeable cg@2744: " cg@2744: |sv specClass| cg@2744: cg@2744: sv := widget superView. cg@2744: cg@2744: sv notNil ifTrue:[ cg@2744: specClass := sv specClass. cg@2744: cg@2744: specClass notNil ifTrue:[ cg@2744: ^ specClass canResizeSubComponents cg@2744: ]. cg@2744: ]. cg@2744: ^ false cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel class methodsFor:'documentation'! cg@2744: cg@2744: documentation cg@2744: " cg@2744: Instances of ViewTreeModel can be used as model on a View and all cg@2744: it contained subviews for a HierarchicalListView. cg@2744: The model keeps two values, the hierarchical representation of the views cg@2744: and subviews (ViewTreeItems) and the selection, a list of selected ViewTreeItems's. cg@2744: It shows the selected items highlighted. cg@2744: cg@2744: cg@2744: [Instance variables:] cg@2744: lockSema lock selection notifications and redraws cg@2744: cg@2744: testModeChannel true, than running in test mode. cg@2744: cg@2744: hasTargetWidgetChannel true, than any target view is grapped cg@2744: cg@2744: selection selected items or nil cg@2744: cg@2744: hiddenLevel internal use; redrawing the selection cg@2744: only is done if the counter is 0. cg@2744: cg@2744: listOfItems hiearchical list build from existing items. cg@2744: cg@2744: selectedSuperItems list of selected super items; items selected cg@2744: but not contained in another selected item. cg@2744: cg@2744: inputEventAction called for each InputEvent cg@2744: cg@2744: mappedViewAction called for a new mapped view which cg@2744: can not be found in the current item list. cg@2744: cg@2744: beforeSelectionChangedAction called before the selection changed cg@2744: cg@2744: [author:] cg@2744: Claus Atzkern cg@2744: cg@2744: [see also:] cg@2744: ViewTreeItem cg@2744: " cg@2744: ! cg@2744: cg@2744: examples cg@2744: " cg@2744: example 1: pick any window and show views and contained views cg@2744: [exBegin] cg@2744: |top sel model panel| cg@2744: cg@2744: model := ViewTreeModel new. cg@2744: top := StandardSystemView new; extent:440@400. cg@2744: sel := ScrollableView for:HierarchicalListView miniScroller:true origin:0.0@0.0 corner:1.0@1.0 in:top. cg@2744: sel bottomInset:24. cg@2744: cg@2744: panel := HorizontalPanelView origin:0.0@1.0 corner:1.0@1.0 in:top. cg@2744: panel topInset:-24. cg@2744: panel horizontalLayout:#fitSpace. cg@2744: cg@2744: Button label:'Exit' action:[model rootItem:nil. top destroy] in:panel. cg@2744: Button label:'Pick Views' action:[ |win| cg@2744: ( (win := Screen current viewFromUser) notNil cg@2744: and:[(win := win topView) ~~ Screen current rootView cg@2744: and:[win ~~ top]] cg@2744: ) ifTrue:[ cg@2744: model rootItem:(ViewTreeItem buildViewsFrom:win) cg@2744: ] ifFalse:[ cg@2744: model rootItem:nil cg@2744: ] cg@2744: ] in:panel. cg@2744: cg@2744: sel multipleSelectOk:true. cg@2744: sel list:model listOfItems. cg@2744: sel model:model. cg@2744: sel useIndex:false. cg@2744: cg@2744: sel doubleClickAction:[:i| |el| cg@2744: el := model listOfItems at:i. cg@2744: el spec notNil ifTrue:[ el spec inspect ] ifFalse:[ el widget inspect ] cg@2744: ]. cg@2744: sel indicatorAction:[:i| (model listOfItems at:i) toggleExpand ]. cg@2744: cg@2744: model inputEventAction:[:anEvent| |item| cg@2744: anEvent isButtonEvent ifTrue:[ cg@2744: anEvent isButtonPressEvent ifTrue:[ cg@2744: model selectedItem:(model listOfItems detectItemRespondsToView:(anEvent view)). cg@2744: ] ifFalse:[ cg@2744: anEvent type == #'buttonMultiPress:x:y:' ifTrue:[ cg@2744: (item := model selectedItem) notNil ifTrue:[item widget inspect] cg@2744: ] cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: cg@2744: top openAndWait. cg@2744: [[top shown] whileTrue:[Delay waitForSeconds:0.5]. model rootItem:nil] forkAt:8 cg@2744: cg@2744: [exEnd] cg@2744: " cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing'! cg@2744: cg@2744: application:anApplication cg@2744: listOfItems application:anApplication. cg@2744: ! cg@2744: cg@2744: rootItem cg@2744: "get the rootItem the event viewer is established on cg@2744: " cg@2744: ^ listOfItems root cg@2744: ! cg@2744: cg@2744: rootItem:anItem cg@2744: "set the rootItem the event viewer is established on cg@2744: " cg@2744: |expanded| cg@2744: cg@2744: timedUpdateTask := nil. cg@2744: self deselect. cg@2744: cg@2744: lockSema critical:[ cg@2744: anItem notNil ifTrue:[ expanded := anItem isExpanded ] cg@2744: ifFalse:[ expanded := false ]. cg@2744: cg@2744: self value:nil. cg@2744: listOfItems root:anItem. cg@2744: cg@2744: anItem notNil ifTrue:[ cg@2744: timedUpdateTask := Process for:[ self timedUpdateTaskCycle ] priority:8. cg@2744: timedUpdateTask name:'Update'. cg@2744: timedUpdateTask resume. cg@2744: ]. cg@2744: ]. cg@2744: cg@2744: (expanded and:[anItem notNil]) ifTrue:[ cg@2744: anItem expand cg@2744: ]. cg@2744: ^ anItem cg@2744: ! cg@2744: cg@2744: rootView cg@2744: "get the top widget the event viewer is established on, a View cg@2744: " cg@2744: ^ listOfItems rootView cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing actions'! cg@2744: cg@2744: beforeSelectionChangedAction cg@2744: "none argument action which is called before cg@2744: the selection changed cg@2744: " cg@2744: ^ beforeSelectionChangedAction cg@2744: ! cg@2744: cg@2744: beforeSelectionChangedAction:aNoneArgBlock cg@2744: "none argument action which is called before cg@2744: the selection changed cg@2744: " cg@2744: beforeSelectionChangedAction := aNoneArgBlock. cg@2744: ! cg@2744: cg@2744: inputEventAction cg@2744: "called for each input event; the argument to the action is the WindowEvent cg@2744: " cg@2744: ^ inputEventAction cg@2744: ! cg@2744: cg@2744: inputEventAction:aOneArgActionTheEvent cg@2744: "called for each input event; the argument to the action is the WindowEvent cg@2744: " cg@2744: inputEventAction := aOneArgActionTheEvent. cg@2744: ! cg@2744: cg@2744: mappedViewAction cg@2744: "called for a new mapped view which can not be found cg@2744: in the current item list cg@2744: " cg@2744: ^ mappedViewAction cg@2744: ! cg@2744: cg@2744: mappedViewAction:aOneArgBlockTheMappedView cg@2744: "called for a new mapped view which can not be found cg@2744: in the current item list cg@2744: " cg@2744: mappedViewAction := aOneArgBlockTheMappedView cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing look'! cg@2744: cg@2744: iconAt:aKey ifNonePut:aNoneArgBlock cg@2744: |icon view| cg@2744: cg@2744: icon := icons at:aKey ifAbsent:nil. cg@2744: icon notNil ifTrue:[^ icon]. cg@2744: cg@2744: icon := aNoneArgBlock value. cg@2744: icon isNil ifTrue:[^ nil]. cg@2744: cg@2744: view := self rootView. cg@2744: view isNil ifTrue:[^ icon]. cg@2744: cg@2744: icon := icon copy onDevice:(view device). cg@2744: icon isImage ifTrue:[ cg@2744: icon clearMaskedPixels. cg@2744: ]. cg@2744: icons at:aKey put:icon. cg@2744: ^ icon cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'accessing visibility'! cg@2744: cg@2744: signalHiddenLevel cg@2744: "show the selection if signaled; increments hiddenLevel cg@2744: see: #waitHiddenLevel cg@2744: " cg@2744: (hiddenLevel := hiddenLevel - 1) < 1 ifTrue:[ cg@2744: hiddenLevel := 0. cg@2744: self invalidateSelection. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: waitHiddenLevel cg@2744: "hide the selection until signaled; increments hiddenLevel cg@2744: see: #signalHiddenLevel cg@2744: " cg@2744: self redrawUnselected:selection andLock:true cg@2744: ! cg@2744: cg@2744: withSelectionHiddenDo:aNoneArgumentBlock cg@2744: "apply block with selection hidden cg@2744: " cg@2744: cg@2744: [ self waitHiddenLevel. cg@2744: cg@2744: aNoneArgumentBlock value cg@2744: cg@2744: ] valueNowOrOnUnwindDo:[ cg@2744: self signalHiddenLevel. cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'aspects'! cg@2744: cg@2744: hasTargetWidgetChannel cg@2744: "answer the channel which is set to true if a target widget exists" cg@2744: cg@2744: ^ hasTargetWidgetChannel cg@2744: ! cg@2744: cg@2744: listOfItems cg@2744: "hiearchical list build from existing items" cg@2744: cg@2744: ^ listOfItems cg@2744: ! cg@2744: cg@2744: selectOnClickHolder cg@2744: "boolean holder, which indicates whether the selection will change on click cg@2744: " cg@2744: ^ selectOnClickHolder cg@2744: ! cg@2744: cg@2744: testModeChannel cg@2744: "answer a boolean channel which describes the behaviour how to process cg@2744: events on the target view. cg@2744: cg@2744: false: all input events are eaten and the selection is shown on the target view. cg@2744: true: no input events are eaten and no selection is shown on the target view." cg@2744: cg@2744: ^ testModeChannel cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'change & update'! cg@2744: cg@2744: targetWidgetChanged cg@2744: hasTargetWidgetChannel value:(self rootItem notNil). cg@2744: ! cg@2744: cg@2744: timedUpdateTaskCycle cg@2744: |view myTaskId| cg@2744: cg@2744: myTaskId := timedUpdateTask. cg@2744: cg@2744: listOfItems root notNil ifTrue:[ cg@2744: view := listOfItems root widget. cg@2744: ]. cg@2744: cg@2744: [ view notNil ] whileTrue:[ cg@2744: Delay waitForSeconds:0.5. cg@2744: cg@2744: (myTaskId == timedUpdateTask and:[view id notNil]) ifFalse:[ cg@2744: view := nil. cg@2744: ] ifTrue:[ cg@2744: (view sensor hasUserEvent:#updateChildren for:self) ifFalse:[ cg@2744: view sensor pushUserEvent:#updateChildren for:self. cg@2744: ]. cg@2744: ]. cg@2744: ]. cg@2744: timedUpdateTask == myTaskId ifTrue:[ cg@2744: timedUpdateTask := nil. cg@2744: listOfItems root:nil. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: update:something with:someArgument from:aModel cg@2744: cg@2744: aModel == testModeChannel ifTrue:[ cg@2744: (hiddenLevel == 0 and:[selection size > 0]) ifTrue:[ cg@2744: testModeChannel value ifTrue:[ cg@2744: self redrawUnselected:selection andLock:false checkTestMode:false. cg@2744: ] ifFalse:[ cg@2744: self invalidateSelection. cg@2744: ]. cg@2744: ]. cg@2744: ^ self cg@2744: ]. cg@2744: super update:something with:someArgument from:aModel. cg@2744: ! cg@2744: cg@2744: updateChildren cg@2744: |rootItem| cg@2744: cg@2744: rootItem := listOfItems root. cg@2744: rootItem isNil ifTrue:[^ self]. cg@2744: cg@2744: rootItem exists ifFalse:[ cg@2744: listOfItems root:nil. cg@2744: ] ifTrue:[ cg@2744: rootItem updateChildren. cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'event processing'! cg@2744: cg@2744: processEvent:anEvent cg@2744: "catch and process all WindowEvents for the rootComponent and its contained cg@2757: widgets; redraw selection in case of damage... cg@2757: return true, if the event was eaten" cg@2757: cg@2744: |evView item rootView testMode| cg@2744: cg@2744: evView := anEvent view. cg@2744: evView isNil ifTrue:[ cg@2757: (anEvent isMessageSendEvent not or:[anEvent receiver ~~ self]) ifTrue:[ cg@2744: ^ false cg@2744: ]. cg@2744: anEvent value. cg@2744: ^ true. cg@2744: ]. cg@2744: rootView := listOfItems rootView. cg@2744: rootView isNil ifTrue:[ ^ false ]. cg@2744: cg@2744: anEvent isConfigureEvent ifTrue:[ cg@2744: hiddenLevel == 0 ifTrue:[ cg@2744: self redrawUnselected:selection andLock:false. cg@2744: ]. cg@2744: ^ false cg@2744: ]. cg@2744: cg@2744: "/ check whether view is contained within the rootView cg@2744: (evView == rootView or:[evView isComponentOf:rootView]) ifFalse:[ cg@2744: ^ false cg@2744: ]. cg@2744: cg@2744: anEvent isInputEvent ifFalse:[ cg@2744: anEvent isDamage ifTrue:[ cg@2744: hiddenLevel == 0 ifTrue:[self invalidateSelection]. cg@2744: ^ false cg@2744: ]. cg@2744: cg@2744: anEvent isMapEvent ifTrue:[ cg@2744: mappedViewAction notNil ifTrue:[ cg@2744: item := listOfItems recursiveDetect:[:el| el widget == evView]. cg@2744: item isNil ifTrue:[ mappedViewAction value:evView ] cg@2744: ]. cg@2744: ^ false cg@2744: ]. cg@2744: cg@2744: anEvent type == #terminate ifTrue:[ cg@2744: item := listOfItems recursiveDetect:[:el| el widget == evView]. cg@2744: item notNil ifTrue:[ self processTerminateForItem:item ]. cg@2744: ^ false cg@2744: ]. cg@2744: ^ false cg@2744: ]. cg@2744: testMode := testModeChannel value. cg@2744: cg@2744: anEvent isFocusEvent ifTrue:[ cg@2744: evView == rootView ifTrue:[ cg@2744: self invalidateSelection cg@2744: ]. cg@2744: ^ testMode not. cg@2744: ]. cg@2744: anEvent isPointerEnterLeaveEvent ifTrue:[ ^ testMode not ]. cg@2744: cg@2744: testMode ifFalse:[ cg@2744: inputEventAction notNil ifTrue:[ inputEventAction value:anEvent ]. cg@2744: ] ifTrue:[ cg@2744: anEvent isButtonPressEvent ifTrue:[ cg@2744: selectOnClickHolder value ifTrue:[ cg@2744: self selectItem:(listOfItems detectItemRespondsToView:evView). cg@2744: ]. cg@2744: ] cg@2744: ]. cg@2744: cg@2744: (hiddenLevel ~~ 0 and:[anEvent isButtonReleaseEvent]) ifTrue:[ cg@2744: hiddenLevel := 1. cg@2744: self signalHiddenLevel. cg@2744: ]. cg@2744: cg@2744: ^ testMode not cg@2744: ! cg@2744: cg@2744: processTerminateForItem:anItem cg@2744: "received terminate for an item cg@2744: " cg@2744: anItem remove. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'initialization'! cg@2744: cg@2744: initialize cg@2744: "setup the default attributes cg@2744: " cg@2744: super initialize. cg@2744: cg@2744: hiddenLevel := 0. cg@2744: lockSema := RecursionLock new. cg@2744: listOfItems := ItemList new on:self. cg@2744: selectedSuperItems := #(). cg@2744: icons := IdentityDictionary new. cg@2744: cg@2744: hasTargetWidgetChannel := false asValue. cg@2744: selectOnClickHolder := true asValue. cg@2744: cg@2744: testModeChannel := false asValue. cg@2744: testModeChannel addDependent:self. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'private selection'! cg@2744: cg@2744: invalidateSelection cg@2744: "invalidate the current selection cg@2744: " cg@2744: |topView| cg@2744: cg@2744: testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode cg@2744: cg@2744: ( hiddenLevel == 0 cg@2744: and:[selection notNil cg@2744: and:[(topView := listOfItems rootView) notNil cg@2744: and:[topView shown]]] cg@2744: ) ifTrue:[ cg@2744: topView sensor pushUserEvent:#redrawSelection for:self withArguments:#() cg@2744: ] cg@2744: ! cg@2744: cg@2744: recursiveRepair:theDamages startIn:aView relativeTo:aRootView cg@2744: "repair all views and contained views, which intersects the damage. cg@2744: !!!! all damages repaired are removed from the list of damages !!!! cg@2744: " cg@2744: |color relOrg damage subViews repaired cg@2744: bwWidth "{ Class:SmallInteger }" cg@2744: x "{ Class:SmallInteger }" cg@2744: y "{ Class:SmallInteger }" cg@2744: w "{ Class:SmallInteger }" cg@2744: h "{ Class:SmallInteger }" cg@2744: relOrgX "{ Class:SmallInteger }" cg@2744: relOrgY "{ Class:SmallInteger }" cg@2744: width "{ Class:SmallInteger }" cg@2744: height "{ Class:SmallInteger }" cg@2744: size "{ Class:SmallInteger }" cg@2744: | cg@2744: (aView shown and:[theDamages notEmpty]) ifFalse:[ ^ self ]. cg@2744: cg@2744: subViews := aView subViews. cg@2744: cg@2744: subViews size ~~ 0 ifTrue:[ cg@2744: subViews reverseDo:[:v| self recursiveRepair:theDamages startIn:v relativeTo:aRootView ]. cg@2744: theDamages isEmpty ifTrue:[ ^ self ]. cg@2744: ]. cg@2744: cg@2744: relOrg := aView originRelativeTo:aRootView. cg@2744: bwWidth := aView borderWidth. cg@2744: size := theDamages size. cg@2744: cg@2744: "/ compute relative origin starting from border left@top cg@2744: relOrgX := relOrg x - bwWidth. cg@2744: relOrgY := relOrg y - bwWidth. cg@2744: width := aView width + bwWidth + bwWidth. cg@2744: height := aView height + bwWidth + bwWidth. cg@2744: cg@2744: size to:1 by:-1 do:[:anIndex| cg@2744: repaired := damage := theDamages at:anIndex. cg@2744: cg@2744: "/ compute the rectangle into the view cg@2744: y := damage top - relOrgY. cg@2744: x := damage left - relOrgX. cg@2744: w := damage width. cg@2744: h := damage height. cg@2744: cg@2744: x < 0 ifTrue:[ w := w + x. x := 0. repaired := nil ]. cg@2744: y < 0 ifTrue:[ h := h + y. y := 0. repaired := nil ]. cg@2744: x + w > width ifTrue:[ w := width - x. repaired := nil ]. cg@2744: y + h > height ifTrue:[ h := height - y. repaired := nil ]. cg@2744: cg@2744: (w > 0 and:[h > 0]) ifTrue:[ cg@2744: bwWidth ~~ 0 ifTrue:[ cg@2744: color isNil ifTrue:[ cg@2744: "/ must force redraw of border cg@2744: color := aView borderColor. cg@2744: aView borderColor:(Color colorId:1). cg@2744: aView borderColor:color. cg@2744: ]. cg@2744: w := w - bwWidth. cg@2744: h := h - bwWidth. cg@2744: cg@2744: (x := x - bwWidth) < 0 ifTrue:[w := w + x. x := 0]. cg@2744: (y := y - bwWidth) < 0 ifTrue:[h := h + y. y := 0]. cg@2744: cg@2744: h > 0 ifFalse:[w := 0]. "/ later testing on width only cg@2744: ]. cg@2744: cg@2744: w > 0 ifTrue:[ cg@2744: aView clearRectangleX:x y:y width:w height:h. cg@2744: aView exposeX:x y:y width:w height:h cg@2744: ]. cg@2744: repaired notNil ifTrue:[ theDamages removeFromIndex:anIndex toIndex:anIndex ]. cg@2744: ] cg@2744: ]. cg@2744: ! cg@2744: cg@2744: redrawSelection cg@2744: "redraw all items selected cg@2744: " cg@2744: |topView size| cg@2744: cg@2744: testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode cg@2744: cg@2744: ( hiddenLevel == 0 cg@2744: and:[(size := selection size) > 0 cg@2744: and:[(topView := listOfItems rootView) notNil cg@2744: and:[topView shown cg@2744: and:[(topView sensor hasEvent:#redrawSelection for:self) not]]]] cg@2744: ) ifFalse:[ cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: lockSema critical:[ cg@2744: |list| cg@2744: cg@2744: list := selection. cg@2744: cg@2744: list size > 0 ifTrue:[ cg@2744: topView paint:(Color black). cg@2744: topView clippedByChildren:false. cg@2744: cg@2744: list keysAndValuesReverseDo:[:anIndex :anItem| cg@2744: (anIndex == 1 and:[size > 1]) ifTrue:[ topView paint:(Color red) ]. cg@2744: cg@2744: anItem handlesDo:[:aRect :what| cg@2744: what isNil ifTrue:[topView displayRectangle:aRect] cg@2744: ifFalse:[topView fillRectangle:aRect] cg@2744: ] cg@2744: ]. cg@2744: topView clippedByChildren:true. cg@2744: ]. cg@2744: ]. cg@2744: ! cg@2744: cg@2744: redrawUnselected:aList andLock:doLock cg@2744: "redraw all items unselected; if doLock is true, the hiddenLevel cg@2744: is incremented and thus the select mechanism is locked. cg@2744: " cg@2744: self redrawUnselected:aList andLock:doLock checkTestMode:true. cg@2744: ! cg@2744: cg@2744: redrawUnselected:aList andLock:doLock checkTestMode:checkTestMode cg@2744: "redraw all items unselected; if doLock is true, the hiddenLevel cg@2744: is incremented and thus the select mechanism is locked. cg@2744: " cg@2744: |rootView damages subViews x y w h| cg@2744: cg@2744: doLock ifTrue:[ cg@2744: hiddenLevel := hiddenLevel + 1. cg@2744: hiddenLevel ~~ 1 ifTrue:[^ self]. cg@2744: ] ifFalse:[ cg@2744: hiddenLevel ~~ 0 ifTrue:[^ self]. cg@2744: ]. cg@2744: checkTestMode ifTrue:[ cg@2744: testModeChannel value ifTrue:[ ^ self ]. "/ test whether running testMode cg@2744: ]. cg@2744: cg@2744: ( aList size ~~ 0 cg@2744: and:[(rootView := listOfItems rootView) notNil cg@2744: and:[rootView shown]] cg@2744: ) ifFalse:[ cg@2744: ^ self cg@2744: ]. cg@2744: cg@2744: lockSema critical:[ cg@2744: damages := OrderedCollection new:(8 * aList size). cg@2744: cg@2744: aList do:[:item| cg@2744: item handlesDo:[:handle :what| cg@2744: damages reverseDo:[:el| cg@2744: (el intersects:handle) ifTrue:[ cg@2744: damages removeIdentical:el. cg@2744: cg@2744: handle left:(handle left min:el left) cg@2744: right:(handle right max:el right) cg@2744: top:(handle top min:el top) cg@2744: bottom:(handle bottom max:el bottom) cg@2744: ] cg@2744: ]. cg@2744: damages add:handle cg@2744: ] cg@2744: ]. cg@2744: cg@2744: damages do:[:el| cg@2744: x := el left. cg@2744: y := el top. cg@2744: w := el width. cg@2744: h := el height. cg@2744: cg@2744: rootView clearRectangleX:x y:y width:w height:h. cg@2744: rootView exposeX:x y:y width:w height:h. cg@2744: ]. cg@2744: cg@2744: (subViews := rootView subViews) notNil ifTrue:[ cg@2744: subViews reverseDo:[:v| self recursiveRepair:damages startIn:v relativeTo:rootView ]. cg@2744: ]. cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'queries'! cg@2744: cg@2744: isInTestMode cg@2744: "answer false, all input events are eaten and the selection is shown on the target view. cg@2744: answer true, no input events are eaten and no selection is shown on the target view." cg@2744: cg@2744: ^ testModeChannel value cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection accessing'! cg@2744: cg@2744: at:anIndex cg@2744: "returns the selected item at an index or nil cg@2744: " cg@2744: selection notNil ifTrue:[ cg@2744: ^ selection at:anIndex ifAbsent:nil cg@2744: ]. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: at:anIndex ifAbsent:aBlock cg@2744: "returns the selected item at an index or the result of the block cg@2744: " cg@2744: selection notNil ifTrue:[ cg@2744: ^ selection at:anIndex ifAbsent:aBlock cg@2744: ]. cg@2744: ^ aBlock value cg@2744: ! cg@2744: cg@2744: first cg@2744: "returns the first selected item or nil cg@2744: " cg@2744: ^ self at:1 cg@2744: ! cg@2744: cg@2744: last cg@2744: "returns the last selected item or nil cg@2744: " cg@2744: ^ selection notNil ifTrue:[selection last] ifFalse:[nil] cg@2744: ! cg@2744: cg@2744: selectedItem cg@2744: "returns the single selected item or nil (size ~~ 1 nil is returned) cg@2744: " cg@2744: ^ selection size == 1 ifTrue:[selection at:1] ifFalse:[nil] cg@2744: ! cg@2744: cg@2744: selectedSuperItems cg@2744: "returs the list of selected superItems; items selected cg@2744: but not contained in another selected item. cg@2744: " cg@2744: ^ selectedSuperItems cg@2744: ! cg@2744: cg@2744: size cg@2744: "returns the number of items selected cg@2744: " cg@2744: ^ selection size cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection adding & removing'! cg@2744: cg@2744: add:item cg@2744: "add an item to the current selection cg@2744: " cg@2744: |newSelect| cg@2744: cg@2744: item isNil ifTrue:[^ item]. cg@2744: cg@2744: lockSema critical:[ cg@2744: selection isNil ifTrue:[ cg@2744: newSelect := Array with:item. cg@2744: ] ifFalse:[ cg@2744: (self includes:item) ifFalse:[ cg@2744: newSelect := selection copyWith:item cg@2744: ] cg@2744: ]. cg@2744: cg@2744: newSelect size ~~ selection size ifTrue:[ cg@2744: item makeVisible. cg@2744: self value:newSelect cg@2744: ] cg@2744: ]. cg@2744: ^ item cg@2744: ! cg@2744: cg@2744: addAll:aCollectionOfItems cg@2744: "add a collection of items to the current selection cg@2744: " cg@2744: |newSelect| cg@2744: cg@2744: aCollectionOfItems size == 0 ifTrue:[ ^ aCollectionOfItems ]. cg@2744: cg@2744: lockSema critical:[ cg@2744: selection isNil ifTrue:[ cg@2744: newSelect := Array withAll:aCollectionOfItems. cg@2744: ] ifFalse:[ cg@2744: newSelect := OrderedCollection withAll:selection. cg@2744: cg@2744: aCollectionOfItems do:[:el| cg@2744: (selection includesIdentical:el) ifFalse:[newSelect add:el] cg@2744: ]. cg@2744: ]. cg@2744: self value:newSelect. cg@2744: ]. cg@2744: ^ aCollectionOfItems cg@2744: ! cg@2744: cg@2744: deselect cg@2744: "clear the selection cg@2744: " cg@2744: self value:nil. cg@2744: ! cg@2744: cg@2744: remove:item cg@2744: "remove the item from the current selection cg@2744: " cg@2744: |newSelect| cg@2744: cg@2744: item isNil ifTrue:[^ nil]. cg@2744: cg@2744: lockSema critical:[ cg@2744: (selection notNil and:[selection includesIdentical:item]) ifTrue:[ cg@2744: selection size == 1 ifTrue:[ newSelect := nil ] cg@2744: ifFalse:[ newSelect := selection copyWithout:item ]. cg@2744: cg@2744: self value:newSelect cg@2744: ]. cg@2744: ]. cg@2744: ^ item cg@2744: ! cg@2744: cg@2744: removeAll cg@2744: "clear the selection cg@2744: " cg@2744: self deselect. cg@2744: ! cg@2744: cg@2744: removeAll:loItems cg@2744: "remove all items of the collection from the current selection cg@2744: " cg@2744: |newSelect| cg@2744: cg@2744: selection isNil ifTrue:[ ^ loItems ]. cg@2744: loItems size == 0 ifTrue:[ ^ loItems ]. cg@2744: cg@2744: lockSema critical:[ cg@2744: selection notNil ifTrue:[ cg@2744: newSelect := selection select:[:el| (loItems includesIdentical:el) not ]. cg@2744: self value:newSelect. cg@2744: ] cg@2744: ]. cg@2744: ^ loItems cg@2744: ! cg@2744: cg@2744: selectAll cg@2744: "select all items cg@2744: " cg@2744: |root newSelection| cg@2744: cg@2744: root := listOfItems root. cg@2744: cg@2744: root isNil ifTrue:[ cg@2744: newSelection := nil cg@2744: ] ifFalse:[ cg@2744: newSelection := OrderedCollection new. cg@2744: root recursiveDo:[:el| newSelection add:el ]. cg@2744: ]. cg@2744: self value:newSelection. cg@2744: ! cg@2744: cg@2744: selectItem:anItem cg@2744: "set the current selection to the item cg@2744: " cg@2744: self value:anItem cg@2744: ! cg@2744: cg@2744: selectRootItem cg@2744: "set the current selection to the root item cg@2744: " cg@2744: self value:(self rootItem). cg@2744: ! cg@2744: cg@2744: selectedItem:anItem cg@2744: "set the current selection to the item cg@2744: " cg@2744: self selectItem:anItem. cg@2744: ! cg@2744: cg@2744: toggleSelectItem:anItem cg@2744: "toggle selection-state of the item; add or remove the item from the cg@2744: current selection. cg@2744: " cg@2744: anItem notNil ifTrue:[ cg@2744: (self includes:anItem) ifTrue:[self remove:anItem] cg@2744: ifFalse:[self add:anItem] cg@2744: ]. cg@2744: ^ anItem cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection enumerating'! cg@2744: cg@2744: collect:aBlock cg@2744: "for each element in the selection, evaluate the argument, aBlock cg@2744: and return a new collection with the results cg@2744: " cg@2744: |res| cg@2744: cg@2744: res := OrderedCollection new. cg@2744: self do:[:el| res add:(aBlock value:el)]. cg@2744: ^ res cg@2744: ! cg@2744: cg@2744: do:aOneArgBlock cg@2744: "evaluate the argument, aBlock for each item in the selection cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[^ nil]. cg@2744: ^ cashedSelection do:aOneArgBlock cg@2744: ! cg@2744: cg@2744: from:start do:aOneArgBlock cg@2744: "evaluate the argument, aBlock for the items starting at index start cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[^ nil]. cg@2744: ^ cashedSelection from:start do:aOneArgBlock cg@2744: ! cg@2744: cg@2744: from:start to:stop do:aOneArgBlock cg@2744: "evaluate the argument, aBlock for the items with index start to cg@2744: stop in the selection. cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[^ nil]. cg@2744: ^ cashedSelection from:start to:stop do:aOneArgBlock cg@2744: ! cg@2744: cg@2744: reverseDo:aOneArgBlock cg@2744: "evaluate the argument, aBlock for each item in the selection cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[^ nil]. cg@2744: ^ cashedSelection reverseDo:aOneArgBlock cg@2744: ! cg@2744: cg@2744: select:aBlock cg@2744: "return a new collection with all elements from the selection, for which cg@2744: the argument aBlock evaluates to true. cg@2744: " cg@2744: |res| cg@2744: cg@2744: res := OrderedCollection new. cg@2744: self do:[:el| (aBlock value:el) ifTrue:[res add:el] ]. cg@2744: ^ res cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection protocol'! cg@2744: cg@2744: changed:aParameter with:oldSelection cg@2744: "update the visibility staus of the current selection cg@2744: " cg@2744: |unselected rootView rootItem selSize| cg@2744: cg@2744: selSize := selection size. cg@2744: cg@2744: selSize == 0 ifTrue:[ cg@2744: selectedSuperItems := #(). cg@2744: ] ifFalse:[ cg@2744: selSize == 1 ifTrue:[ cg@2744: selectedSuperItems := Array with:(selection at:1). cg@2744: ] ifFalse:[ cg@2744: rootItem := listOfItems root. cg@2744: cg@2744: (selection includesIdentical:rootItem) ifTrue:[ cg@2744: selectedSuperItems := Array with:rootItem. cg@2744: ] ifFalse:[ cg@2744: selectedSuperItems := OrderedCollection new:selSize. cg@2744: cg@2744: selection do:[:anItem| cg@2744: anItem parentsDetect:[:el| selection includesIdentical:el ] cg@2744: ifNone:[ selectedSuperItems add:anItem ]. cg@2744: ]. cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: cg@2744: ( hiddenLevel == 0 cg@2744: and:[(rootView := listOfItems rootView) notNil cg@2744: and:[rootView shown]] cg@2744: ) ifTrue:[ cg@2744: selSize == 0 ifTrue:[ cg@2744: "/ must redraw the old selection unselected cg@2744: self redrawUnselected:oldSelection andLock:false cg@2744: ] ifFalse:[ cg@2744: self invalidateSelection. cg@2744: cg@2744: oldSelection size ~~ 0 ifTrue:[ cg@2744: "/ must redraw all elements no longer in the selection cg@2744: unselected := oldSelection select:[:el| (selection includesIdentical:el) not ]. cg@2744: self redrawUnselected:unselected andLock:false. cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: super changed:aParameter with:oldSelection. cg@2744: ! cg@2744: cg@2744: setValue:aNewSelection cg@2744: "set the selection without notifying cg@2744: " cg@2744: |newSelect idx| cg@2744: cg@2744: newSelect := nil. cg@2744: cg@2744: aNewSelection notNil ifTrue:[ cg@2744: lockSema critical:[ cg@2744: aNewSelection isCollection ifFalse:[ cg@2744: (selection size == 1 and:[selection first == aNewSelection]) ifTrue:[ cg@2744: newSelect := selection cg@2744: ] ifFalse:[ cg@2744: newSelect := Array with:aNewSelection. cg@2744: ] cg@2744: ] ifTrue:[ cg@2744: aNewSelection notEmpty ifTrue:[ cg@2744: aNewSelection size ~~ selection size ifTrue:[ cg@2744: newSelect := aNewSelection copy. cg@2744: ] ifFalse:[ cg@2744: idx := selection findFirst:[:el| (aNewSelection includesIdentical:el) not ]. cg@2744: cg@2744: idx ~~ 0 ifTrue:[newSelect := aNewSelection copy] cg@2744: ifFalse:[newSelect := selection ]. cg@2744: ] cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: ]. cg@2744: newSelect ~~ selection ifTrue:[ cg@2744: beforeSelectionChangedAction value. cg@2744: selection := newSelect. cg@2744: selection notNil ifTrue:[selection do:[:el| el makeVisible]] cg@2744: ]. cg@2744: ! cg@2744: cg@2744: triggerValue:aValue cg@2744: "set my value & send change notifications to my dependents. cg@2744: Send the change message even if the value didn't change. cg@2744: " cg@2744: |oldSelection| cg@2744: cg@2744: lockSema critical:[ cg@2744: oldSelection := selection. cg@2744: self setValue:aValue. cg@2744: self changed:#value with:oldSelection cg@2744: ] cg@2744: ! cg@2744: cg@2744: value cg@2744: "returns the current selection cg@2744: " cg@2744: ^ selection ? #() cg@2744: ! cg@2744: cg@2744: value:aValue cg@2744: "change the current selection and send change notifications to my cg@2744: dependents if it changed. cg@2744: " cg@2744: |oldSelection| cg@2744: cg@2744: lockSema critical:[ cg@2744: oldSelection := selection. cg@2744: self setValue:aValue. cg@2744: cg@2744: oldSelection == selection ifFalse:[ cg@2744: self changed:#value with:oldSelection cg@2744: ] cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection searching'! cg@2744: cg@2744: detect:aBlock cg@2744: "evaluate the argument, aBlock for each item in the selection until cg@2744: the block returns true; in this case return the element which caused cg@2744: the true evaluation. cg@2744: If none of the evaluations returns true, an error is raised cg@2744: " cg@2744: ^ self detect:aBlock ifNone:[self errorNotFound] cg@2744: ! cg@2744: cg@2744: detect:aBlock ifNone:exceptionBlock cg@2744: "evaluate the argument, aBlock for each item in the selection until the cg@2744: block returns true; in this case return the element which caused the cg@2744: true evaluation. cg@2744: If none of the evaluations returns true, the result of the evaluation cg@2744: of the exceptionBlock is returned cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[ ^ exceptionBlock value ]. cg@2744: ^ cashedSelection detect:aBlock ifNone:exceptionBlock cg@2744: ! cg@2744: cg@2744: detectLast:aBlock cg@2744: "evaluate the argument, aBlock for each item in the selection until cg@2744: the block returns true; in this case return the element which caused cg@2744: the true evaluation. The items are processed in reverse order. cg@2744: If none of the evaluations returns true, an error is raised cg@2744: " cg@2744: ^ self detectLast:aBlock ifNone:[self errorNotFound] cg@2744: ! cg@2744: cg@2744: detectLast:aBlock ifNone:exceptionBlock cg@2744: "evaluate the argument, aBlock for each item in the selection until cg@2744: the block returns true; in this case return the element which caused cg@2744: the true evaluation. The items are processed in reverse order. cg@2744: If none of the evaluations returns true, the result of the evaluation cg@2744: of the exceptionBlock is returned cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[ ^ exceptionBlock value ]. cg@2744: ^ cashedSelection detectLast:aBlock ifNone:exceptionBlock cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel methodsFor:'selection testing'! cg@2744: cg@2744: includes:anItem cg@2744: "returns true if the item is in the current selection cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[^ false]. cg@2744: ^ cashedSelection includesIdentical:anItem cg@2744: ! cg@2744: cg@2744: includesAll:aCollection cg@2744: "return true, if all items of the collection are included in the current selection cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: aCollection size ~~ 0 ifTrue:[ cg@2744: cashedSelection := selection. cg@2744: cashedSelection isNil ifTrue:[ ^ false ]. cg@2744: cg@2744: aCollection do:[:el| cg@2744: (cashedSelection includesIdentical:el) ifFalse:[^ false] cg@2744: ] cg@2744: ]. cg@2744: ^ true cg@2744: ! cg@2744: cg@2744: includesAny:aCollection cg@2744: "return true, if the any item of the collection is in the current selection cg@2744: " cg@2744: |cashedSelection| cg@2744: cg@2744: aCollection notNil ifTrue:[ cg@2744: cashedSelection := selection. cg@2744: cg@2744: cashedSelection notNil ifTrue:[ cg@2744: aCollection do:[:el| cg@2744: (cashedSelection includesIdentical:el) ifTrue:[^ true] cg@2744: ] cg@2744: ] cg@2744: ]. cg@2744: ^ false cg@2744: ! cg@2744: cg@2744: includesIdentical:anItem cg@2744: "returns true if the item is in the current selection cg@2744: " cg@2744: ^ self includes:anItem cg@2744: ! cg@2744: cg@2744: isEmpty cg@2744: "returns true if the current selection is empty cg@2744: " cg@2744: ^ selection size == 0 cg@2744: ! cg@2744: cg@2744: isSelected:anItem cg@2744: "returns true if the item is in the current selection cg@2744: " cg@2744: ^ self includes:anItem cg@2744: ! cg@2744: cg@2744: notEmpty cg@2744: "returns true if the current selection is not empty cg@2744: " cg@2744: ^ selection size ~~ 0 cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList class methodsFor:'documentation'! cg@2744: cg@2744: documentation cg@2744: " cg@2744: Kind of HierarchicalList class which contains all the visible cg@2744: ViewTreeItem's and the root, the anchor of the hierarchical list. cg@2744: cg@2744: [Instance variables:] cg@2744: treeModel all events are delegated to cg@2744: eventHook save and resore the pre/post -EventHook cg@2744: cg@2744: cg@2744: [author:] cg@2744: Claus Atzkern cg@2744: cg@2744: [see also:] cg@2744: HierarchicalList cg@2744: ViewTreeModel cg@2744: ViewTreeItem cg@2744: " cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'accessing'! cg@2744: cg@2744: root:theRoot cg@2744: "set the root item; delegate events to my treeModel cg@2744: " cg@2744: |rootView| cg@2744: cg@2744: theRoot == root ifTrue:[^ self]. cg@2744: cg@2744: rootView := self rootView. cg@2744: super root:theRoot. cg@2744: cg@2744: rootView notNil ifTrue:[ |wgrp| cg@2744: wgrp := rootView windowGroup. cg@2744: cg@2744: wgrp notNil ifTrue:[ cg@2744: wgrp removePreEventHook:treeModel. cg@2744: wgrp removePostEventHook:self. cg@2744: ]. cg@2744: ]. cg@2744: cg@2744: super root:theRoot. cg@2744: rootView := self rootView. cg@2744: cg@2744: rootView notNil ifTrue:[ cg@2744: "must setup a task because there might not exist a windowGroup at the moment cg@2744: " cg@2744: [ |wgrp| cg@2744: cg@2744: [rootView == self rootView] whileTrue:[ cg@2744: wgrp := rootView windowGroup. cg@2744: wgrp notNil ifTrue:[ cg@2744: rootView := nil. cg@2744: wgrp addPreEventHook:treeModel. cg@2744: wgrp addPostEventHook:self. cg@2744: ] ifFalse:[ cg@2744: Delay waitForMilliseconds:100. cg@2744: ]. cg@2744: ]. cg@2744: cg@2744: ] forkAt:(Processor userSchedulingPriority + 2). cg@2744: ]. cg@2744: treeModel notNil ifTrue:[ cg@2744: treeModel targetWidgetChanged. cg@2744: ]. cg@2744: cg@2744: ^ root. cg@2744: ! cg@2744: cg@2744: rootView cg@2744: "returns the widget assigned to the root or nil cg@2744: " cg@2744: ^ root notNil ifTrue:[root widget] ifFalse:[nil] cg@2744: ! cg@2744: cg@2744: treeModel cg@2744: "returne the treeModel, a ViewTreeModel cg@2744: " cg@2744: ^ treeModel cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'accessing look'! cg@2744: cg@2744: additionalLabelForItem:anItem cg@2744: "answer the additional lable for an item or nil" cg@2744: cg@2744: |applClass| cg@2744: cg@2744: showWidgetNames == true ifTrue:[ cg@2744: ^ '[', anItem widget name, ']' cg@2744: ]. cg@2744: cg@2744: anItem isApplicationClass ifTrue:[ cg@2744: applClass := anItem applicationClass. cg@2744: cg@2744: applClass notNil ifTrue:[ cg@2744: ^ ('[', applClass name, ']') cg@2744: ]. cg@2744: ]. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: showWidgetNames cg@2744: "answer true if the additional text is the widget name cg@2744: otherwise the name of the application" cg@2744: cg@2744: ^ showWidgetNames ? false cg@2744: ! cg@2744: cg@2744: showWidgetNames:aBoolean cg@2744: "set true if the additional text is the widget name cg@2744: otherwise the name of the application" cg@2744: cg@2744: self showWidgetNames == aBoolean ifFalse:[ cg@2744: showWidgetNames := aBoolean. cg@2744: cg@2744: root notNil ifTrue:[ cg@2744: root recursiveAdditionalNameBehaviourChanged. cg@2744: self changed. cg@2744: ]. cg@2744: ]. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'event processing'! cg@2744: cg@2744: processEvent:anEvent cg@2744: "post process event cg@2744: " cg@2744: ^ treeModel isInTestMode not cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'instance creation'! cg@2744: cg@2744: on:aModel cg@2744: "set the model, a ViewTreeModel cg@2744: " cg@2744: treeModel := aModel. cg@2744: showRoot := true. cg@2744: showWidgetNames := false. cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication::ViewTreeModel::ItemList methodsFor:'searching'! cg@2744: cg@2744: detectItemRespondsToView:aView cg@2744: "returns the bottom-most item which contains the view cg@2744: " cg@2744: |view item topView| cg@2744: cg@2744: root notNil ifTrue:[ cg@2744: view := aView. cg@2744: topView := root widget. cg@2744: cg@2744: [ view notNil ] whileTrue:[ cg@2744: topView == view ifTrue:[^ root]. cg@2744: item := root recursiveDetect:[:el| el widget == view ]. cg@2744: item notNil ifTrue:[^ item]. cg@2744: view := view superView cg@2744: ] cg@2744: ]. cg@2744: ^ nil cg@2744: ! cg@2744: cg@2744: recursiveDetect:aOneOrgBlock cg@2744: "recursive find the first child, for which evaluation cg@2744: of the block returns true; if none nil is returned cg@2744: " cg@2744: root notNil ifTrue:[ cg@2744: (aOneOrgBlock value:root) ifTrue:[ ^ root ]. cg@2744: ^ root recursiveDetect:aOneOrgBlock cg@2744: ]. cg@2744: ^ nil cg@2744: ! ! cg@2744: cg@2744: !ViewTreeInspectorApplication class methodsFor:'documentation'! cg@2744: cg@2744: version cg@2744: ^ '$Header$' cg@2744: ! cg@2744: cg@2744: version_CVS cg@2744: ^ '$Header$' cg@2744: ! ! cg@2744: cg@2744: ViewTreeInspectorApplication initialize! cg@2744: ViewTreeInspectorApplication::ViewTreeItem initialize!