platform-ui-home/workbench_design/Inside the workbench.html
Parent Directory
|
Revision Log
Revision 1.2 - (view) (download) (as text)
| 1 : | sxenos | 1.1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| 2 : | <html> | ||
| 3 : | <head> | ||
| 4 : | <meta content="text/html; charset=ISO-8859-1" | ||
| 5 : | http-equiv="content-type"> | ||
| 6 : | <title>Inside the Workbench: A guide to the workbench internals</title> | ||
| 7 : | </head> | ||
| 8 : | <body> | ||
| 9 : | <div style="text-align: center;"> | ||
| 10 : | <div style="text-align: left;"> | ||
| 11 : | <table border="0" cellpadding="2" cellspacing="5" width="100%"> | ||
| 12 : | <tbody> | ||
| 13 : | <tr> | ||
| 14 : | <td colspan="2" align="left" bgcolor="#0080c0" valign="top"><b><font | ||
| 15 : | color="#ffffff" face="Arial,Helvetica"> Platform UI Design Document<br> | ||
| 16 : | </font></b></td> | ||
| 17 : | </tr> | ||
| 18 : | </tbody> | ||
| 19 : | </table> | ||
| 20 : | </div> | ||
| 21 : | <span style="font-weight: bold;"><font size="+2"><span | ||
| 22 : | style="font-weight: bold;"><font size="+3"><br> | ||
| 23 : | Inside the | ||
| 24 : | Workbench<br> | ||
| 25 : | A guide to the workbench internals<br> | ||
| 26 : | <br> | ||
| 27 : | </font></span></font></span></div> | ||
| 28 : | <br> | ||
| 29 : | <div style="margin-left: 40px;"><span style="font-weight: bold;">Summary<br> | ||
| 30 : | </span>This document describes how the Eclipse 3.1 workbench works. It | ||
| 31 : | describes the infrastructure that makes views and editors work. The | ||
| 32 : | goal is to make the reader familiar with important classes in the | ||
| 33 : | workbench, and how they interact. It is assumed that the reader is | ||
| 34 : | already familiar with the workbench APIs, and with creating views, | ||
| 35 : | editors, action sets.<br> | ||
| 36 : | <br> | ||
| 37 : | <span style="font-weight: bold;">Stefan Xenos, IBM</span><br> | ||
| 38 : | sxenos | 1.2 | July 12, 2005<br> |
| 39 : | sxenos | 1.1 | <br> |
| 40 : | </div> | ||
| 41 : | <br> | ||
| 42 : | <hr style="width: 100%; height: 2px;"> | ||
| 43 : | <h1><a class="mozTocH1" name="mozTocId932753"></a>Table of Contents</h1> | ||
| 44 : | <ul id="mozToc"> | ||
| 45 : | <!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId932753">Table | ||
| 46 : | of Contents</a></li> | ||
| 47 : | <li><a href="#mozTocId777378">1.0 Introduction </a></li> | ||
| 48 : | <li><a href="#mozTocId611837">2.0 Inside a part </a> | ||
| 49 : | <ul> | ||
| 50 : | <li><a href="#mozTocId683987">2.1 Part Lifecycle </a></li> | ||
| 51 : | <li><a href="#mozTocId623821">2.2 Part Construction</a></li> | ||
| 52 : | </ul> | ||
| 53 : | </li> | ||
| 54 : | <li><a href="#mozTocId304467">3.0 Workbench Layout </a> | ||
| 55 : | <ul> | ||
| 56 : | <li><a href="#mozTocId913623">3.1 An example layout</a></li> | ||
| 57 : | <li><a href="#mozTocId994793">3.2 Zoom / Unzoom protocol </a></li> | ||
| 58 : | <li><a href="#mozTocId364295">3.3 Layout protocol </a></li> | ||
| 59 : | <li><a href="#mozTocId867109">3.4 PartStack: Communicating with | ||
| 60 : | the Presentation API </a></li> | ||
| 61 : | <li><a href="#mozTocId854140">3.5 PartSashContainer: The main | ||
| 62 : | workbench layout </a></li> | ||
| 63 : | <li><a href="#mozTocId370659">3.6 Drag / Drop</a></li> | ||
| 64 : | </ul> | ||
| 65 : | </li> | ||
| 66 : | <li><a href="#mozTocId438049">3.0 Action Bars</a> | ||
| 67 : | <ul> | ||
| 68 : | <li><a href="#mozTocId808539">3.1 Editor Action Bars </a></li> | ||
| 69 : | <li><a href="#mozTocId809219">3.2 Action Sets </a></li> | ||
| 70 : | <li><a href="#mozTocId846891">3.3 View Actions</a></li> | ||
| 71 : | </ul> | ||
| 72 : | </li> | ||
| 73 : | <li><a href="#mozTocId453994">4.0 General Conventions</a> | ||
| 74 : | <ul> | ||
| 75 : | <li><a href="#mozTocId451497">4.1 Objects must not be returned | ||
| 76 : | through API until they are fully initialized</a></li> | ||
| 77 : | <li><a href="#mozTocId959546">4.2 No method may open a modal | ||
| 78 : | dialog unless its JavaDoc says so</a></li> | ||
| 79 : | <li><a href="#mozTocId877708">4.3 Lazy creation should happen as | ||
| 80 : | late as possible</a></li> | ||
| 81 : | <li><a href="#mozTocId758931">4.4 getters should not modify the | ||
| 82 : | thing they are supposed to measure</a></li> | ||
| 83 : | </ul> | ||
| 84 : | </li> | ||
| 85 : | </ul> | ||
| 86 : | <div style="margin-left: 40px;"><span style="font-weight: bold;"></span></div> | ||
| 87 : | <h1><a class="mozTocH1" name="mozTocId777378"></a><span | ||
| 88 : | style="font-weight: bold;"></span><span style="font-weight: bold;">1.0 | ||
| 89 : | Introduction</span> | ||
| 90 : | <br> | ||
| 91 : | </h1> | ||
| 92 : | <span style="font-weight: bold;"></span> | ||
| 93 : | <br> | ||
| 94 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 95 : | 1.0.1: Ownership of views and editors<br> | ||
| 96 : | <br> | ||
| 97 : | </span></div> | ||
| 98 : | <div style="text-align: center;"><img alt="" | ||
| 99 : | src="workbench_high_level.PNG" style="width: 600px; height: 340px;"><br> | ||
| 100 : | </div> | ||
| 101 : | <br> | ||
| 102 : | Figure 1.0.1 shows how views and editors are owned by the workbench.<br> | ||
| 103 : | <br> | ||
| 104 : | The Workbench contains one or more WorkbenchWindows, each of which | ||
| 105 : | contain zero or more WorkbenchPages. The WorkbenchWindow supplies the | ||
| 106 : | trim widgets, and the WorkbenchPage supplies the window | ||
| 107 : | contents. In theory, a WorkbenchWindow can contain any number of pages, | ||
| 108 : | but in practice there is never more than 1 page in a window.<br> | ||
| 109 : | <br> | ||
| 110 : | Views and editors are owned by the page, through a ViewFactory and | ||
| 111 : | EditorManager respectively. EditorManager stores the list of editors | ||
| 112 : | and their shared | ||
| 113 : | resources, and ViewFactory stores a reference counted list of views. | ||
| 114 : | The workbench works in terms of EditorReferences and ViewReferences, | ||
| 115 : | and in this article the terms "editor" or "view" will refer to these | ||
| 116 : | classes specifically. In situations where the distinction between | ||
| 117 : | editors and views is not important, we will simply use the term "part". | ||
| 118 : | The implementation of the part (typically an IEditorPart or IViewPart) | ||
| 119 : | is created lazily when it is first needed. As shown in figure 1.0.2, a | ||
| 120 : | part reference exists for every tab but the implementation is only | ||
| 121 : | created the first time it becomes visible.<br> | ||
| 122 : | <br> | ||
| 123 : | The page owns a set of perspectives. Perspectives contain a layout and | ||
| 124 : | information about what action sets to enable. Although perspectives | ||
| 125 : | appear to contain views and the editor area, they only own a layout. | ||
| 126 : | The page itself maintains a reference count for how many perspectives | ||
| 127 : | are using each view, and has complete ownership of the parts and editor | ||
| 128 : | area.<br> | ||
| 129 : | <br> | ||
| 130 : | Not shown in figure 1 are the classes PerspectiveHelper and | ||
| 131 : | EditorAreaHelper. These classes exist largely for historic purposes, | ||
| 132 : | and in this article we will treat the former as though it were part of | ||
| 133 : | the Perspective class and the latter as part of the WorkbenchPage class.<br> | ||
| 134 : | <br> | ||
| 135 : | <br> | ||
| 136 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 137 : | 1.0.2: Workbench objects and what they look like<br> | ||
| 138 : | <br> | ||
| 139 : | </span></div> | ||
| 140 : | <div style="text-align: center;"><img alt="" src="what_you_see.PNG" | ||
| 141 : | style="width: 892px; height: 700px;"><br> | ||
| 142 : | </div> | ||
| 143 : | <br> | ||
| 144 : | <h1><a class="mozTocH2" name="mozTocId611837"></a>2.0 Inside a part<br> | ||
| 145 : | </h1> | ||
| 146 : | <div style="text-align: center;"><span style="font-weight: bold;"> | ||
| 147 : | Figure 2.0.1: Anatomy of a part</span><br> | ||
| 148 : | </div> | ||
| 149 : | <div style="text-align: center;"><img alt="" src="anatomy_of_a_part.PNG" | ||
| 150 : | style="width: 420px; height: 280px;"><br> | ||
| 151 : | </div> | ||
| 152 : | Internally, a part consists of several objects (figure 2.0.1). | ||
| 153 : | WorkbenchPartReference is the topmost representation of the part. | ||
| 154 : | Depending on where it is used, the part reference is often exposed as | ||
| 155 : | IWorkbenchPartReference, IViewReference, IEditorRefenece, or | ||
| 156 : | IPresentablePart, or PartPane. These are essentially different | ||
| 157 : | interfaces to the same object. The I*Reference interfaces are | ||
| 158 : | implemented directly by WorkbenchPartReference and its subclasses. | ||
| 159 : | IPresentablePart is a simple adapter that redirects its methods | ||
| 160 : | directly to the part. PartPane implements the LayoutPart protocol which | ||
| 161 : | is needed to insert the part into the workbench layout. PartPane also | ||
| 162 : | manages the SWT resources (such as a top-level control) that are needed | ||
| 163 : | to include the control in the workbench layout.<br> | ||
| 164 : | <br> | ||
| 165 : | The part implementation (the IEditorPart or IViewPart) is owned by the | ||
| 166 : | reference. When the | ||
| 167 : | implementation is created, it is given a PartSite. The PartSite (seen | ||
| 168 : | by client code as an IWorkbenchPartSite, IEditorSite, or IViewSite) | ||
| 169 : | allows the client code to communicate with the reference and manages | ||
| 170 : | services created for the implementation.<br> | ||
| 171 : | <br> | ||
| 172 : | WorkbenchPartReferences allocate SWT resources lazily as needed. | ||
| 173 : | Once created, the part reference must be explicitly disposed. Disposing | ||
| 174 : | the reference cleans up all of its resources (including the part | ||
| 175 : | implementation itself) and guarantees that the reference will never | ||
| 176 : | allocate additional resources. The workbench page disposes the part | ||
| 177 : | reference once it is certain that it will never need to use that part | ||
| 178 : | again. Unlike SWT controls, it is valid to continue using the reference | ||
| 179 : | after it has been disposed. A disposed part reference is unlikely to do | ||
| 180 : | anything interesting besides returning its name and cannot be used with | ||
| 181 : | any | ||
| 182 : | methods in the workbench page. Since it is hard (or impossible) for | ||
| 183 : | clients to track the lifecycle of the reference, they are permitted to | ||
| 184 : | continue using its public interface after disposal.<br> | ||
| 185 : | <br> | ||
| 186 : | <h2><a class="mozTocH3" name="mozTocId683987"></a>2.1 Part Lifecycle<br> | ||
| 187 : | </h2> | ||
| 188 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 189 : | 2.1.1: WorkbenchPartReference states<br> | ||
| 190 : | <br> | ||
| 191 : | </span></div> | ||
| 192 : | <div style="text-align: center;"><img alt="" src="part_states.PNG" | ||
| 193 : | style="width: 445px; height: 590px;"><br> | ||
| 194 : | </div> | ||
| 195 : | Figure 2.1.1 shows the part lifecycle as a state machine. The part | ||
| 196 : | reference stores its current state in the integer state field.<br> | ||
| 197 : | <br> | ||
| 198 : | Notes:<br> | ||
| 199 : | <ul> | ||
| 200 : | <li>The part is in a distinct state while it is in the process of | ||
| 201 : | creating the implementation. It cannot be recursively re-created or | ||
| 202 : | disposed while it is in this state.</li> | ||
| 203 : | <li>The part implementation cannot be recreated once the reference | ||
| 204 : | has been disposed.</li> | ||
| 205 : | <li>Parts cannot return to the lazy state once they have been | ||
| 206 : | created. This is a limitation in the 3.1 implementation, not a | ||
| 207 : | functional requirement.</li> | ||
| 208 : | <li>It is valid to continue using the public interface of | ||
| 209 : | WorkbenchPartReference once it has been disposed, however a disposed | ||
| 210 : | reference cannot be passed to methods in workbench page (since it is, | ||
| 211 : | by definition, no longer part of any page).</li> | ||
| 212 : | </ul> | ||
| 213 : | <h2><a class="mozTocH3" name="mozTocId623821"></a>2.2 Part Construction</h2> | ||
| 214 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 215 : | 2.2.1: Message sequence for creating a part<br> | ||
| 216 : | <br> | ||
| 217 : | </span></div> | ||
| 218 : | <div style="text-align: center;"><img alt="" src="part_creation_msc.PNG" | ||
| 219 : | style="width: 892px; height: 700px;"><br> | ||
| 220 : | </div> | ||
| 221 : | <br> | ||
| 222 : | Figure 2.2.1 shows the process for creating a part. The horizontal | ||
| 223 : | line separates the two phases of creating a part. First the part is | ||
| 224 : | added to the layout, and then a real implementation is attached. These | ||
| 225 : | are two distinct operations, and the part can exist as a tab in the | ||
| 226 : | page with no implementation for some time before it becomes visible. | ||
| 227 : | This diagram focuses on the interactions with the part reference, and | ||
| 228 : | skips the details of adding the part to the presentation and creating | ||
| 229 : | the part site.<br> | ||
| 230 : | <br> | ||
| 231 : | Author's note: there are situations where it would be useful to only | ||
| 232 : | add the part to the layout if it can be created successfully (this | ||
| 233 : | would be necessary to pass a PartInitException thrown in the | ||
| 234 : | implementation's init method up through IWorkbenchPage.openEditor). In | ||
| 235 : | these situations, it would be possible to merge both operations into | ||
| 236 : | one atomic operation by creating the part before adding it to the | ||
| 237 : | layout. It is unknown if this would create event ordering bugs in | ||
| 238 : | client code.<br> | ||
| 239 : | <br> | ||
| 240 : | <span style="font-weight: bold;"></span> | ||
| 241 : | <h1><a class="mozTocH2" name="mozTocId304467"></a>3.0 Workbench Layout<br> | ||
| 242 : | </h1> | ||
| 243 : | <br> | ||
| 244 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 245 : | 3.0.1: LayoutPart hierarchy</span><br> | ||
| 246 : | <img alt="" src="LayoutPart_hierarchy.PNG" | ||
| 247 : | style="width: 302px; height: 412px;"><br> | ||
| 248 : | </div> | ||
| 249 : | <br> | ||
| 250 : | The workbench layout provides supports arranging parts using drag & | ||
| 251 : | drop, resizing and detaching parts, fast views, etc. This section gives | ||
| 252 : | a quick overview of the layout mechanism.<br> | ||
| 253 : | <br> | ||
| 254 : | Anything in the workbench layout is a LayoutPart. A LayoutPart manages | ||
| 255 : | a set of widgets in a rectangular region of the screen, can contain or | ||
| 256 : | arrange other layout parts, returns size constraints, responds to drag | ||
| 257 : | events, etc. To this extent, a LayoutPart is very similar to a custom | ||
| 258 : | SWT Control. However, LayoutPart differs from Control in several | ||
| 259 : | important ways.<br> | ||
| 260 : | <ul> | ||
| 261 : | <li>The LayoutPart hierarchy is not the same as the widget hierarchy. | ||
| 262 : | Even though one LayoutPart may contain another, their widgets may be | ||
| 263 : | peers. This allows drag and drop to work on platforms where SWT doesn't | ||
| 264 : | support reparenting, since a LayoutPart can be reparented without | ||
| 265 : | reparenting its widgets.<br> | ||
| 266 : | </li> | ||
| 267 : | <li>LayoutParts mainly perform layout-related tasks, unlike Controls | ||
| 268 : | which also supply behavior and appearance. The behavior of a LayoutPart | ||
| 269 : | is supplied by the widgets it arranges.<br> | ||
| 270 : | </li> | ||
| 271 : | <li>LayoutParts know about higher-level concepts like zoom, and can | ||
| 272 : | specify constraints about their own size.<br> | ||
| 273 : | </li> | ||
| 274 : | </ul> | ||
| 275 : | Figure 3.0.1 shows the LayoutPart hierarchy. Notice the symmetry | ||
| 276 : | between the View* classes and the Editor* classes. These classes exist | ||
| 277 : | largely for historical reasons, and it should be possible to move all | ||
| 278 : | of the functionality into the Part* base classes or other objects in | ||
| 279 : | the system. Since all of the interesting behavior comes from the Part* | ||
| 280 : | classes, the remainder of this section will focus on them without | ||
| 281 : | describing the minor differences between views and editors.<br> | ||
| 282 : | <br> | ||
| 283 : | PartSashContainer arranges a set of child parts separated by a bunch of | ||
| 284 : | sashes. This is the object that implements the most visible aspects of | ||
| 285 : | the workbench layout. It arranges rectangular regions separated by | ||
| 286 : | sashes, and allows new regions to be created by splitting old ones. It | ||
| 287 : | also supports the size constraints that make minimized views possible, | ||
| 288 : | and determines what it means for one of these regions to be maximized. | ||
| 289 : | Typically, a PartSashContainer contains a bunch of PartStacks, although | ||
| 290 : | it is also possible for it to contain another PartSashContainer. The | ||
| 291 : | latter case occurs since the editor area and the perspective both use a | ||
| 292 : | PartSashContainer for their layout and one is embedded inside the | ||
| 293 : | other. PartSashContainer owns its stacks but does not own an embedded | ||
| 294 : | PartSashContainer. In a workbench window, there is one | ||
| 295 : | PartSashContainer for each perspective and one for the editor area | ||
| 296 : | itself.<br> | ||
| 297 : | <br> | ||
| 298 : | PartStack arranges a stack of PartPanes. PartStack allows the | ||
| 299 : | presentation API to participate in the workbench layout. The code for | ||
| 300 : | creating the tabs and arranging parts is supplied by the active | ||
| 301 : | presentation.<br> | ||
| 302 : | <br> | ||
| 303 : | PartPane allows views and editors to participate in the workbench | ||
| 304 : | layout. Although PartPanes are arranged by PartStacks they belong to | ||
| 305 : | part reference, not the stack. The same PartPane can exist in more than | ||
| 306 : | one PartStack at a time if that part appears in more that one | ||
| 307 : | perspective.<span style="font-weight: bold;"><br> | ||
| 308 : | <br> | ||
| 309 : | </span> | ||
| 310 : | <h2><a class="mozTocH3" name="mozTocId913623"></a>3.1 An example layout</h2> | ||
| 311 : | LayoutParts are best explained through example. Imagine a | ||
| 312 : | WorkbenchWindow that contains custom Java and Java Browsing | ||
| 313 : | perspectives that look like figure 3.1.1 and figure 3.1.2 | ||
| 314 : | respectively.<br> | ||
| 315 : | <br> | ||
| 316 : | <br> | ||
| 317 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 318 : | 3.1.1: Example Java Perspective</span><br> | ||
| 319 : | <img alt="" src="perspective1.PNG" style="width: 571px; height: 495px;"><br> | ||
| 320 : | <br> | ||
| 321 : | <span style="font-weight: bold;">Figure 3.1.2: Example Java Browsing | ||
| 322 : | perspective</span><br> | ||
| 323 : | <img alt="" src="perspective2.PNG" style="width: 571px; height: 495px;"><br> | ||
| 324 : | </div> | ||
| 325 : | <br> | ||
| 326 : | Assume that the window resembles Figure 3.1.1. In this case, the Java | ||
| 327 : | perspective is active, the Java Browsing perspective is hidden, and the | ||
| 328 : | objects are connected as shown in figure 3.1.3:<br> | ||
| 329 : | <br> | ||
| 330 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 331 : | 3.1.3: LayoutPart instances when two perspectives are open</span><br> | ||
| 332 : | <img alt="" src="perspective1_2_instances.PNG" | ||
| 333 : | style="width: 555px; height: 670px;"><br> | ||
| 334 : | <div style="text-align: left;"><br> | ||
| 335 : | </div> | ||
| 336 : | </div> | ||
| 337 : | <br> | ||
| 338 : | sxenos | 1.2 | <br> |
| 339 : | All LayoutParts have a container pointer that points to the object that | ||
| 340 : | is currently managing their position. Since the same LayoutPart | ||
| 341 : | instance may exist in more than one perspective at once, this pointer | ||
| 342 : | points to the part's container in the currently-active perspective. In | ||
| 343 : | the case of the projects view, above, the part is not in the current | ||
| 344 : | perspective so its container pointer is null. When another | ||
| 345 : | perspective becomes active, all the container pointers move to the new | ||
| 346 : | perspective. For historical reasons, this is accomplished by setting | ||
| 347 : | and | ||
| 348 : | clearing the contianer pointer when the container becomes visible or | ||
| 349 : | invisible. This works since only one perspective is visible at a time, | ||
| 350 : | but it also means that perspectives cannot be manipulated when they are | ||
| 351 : | invisible.<br> | ||
| 352 : | sxenos | 1.1 | <br> |
| 353 : | The diagram shows the internal objects that make up the only editor. | ||
| 354 : | Although this detail has been omitted for the views, they would look | ||
| 355 : | similar. Each view's PartPane is owned by a part reference which may | ||
| 356 : | sxenos | 1.2 | have an associated part implementation.<br> |
| 357 : | sxenos | 1.1 | <br> |
| 358 : | <h2><a class="mozTocH3" name="mozTocId994793"></a>3.2 Zoom / Unzoom | ||
| 359 : | protocol<br> | ||
| 360 : | </h2> | ||
| 361 : | The notion of "zoom" is defined locally between a part and its | ||
| 362 : | immediate container. Zoom changes are triggered bottom-up. A part asks | ||
| 363 : | its parent to "zoom me", and the parent either does something with the | ||
| 364 : | request or forwards the request up to its parent. Each container | ||
| 365 : | determines what it means for a child to be zoomed. Once a part's zoom | ||
| 366 : | state changes, its parent notifies it by calling setZoomed. The part | ||
| 367 : | may in turn zoom or unzoom one or more of its children.<br> | ||
| 368 : | <br> | ||
| 369 : | Anything that can contain LayoutParts must implement the following | ||
| 370 : | methods, to support zooming:<span style="font-family: monospace;"><br> | ||
| 371 : | <br> | ||
| 372 : | </span><code> /**<br> | ||
| 373 : | * Called by child parts to request a zoom in, | ||
| 374 : | given an immediate child <br> | ||
| 375 : | * <br> | ||
| 376 : | * @param toZoom part to zoom in on<br> | ||
| 377 : | */<br> | ||
| 378 : | public void childRequestZoomIn(LayoutPart toZoom);<br> | ||
| 379 : | <br> | ||
| 380 : | /**<br> | ||
| 381 : | * Called by child parts to request a zoom out<br> | ||
| 382 : | */<br> | ||
| 383 : | public void childRequestZoomOut();<br> | ||
| 384 : | <br> | ||
| 385 : | /**<br> | ||
| 386 : | * Returns true iff the given child is obscured | ||
| 387 : | due to the fact that the container is zoomed into<br> | ||
| 388 : | * another part. <br> | ||
| 389 : | * <br> | ||
| 390 : | * @param toTest part to test<br> | ||
| 391 : | * @return true iff the part is currently | ||
| 392 : | obscured <br> | ||
| 393 : | */<br> | ||
| 394 : | public boolean childObscuredByZoom(LayoutPart | ||
| 395 : | toTest);<br> | ||
| 396 : | <br> | ||
| 397 : | /**<br> | ||
| 398 : | * Returns true iff we are zoomed into the | ||
| 399 : | given part, given an immediate child of this container.<br> | ||
| 400 : | * <br> | ||
| 401 : | * @param toTest part to test<br> | ||
| 402 : | * @return true iff this contianer is currently | ||
| 403 : | zooming in on the given part<br> | ||
| 404 : | */<br> | ||
| 405 : | public boolean childIsZoomed(LayoutPart toTest);<br> | ||
| 406 : | </code><br> | ||
| 407 : | Consider again Figure 3.1.1. If we were to double-click on the java | ||
| 408 : | editor to zoom it, the LayoutParts would send messages to one another | ||
| 409 : | in the following sequence. (In this diagram, each cell represents a | ||
| 410 : | method call. Each column is an object. The reciever's column shows the | ||
| 411 : | method name and the caller contains an arrow. Rows are in ascending | ||
| 412 : | order of time.)<br> | ||
| 413 : | <br> | ||
| 414 : | <table style="width: 100%; text-align: left;" border="1" cellpadding="2" | ||
| 415 : | cellspacing="2"> | ||
| 416 : | <tbody> | ||
| 417 : | <tr> | ||
| 418 : | <td style="vertical-align: top; font-weight: bold;">Java Editor | ||
| 419 : | (PartPane)<br> | ||
| 420 : | </td> | ||
| 421 : | <td style="vertical-align: top; font-weight: bold;">PartStack<br> | ||
| 422 : | </td> | ||
| 423 : | <td style="vertical-align: top; font-weight: bold;">editor area | ||
| 424 : | (EditorSashContainer)<br> | ||
| 425 : | </td> | ||
| 426 : | <td style="vertical-align: top; font-weight: bold;">ViewSashContainer<br> | ||
| 427 : | </td> | ||
| 428 : | </tr> | ||
| 429 : | <tr> | ||
| 430 : | <td style="vertical-align: top;">requestZoomIn<br> | ||
| 431 : | </td> | ||
| 432 : | <td style="vertical-align: top;"><br> | ||
| 433 : | </td> | ||
| 434 : | <td style="vertical-align: top;"><br> | ||
| 435 : | </td> | ||
| 436 : | <td style="vertical-align: top;"><br> | ||
| 437 : | </td> | ||
| 438 : | </tr> | ||
| 439 : | <tr> | ||
| 440 : | <td style="vertical-align: top;"><img alt="" src="right_arrow.PNG" | ||
| 441 : | style="width: 42px; height: 17px;"><br> | ||
| 442 : | </td> | ||
| 443 : | <td style="vertical-align: top;">childRequestZoomIn(java editor)<br> | ||
| 444 : | </td> | ||
| 445 : | <td style="vertical-align: top;"><br> | ||
| 446 : | </td> | ||
| 447 : | <td style="vertical-align: top;"><br> | ||
| 448 : | </td> | ||
| 449 : | </tr> | ||
| 450 : | <tr> | ||
| 451 : | <td style="vertical-align: top;"><br> | ||
| 452 : | </td> | ||
| 453 : | <td style="vertical-align: top;"><img alt="" src="right_arrow.PNG" | ||
| 454 : | style="width: 42px; height: 17px;"><br> | ||
| 455 : | </td> | ||
| 456 : | <td style="vertical-align: top;">childRequestZoomIn(java editor's | ||
| 457 : | part stack)<br> | ||
| 458 : | </td> | ||
| 459 : | <td style="vertical-align: top;"><br> | ||
| 460 : | </td> | ||
| 461 : | </tr> | ||
| 462 : | <tr> | ||
| 463 : | <td style="vertical-align: top;"><br> | ||
| 464 : | </td> | ||
| 465 : | <td style="vertical-align: top;"><br> | ||
| 466 : | </td> | ||
| 467 : | <td style="vertical-align: top;">if there were other editor | ||
| 468 : | stacks in the layout, we would call setVisible(false) on them here</td> | ||
| 469 : | <td style="vertical-align: top;"><br> | ||
| 470 : | </td> | ||
| 471 : | </tr> | ||
| 472 : | <tr> | ||
| 473 : | <td style="vertical-align: top;"><br> | ||
| 474 : | </td> | ||
| 475 : | <td style="vertical-align: top;"><br> | ||
| 476 : | </td> | ||
| 477 : | <td style="vertical-align: top;">remember the partStack as the | ||
| 478 : | zoomed part<br> | ||
| 479 : | </td> | ||
| 480 : | <td style="vertical-align: top;"><br> | ||
| 481 : | </td> | ||
| 482 : | </tr> | ||
| 483 : | <tr> | ||
| 484 : | <td style="vertical-align: top;"><br> | ||
| 485 : | </td> | ||
| 486 : | <td style="vertical-align: top;">setZoomed(true)<br> | ||
| 487 : | </td> | ||
| 488 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 489 : | style="width: 42px; height: 17px;"><br> | ||
| 490 : | </td> | ||
| 491 : | <td style="vertical-align: top;"><br> | ||
| 492 : | </td> | ||
| 493 : | </tr> | ||
| 494 : | <tr> | ||
| 495 : | <td style="vertical-align: top;">setZoomed(true)<br> | ||
| 496 : | </td> | ||
| 497 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 498 : | style="width: 42px; height: 17px;"><br> | ||
| 499 : | </td> | ||
| 500 : | <td style="vertical-align: top;"><br> | ||
| 501 : | </td> | ||
| 502 : | <td style="vertical-align: top;"><br> | ||
| 503 : | </td> | ||
| 504 : | </tr> | ||
| 505 : | <tr> | ||
| 506 : | <td style="vertical-align: top;"><br> | ||
| 507 : | </td> | ||
| 508 : | <td style="vertical-align: top;"><br> | ||
| 509 : | </td> | ||
| 510 : | <td style="vertical-align: top;"><img alt="" src="right_arrow.PNG" | ||
| 511 : | style="width: 42px; height: 17px;"><br> | ||
| 512 : | </td> | ||
| 513 : | <td style="vertical-align: top;">childRequestZoomIn(editor area)<br> | ||
| 514 : | </td> | ||
| 515 : | </tr> | ||
| 516 : | <tr> | ||
| 517 : | <td style="vertical-align: top;"><br> | ||
| 518 : | </td> | ||
| 519 : | <td style="vertical-align: top;"><br> | ||
| 520 : | </td> | ||
| 521 : | <td style="vertical-align: top;"><br> | ||
| 522 : | </td> | ||
| 523 : | <td style="vertical-align: top;">call setVisible(false) on all | ||
| 524 : | PartStacks for views in the perspective<br> | ||
| 525 : | </td> | ||
| 526 : | </tr> | ||
| 527 : | <tr> | ||
| 528 : | <td style="vertical-align: top;"><br> | ||
| 529 : | </td> | ||
| 530 : | <td style="vertical-align: top;"><br> | ||
| 531 : | </td> | ||
| 532 : | <td style="vertical-align: top;"><br> | ||
| 533 : | </td> | ||
| 534 : | <td style="vertical-align: top;">remember the editor area as the | ||
| 535 : | zoomed part<br> | ||
| 536 : | </td> | ||
| 537 : | </tr> | ||
| 538 : | <tr> | ||
| 539 : | <td style="vertical-align: top;"><br> | ||
| 540 : | </td> | ||
| 541 : | <td style="vertical-align: top;"><br> | ||
| 542 : | </td> | ||
| 543 : | <td style="vertical-align: top;">setZoomed(true)<br> | ||
| 544 : | </td> | ||
| 545 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 546 : | style="width: 42px; height: 17px;"></td> | ||
| 547 : | </tr> | ||
| 548 : | <tr> | ||
| 549 : | <td style="vertical-align: top;"><br> | ||
| 550 : | </td> | ||
| 551 : | <td style="vertical-align: top;"><br> | ||
| 552 : | </td> | ||
| 553 : | <td style="vertical-align: top;"><br> | ||
| 554 : | </td> | ||
| 555 : | <td style="vertical-align: top;">trigger a layout<br> | ||
| 556 : | </td> | ||
| 557 : | </tr> | ||
| 558 : | <tr> | ||
| 559 : | <td style="vertical-align: top;"><br> | ||
| 560 : | </td> | ||
| 561 : | <td style="vertical-align: top;"><br> | ||
| 562 : | </td> | ||
| 563 : | <td style="vertical-align: top;">setBounds(zoomed bounds)<br> | ||
| 564 : | </td> | ||
| 565 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 566 : | style="width: 42px; height: 17px;"></td> | ||
| 567 : | </tr> | ||
| 568 : | <tr> | ||
| 569 : | <td style="vertical-align: top;"><br> | ||
| 570 : | </td> | ||
| 571 : | <td style="vertical-align: top;">setBounds(zoomed bounds)</td> | ||
| 572 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 573 : | style="width: 42px; height: 17px;"></td> | ||
| 574 : | <td style="vertical-align: top;"><br> | ||
| 575 : | </td> | ||
| 576 : | </tr> | ||
| 577 : | <tr> | ||
| 578 : | <td style="vertical-align: top;">setBounds(zoomed bounds)</td> | ||
| 579 : | <td style="vertical-align: top;"><img alt="" src="left_arrow.PNG" | ||
| 580 : | style="width: 42px; height: 17px;"></td> | ||
| 581 : | <td style="vertical-align: top;"><br> | ||
| 582 : | </td> | ||
| 583 : | <td style="vertical-align: top;"><br> | ||
| 584 : | </td> | ||
| 585 : | </tr> | ||
| 586 : | <tr> | ||
| 587 : | <td style="vertical-align: top;"><br> | ||
| 588 : | </td> | ||
| 589 : | <td style="vertical-align: top;"><br> | ||
| 590 : | </td> | ||
| 591 : | <td style="vertical-align: top;">trigger a layout (nothing to do)<br> | ||
| 592 : | </td> | ||
| 593 : | <td style="vertical-align: top;"><br> | ||
| 594 : | </td> | ||
| 595 : | </tr> | ||
| 596 : | </tbody> | ||
| 597 : | </table> | ||
| 598 : | <br> | ||
| 599 : | <h2><a class="mozTocH3" name="mozTocId364295"></a>3.3 Layout protocol<br> | ||
| 600 : | </h2> | ||
| 601 : | Every LayoutPart can specify constraints on their size. Parts specify | ||
| 602 : | constraints by implementing the ISizeProvider interface. ISizeProvider | ||
| 603 : | serves a similar function as the computeSize method on an SWT control, | ||
| 604 : | in that the parent layout uses it to consult with the part when | ||
| 605 : | computing the part's size. ISizeProvider can provide a variety of | ||
| 606 : | constraints:<br> | ||
| 607 : | <br> | ||
| 608 : | <table style="width: 100%; text-align: left;" border="1" cellpadding="2" | ||
| 609 : | cellspacing="2"> | ||
| 610 : | <tbody> | ||
| 611 : | <tr> | ||
| 612 : | <td style="vertical-align: top; font-weight: bold;">Constraint | ||
| 613 : | type<br> | ||
| 614 : | </td> | ||
| 615 : | <td style="vertical-align: top; font-weight: bold;">Meaning<br> | ||
| 616 : | </td> | ||
| 617 : | </tr> | ||
| 618 : | <tr> | ||
| 619 : | <td style="vertical-align: top;">Minimum size<br> | ||
| 620 : | </td> | ||
| 621 : | <td style="vertical-align: top;">Given the available space along | ||
| 622 : | one dimension, the part returns the minimum size that it can be | ||
| 623 : | compressed to along the other dimension. For example, a stack would | ||
| 624 : | typically set its minimum size to be large enough to fit its tabs. The | ||
| 625 : | information about available perpendicular space could allow a stack to | ||
| 626 : | have wrapping tabs and still reserve enough vertical space for the tabs | ||
| 627 : | once they are wrapped to fill the available horizontal space.<br> | ||
| 628 : | </td> | ||
| 629 : | </tr> | ||
| 630 : | <tr> | ||
| 631 : | <td style="vertical-align: top;">Maximum size<br> | ||
| 632 : | </td> | ||
| 633 : | <td style="vertical-align: top;">Given the available space along | ||
| 634 : | one dimension, the part returns the maximum size that it can utilize | ||
| 635 : | along the other dimension. For example, minimized stacks are | ||
| 636 : | implemented by setting their maximum size to the minimized size. | ||
| 637 : | Non-minimized stacks typically have an unbounded maximum size.<br> | ||
| 638 : | </td> | ||
| 639 : | </tr> | ||
| 640 : | <tr> | ||
| 641 : | <td style="vertical-align: top;">Preferred size<br> | ||
| 642 : | </td> | ||
| 643 : | <td style="vertical-align: top;">Given the availble space along | ||
| 644 : | one dimension and a preferred size, this returns the size closest to | ||
| 645 : | the preferred size at which the part would look best. Parts can use | ||
| 646 : | this to quantize their size. For example, a part can ensure that its | ||
| 647 : | size is always chosen such that it can be completely filled with | ||
| 648 : | toolbar icons leaving no space left over.<br> | ||
| 649 : | </td> | ||
| 650 : | </tr> | ||
| 651 : | </tbody> | ||
| 652 : | </table> | ||
| 653 : | <br> | ||
| 654 : | Although there are three kinds of constraints, they are all returned | ||
| 655 : | using a single method. See the JavaDoc on ISizeProvider for more | ||
| 656 : | information.<br> | ||
| 657 : | <br> | ||
| 658 : | Whenever a size constraint changes, the part notifies its contianer by | ||
| 659 : | calling resizeChild(part). This tells the container to respond to the | ||
| 660 : | new constraints, and to resize the child if necessary (author's note: | ||
| 661 : | if this is ever exposed as API, it would be better to separate the | ||
| 662 : | concerns of notifying the parent of changes and triggering a layout. In | ||
| 663 : | general, it may be possible for more than one part to change without | ||
| 664 : | requiring a layout between each change).<br> | ||
| 665 : | <br> | ||
| 666 : | <h2><a class="mozTocH3" name="mozTocId867109"></a>3.4 PartStack: | ||
| 667 : | Communicating with the Presentation API<br> | ||
| 668 : | </h2> | ||
| 669 : | PartStack allows presentation to participate in the workbench layout. | ||
| 670 : | As shown in Figure 3.4.1, it wraps a single instance of | ||
| 671 : | StackPresentation, and allows it the presentation to manipulate parts | ||
| 672 : | by converting each visible part into an IPresentablePart. The part | ||
| 673 : | stack outlives the StackPresentation. Whenever the part stack needs | ||
| 674 : | widgets, it creates the StackPresentation. If the widgets are no longer | ||
| 675 : | needed, it disposes the StackPresentation and remembers its persisted | ||
| 676 : | form. Whenever the PartStack persists its StackPresenation, it | ||
| 677 : | remembers the presentation ID so that it will not try to restore one | ||
| 678 : | StackPresentation from state saved by an incompatible presentation.<br> | ||
| 679 : | <br> | ||
| 680 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 681 : | 3.4.1: Anatomy of PartStack</span><br> | ||
| 682 : | <img alt="" src="PartStack.PNG" style="width: 430px; height: 225px;"><br> | ||
| 683 : | <div style="text-align: left;"><br> | ||
| 684 : | Author's note: it would be useful to update this document with a state | ||
| 685 : | diagram for PartStack, and message sequence charts for initializaiton | ||
| 686 : | and part activation.<br> | ||
| 687 : | <br> | ||
| 688 : | </div> | ||
| 689 : | </div> | ||
| 690 : | <h2><a class="mozTocH3" name="mozTocId854140"></a>3.5 | ||
| 691 : | PartSashContainer: The main workbench layout <br> | ||
| 692 : | </h2> | ||
| 693 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 694 : | 3.5.1: PartSashContainer</span><br> | ||
| 695 : | <img alt="" src="PartSashContainer.PNG" | ||
| 696 : | style="width: 428px; height: 305px;"><br> | ||
| 697 : | </div> | ||
| 698 : | <br> | ||
| 699 : | PartSashContainer implements the main layout for a perspective and the | ||
| 700 : | editor area. As shown in figure 3.5.1, PartSashContainer contains a | ||
| 701 : | list of children, a (possibly null) zoomed part, and a LayoutTree that | ||
| 702 : | manages the actual layout. <br> | ||
| 703 : | <br> | ||
| 704 : | LayoutTree is a binary tree (technically, a KD tree). Each internal | ||
| 705 : | node is an instance of LayoutTreeNode. It contains a draggable sash | ||
| 706 : | (LayoutPartSash) that divides its area among its left and right | ||
| 707 : | children. LayoutTreeNodes can be horizontal or vertical based on the | ||
| 708 : | orientation of the sash. For horizontal nodes, the "left" child is on | ||
| 709 : | top and the "right" child is on the bottom. Leaf nodes are instances of | ||
| 710 : | LayoutTree (the base class), and they point to a LayoutPart that | ||
| 711 : | occupies that region of the screen. Normally, this is a PartStack, but | ||
| 712 : | in general it can be any LayoutPart. <br> | ||
| 713 : | <br> | ||
| 714 : | Each LayoutTree occupies a recangular region of the screen that | ||
| 715 : | encompasses its children. Internal nodes keep track of an integer size | ||
| 716 : | for each child (implementation note: the sizes are stored in the | ||
| 717 : | associated LayoutPartSash, not the LayoutTreeNode itself). Normally, | ||
| 718 : | the left and right sizes are used as a ratio for dividing up the | ||
| 719 : | available space. However, when one child contains the editor area, the | ||
| 720 : | other becomes "non-compressible". If one side in non-compressible, the | ||
| 721 : | size value is interpreted as a fixed pixel size rather than a ratio. | ||
| 722 : | When the sash is moved, the size values are set to the current pixel | ||
| 723 : | sizes of the left and right children.<br> | ||
| 724 : | <br> | ||
| 725 : | Figure 3.5.2 shows an example LayoutTree. If this tree were rendered | ||
| 726 : | in a workbench window, it would resemble Figure 3.5.3. The tall | ||
| 727 : | vertical sash separating the package explorer from the editor area is | ||
| 728 : | the root node. The left child is the leaf node holding the package | ||
| 729 : | explorer's stack. The right node is the horizontal sash separating the | ||
| 730 : | problems view from the editor area. The editor area itself is a | ||
| 731 : | PartSashContainer, which has its own LayoutTree. Note that the rounded | ||
| 732 : | rectangles in Figure 3.5.2 are LayoutParts. The upper portion of the | ||
| 733 : | rectangle is the part type and the lower portion is some text to help | ||
| 734 : | locate the part in the screenshot. In this example, every internal node | ||
| 735 : | has the editor area on one side of it, so all sizes are interpreted as | ||
| 736 : | pixel sizes and not ratios.<br> | ||
| 737 : | <div style="text-align: center;"><span style="font-weight: bold;"></span><br> | ||
| 738 : | <span style="font-weight: bold;">Figure 3.5.2: Example LayoutTree</span><br | ||
| 739 : | style="font-weight: bold;"> | ||
| 740 : | <img alt="" src="example_LayoutTree.PNG" | ||
| 741 : | style="width: 480px; height: 462px; font-weight: bold;"><br> | ||
| 742 : | <span style="font-weight: bold;"><br> | ||
| 743 : | Figure 3.5.3: Example perspective</span><br style="font-weight: bold;"> | ||
| 744 : | <img alt="" src="perspective1.PNG" | ||
| 745 : | style="width: 571px; height: 495px; font-weight: bold;"><br> | ||
| 746 : | </div> | ||
| 747 : | <br> | ||
| 748 : | Like LayoutParts, LayoutTrees also implement ISizeProvider and support | ||
| 749 : | size constraints. For external nodes, the size constraints come | ||
| 750 : | directly from the LayoutPart. For internal nodes, the size constraints | ||
| 751 : | are computed from the child nodes as follows:<br> | ||
| 752 : | <ol> | ||
| 753 : | <li>When computing a constraint perpendicular to the sash, the result | ||
| 754 : | is the sum of the constraints of the children plus the width of the | ||
| 755 : | sash.</li> | ||
| 756 : | <li>When computing a constraint parallel to the sash, the result is | ||
| 757 : | the maximum of the constraints of the children<br> | ||
| 758 : | </li> | ||
| 759 : | </ol> | ||
| 760 : | An example can help make this a little less abstract. Imagine we're | ||
| 761 : | computing the minimum width for the root node in figure 3.5.1, which | ||
| 762 : | is a tall vertical sash. Width measurements are perpendicular to the | ||
| 763 : | sash, so we end up with case 1. The minimum width is the minimum width | ||
| 764 : | of the left stack plus the sash width plus the minimum width of the | ||
| 765 : | right child. This makes sense because if we made the root node any | ||
| 766 : | smaller, one of the three would need to be truncated or made smaller | ||
| 767 : | than their minimum size.<br> | ||
| 768 : | <br> | ||
| 769 : | The "right child" mentioned above is the horizontal sash separating the | ||
| 770 : | problems view from the editor area. When computing its minimum width, | ||
| 771 : | we hit case 2: the minimum width of a horizantal sash is the maximum of | ||
| 772 : | the minimum widths of each child. Intuitively, this means that the | ||
| 773 : | child with the larger minimum size will be the first to reach its | ||
| 774 : | minimum when the layout gets small.<br> | ||
| 775 : | <br> | ||
| 776 : | <h2><a class="mozTocH2" name="mozTocId370659"></a>3.6 Drag / Drop</h2> | ||
| 777 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 778 : | 3.6.1: LayoutPart drop regions</span><br> | ||
| 779 : | </div> | ||
| 780 : | <div style="text-align: center;"><img alt="" src="drag_regions.PNG" | ||
| 781 : | style="width: 571px; height: 495px;"><br> | ||
| 782 : | <div style="text-align: left;"><br> | ||
| 783 : | Dragging a workbench part is triggered by calling DragUtil.performDrag. | ||
| 784 : | SWT controls can respond to drag / drop by registering an | ||
| 785 : | IDragOverListener with DragUtil .addDragTarget. If multiple drag | ||
| 786 : | listeners are registered for the same screen position, the one | ||
| 787 : | associated with the most specific control gets precidence.<br> | ||
| 788 : | <br> | ||
| 789 : | Rather than register drag listeners directly, LayoutParts implement a | ||
| 790 : | getDropTarget method. When the window recieves a drag event, it | ||
| 791 : | delegates to the top-level LayoutPart's getDropTarget. Each part either | ||
| 792 : | delegates to one of its children or handles the drag event directly. If | ||
| 793 : | the part returns null from getDropTarget, this means that the part has | ||
| 794 : | no special preference for the drop event, and the parent may provide a | ||
| 795 : | default behavior. Unlike IDragOverListener, getDropTarget works | ||
| 796 : | top-down. The parent may overload any drag regions that are recognized | ||
| 797 : | by the child, or provide default behaviors for drag regions not | ||
| 798 : | recognized by the child.<br> | ||
| 799 : | <br> | ||
| 800 : | Figure 3.6.1 shows regions of the workbench where LayoutParts can be | ||
| 801 : | dropped. The workbench checks these regions in the following order:<br> | ||
| 802 : | <br> | ||
| 803 : | <table style="width: 100%; text-align: left;" border="1" cellpadding="2" | ||
| 804 : | cellspacing="2"> | ||
| 805 : | <tbody> | ||
| 806 : | <tr> | ||
| 807 : | <td style="vertical-align: top;"><span | ||
| 808 : | style="color: rgb(0, 51, 0);">1. green region</span><br> | ||
| 809 : | </td> | ||
| 810 : | <td style="vertical-align: top;">The fast view bar registers a | ||
| 811 : | IDragOverListener that responds to views being dragged.<br> | ||
| 812 : | </td> | ||
| 813 : | </tr> | ||
| 814 : | <tr> | ||
| 815 : | <td style="vertical-align: top;"><span | ||
| 816 : | style="background-color: rgb(0, 0, 0);"><span | ||
| 817 : | style="background-color: rgb(255, 255, 255);">2. black regions</span></span><br> | ||
| 818 : | </td> | ||
| 819 : | <td style="vertical-align: top;">These areas are reserved by | ||
| 820 : | PartSashContainer.getDropTarget. When the user drags a part over this | ||
| 821 : | region, the PartSashContainer interprets this as a split and does not | ||
| 822 : | ask its child to participate in the drag. This ensures that it is never | ||
| 823 : | possible for the child to prevent splitting by reserving its entire | ||
| 824 : | area as a drop region. The region outside the PartSashContainer's | ||
| 825 : | client area is handled by an IDragOverListener registered with the | ||
| 826 : | shell. This allows parts to be attached to the edge of the layout by | ||
| 827 : | dragging over the window trim.<br> | ||
| 828 : | </td> | ||
| 829 : | </tr> | ||
| 830 : | <tr> | ||
| 831 : | <td style="vertical-align: top;"><span | ||
| 832 : | style="color: rgb(255, 0, 0);">3. red regions</span><br> | ||
| 833 : | </td> | ||
| 834 : | <td style="vertical-align: top;">For most of the screen area, | ||
| 835 : | PartSashContainer delegates to its child (PartStack.getDropTarget). | ||
| 836 : | PartStack filters out objects that don't belong in the stack (no | ||
| 837 : | editors in view stacks, etc) and delegates to the presentation | ||
| 838 : | (StackPresentation.dragOver). The default presentation recognizes the | ||
| 839 : | tabs and title area as drop targets, but returns null everywhere else. | ||
| 840 : | This is the best practice for presentations and PartStack since it | ||
| 841 : | permits PartSashContainer to extend the split regions where possible.<br> | ||
| 842 : | </td> | ||
| 843 : | </tr> | ||
| 844 : | <tr> | ||
| 845 : | <td style="vertical-align: top;"><span | ||
| 846 : | style="color: rgb(0, 0, 153);">4. blue regions</span><br> | ||
| 847 : | </td> | ||
| 848 : | <td style="vertical-align: top;">If the child doesn't have any | ||
| 849 : | particular use for the drop location, the PartSashContainer extends the | ||
| 850 : | split regions. If the child allows objects of this type to be added | ||
| 851 : | (determined by calling LayoutPart.allowsAdd), it uses the center of the | ||
| 852 : | rectangle for stacking. Otherwise, the entire region is used for | ||
| 853 : | splitting. The latter case occurs when dragging views over the editor | ||
| 854 : | area or when dragging over a standalone view.<br> | ||
| 855 : | </td> | ||
| 856 : | </tr> | ||
| 857 : | <tr> | ||
| 858 : | <td style="vertical-align: top;">5. outside the window (not shown)<br> | ||
| 859 : | </td> | ||
| 860 : | <td style="vertical-align: top;">The workbench page registers an | ||
| 861 : | IDragOverListener that responds to views being dragged outside the | ||
| 862 : | workbench window, and interprets this as a detach operation.<br> | ||
| 863 : | </td> | ||
| 864 : | </tr> | ||
| 865 : | </tbody> | ||
| 866 : | </table> | ||
| 867 : | <br> | ||
| 868 : | By convention, all methods used for drag / drop work in display | ||
| 869 : | coordinates.<br> | ||
| 870 : | </div> | ||
| 871 : | </div> | ||
| 872 : | <h1><a class="mozTocH2" name="mozTocId438049"></a>3.0 Action Bars</h1> | ||
| 873 : | Parts contribute to menus, toolbars, coolbars, popup menus, etc. using | ||
| 874 : | action bars. Each action bar implements IActionBars. It is possible to | ||
| 875 : | create one action bar as a child of another. In this situation, the | ||
| 876 : | parent and child share the same widgets, but the child may be disabled | ||
| 877 : | independently of the parent. Figure 3.0.1 shows how the workbench | ||
| 878 : | action bars are | ||
| 879 : | constructed. The rectangles indicate instances of IActionBars, and the | ||
| 880 : | ovals indicate other entities that create or modify action bars.<br> | ||
| 881 : | <br> | ||
| 882 : | <div style="text-align: center;"><span style="font-weight: bold;">Figure | ||
| 883 : | 3.0.1: Action bar information flow</span><br> | ||
| 884 : | <img alt="" src="action_bar_flow.PNG" | ||
| 885 : | style="width: 800px; height: 600px;"><br> | ||
| 886 : | <div style="text-align: left;"><p:colorscheme | ||
| 887 : | colors="#FFFFFF,#000000,#808080,#000000,#00CC99,#3333CC,#CCCCFF,#B2B2B2"></p:colorscheme> | ||
| 888 : | <div v:shape="_x0000_s2050" class="O"> | ||
| 889 : | <div style=""><span style="font-size: 50%;"><br> | ||
| 890 : | </span><span style="font-family: Symbol; font-size: 50%;"></span><span | ||
| 891 : | style="font-size: 50%;"></span><span | ||
| 892 : | style="font-family: Symbol; font-size: 50%;"></span><span | ||
| 893 : | style="font-size: 50%;"></span><span | ||
| 894 : | style="font-family: Symbol; font-size: 50%;"></span><span | ||
| 895 : | style="font-size: 50%;"></span></div> | ||
| 896 : | <div style=""><span style="display: none;"> | ||
| 897 : | </span></div> | ||
| 898 : | </div> | ||
| 899 : | </div> | ||
| 900 : | </div> | ||
| 901 : | <br> | ||
| 902 : | The workbench window has a top level IActionBars instance that | ||
| 903 : | contributes to the main menubar, coolbar, etc. (this top-level object | ||
| 904 : | is returned by WorkbenchWindow.getActionBars()).<br> | ||
| 905 : | <br> | ||
| 906 : | <h2><a class="mozTocH3" name="mozTocId808539"></a>3.1 Editor Action Bars<br> | ||
| 907 : | </h2> | ||
| 908 : | Each type of editor gets a reference-counted IActionBars instance that | ||
| 909 : | is a child of the window's action bars. For | ||
| 910 : | example, if the workbench contains 10 java editors and 10 text editors, | ||
| 911 : | it will create one IActionBars to be shared among the Java editors and | ||
| 912 : | another IActionBars to be shared among the text editors. Editors can | ||
| 913 : | access this shared instance by calling getSite().getActionBars(). | ||
| 914 : | Editor action bars are initialized by an instance of | ||
| 915 : | IEditorActionBarContributor, and additional actions are added by the | ||
| 916 : | editorActions | ||
| 917 : | extension point.<br> | ||
| 918 : | <br> | ||
| 919 : | The reference counted IEditorActionBars are managed by the | ||
| 920 : | EditorManager, along with the IActionBarContributor.<br> | ||
| 921 : | <br> | ||
| 922 : | <h2><a class="mozTocH3" name="mozTocId809219"></a>3.2 Action Sets<br> | ||
| 923 : | </h2> | ||
| 924 : | An action set is an action bar that is identified by ID. Action sets | ||
| 925 : | are contributed by the actionSets extension point, and their action | ||
| 926 : | bars are a child of the workbench window's root action bars. Visibility | ||
| 927 : | of action sets is controlled by the following function:<br> | ||
| 928 : | <br> | ||
| 929 : | <div style="margin-left: 40px;"><img alt="" src="action_set_formula.PNG" | ||
| 930 : | style="width: 208px; height: 29px;"><br> | ||
| 931 : | </div> | ||
| 932 : | <br> | ||
| 933 : | Where:<br> | ||
| 934 : | <br> | ||
| 935 : | <div style="margin-left: 40px;">P = set of actions enabled in the | ||
| 936 : | perspective. Returned by Perspective.getAlwaysOnActionSets(). | ||
| 937 : | Initialized by the perspective factory, perspective extensions | ||
| 938 : | extension point, and IWonkbenchPage.showActionSet.<br> | ||
| 939 : | A = action sets associated with the active part (associated by the | ||
| 940 : | actionSetPartAssociations extension point).<br> | ||
| 941 : | E = action sets associated with the active editor (associated by the | ||
| 942 : | actionSetPartAssociations extension point).<br> | ||
| 943 : | D = action sets that are enabled by default (a property of the | ||
| 944 : | actionSets extension markup).<br> | ||
| 945 : | N = action sets that are explicitly disabled in the current | ||
| 946 : | perspective. Initialized by IWorkbenchPage.hideActionSet.<br> | ||
| 947 : | </div> | ||
| 948 : | <br> | ||
| 949 : | The sets P and N are persisted with the current perspective between | ||
| 950 : | sessions. The sets A and E can change every time the active part or | ||
| 951 : | editor changes.<br> | ||
| 952 : | <br> | ||
| 953 : | The workbench page uses the class ActionSetManager to compute action | ||
| 954 : | set enablement. This class keeps two reference counts for each action | ||
| 955 : | set: <br> | ||
| 956 : | <ul> | ||
| 957 : | <li>a "showCount" indicates how many of P, A, E, and D the action set | ||
| 958 : | appears in</li> | ||
| 959 : | <li>a "hideCount" indicates whether the action set appears in N</li> | ||
| 960 : | </ul> | ||
| 961 : | The action set is visible iff showCount is nonzero and hideCount is | ||
| 962 : | zero.<br> | ||
| 963 : | <br> | ||
| 964 : | <h2><a class="mozTocH3" name="mozTocId846891"></a>3.3 View Actions</h2> | ||
| 965 : | Each view instance is given its own IActionBars instance. Unlike editor | ||
| 966 : | action bars, these are not shared and are not a child of the workbench | ||
| 967 : | window's root action bars. This means that view instances can | ||
| 968 : | programmatically add actions to their action bar. Additional actions | ||
| 969 : | are also added to a view's action bars through the viewActions | ||
| 970 : | extension point.<br> | ||
| 971 : | <br> | ||
| 972 : | <h1><a class="mozTocH1" name="mozTocId453994"></a>4.0 General | ||
| 973 : | Conventions</h1> | ||
| 974 : | This section describes coding conventions that apply to the entire | ||
| 975 : | workbench.<br> | ||
| 976 : | <h2><a class="mozTocH3" name="mozTocId451497"></a>4.1 Objects must not | ||
| 977 : | be returned through API until they are fully initialized</h2> | ||
| 978 : | Some objects require several public methods to be called in a specific | ||
| 979 : | order before they are considered fully initialized. For example, to | ||
| 980 : | initialize an IViewPart, it is necessary to call the constructor, | ||
| 981 : | setInitializationData, init, and createPartControl before the part is | ||
| 982 : | considered initialized. Until <span style="font-style: italic;">all</span> | ||
| 983 : | of the above have happened successfully, it must not be possible to | ||
| 984 : | reach the object through any API method.<br> | ||
| 985 : | <br> | ||
| 986 : | Keep in mind that the may trigger other client code during its own | ||
| 987 : | initialization, so it should not even be possible for an object to find | ||
| 988 : | itself during construction.<br> | ||
| 989 : | <h2><a class="mozTocH3" name="mozTocId959546"></a>4.2 No method may | ||
| 990 : | open a modal dialog unless its JavaDoc says so</h2> | ||
| 991 : | Any method that has the possibility of opening a modal (or of calling | ||
| 992 : | Display.readAndDispatch through any other means) needs to be clearly | ||
| 993 : | documented. All callers of that method must be prepared to handle | ||
| 994 : | background | ||
| 995 : | threads running arbitrary code in *syncExecs during the method call. It | ||
| 996 : | is always a bug to open a modal dialog when extending or overloading a | ||
| 997 : | method unless the JavaDoc in the base class says otherwise. Permitting | ||
| 998 : | opening of dialogs in a method that did not previously do so is a | ||
| 999 : | breaking change for all callers of that method.<br> | ||
| 1000 : | <br> | ||
| 1001 : | Some common bugs:<br> | ||
| 1002 : | <ul> | ||
| 1003 : | <li>Views are never allowed to call MessageDialog.openError from | ||
| 1004 : | their createPartControls method, especially when handling an exception.</li> | ||
| 1005 : | <li>Parts can be closed in a *syncExec. If a part calls a method that | ||
| 1006 : | opens dialogs, it might not still exist when the method returns. After | ||
| 1007 : | calling the method, the part must check that it hasn't been disposed | ||
| 1008 : | before using their widgets or accessing any members that would have | ||
| 1009 : | been deallocated by the disposal.<br> | ||
| 1010 : | </li> | ||
| 1011 : | </ul> | ||
| 1012 : | <h2><a class="mozTocH3" name="mozTocId877708"></a>4.3 Lazy creation | ||
| 1013 : | should happen as late as possible<br> | ||
| 1014 : | </h2> | ||
| 1015 : | Part implementations should be created at the latest possible moment. | ||
| 1016 : | The workbench's internal state should be restored as much as possible | ||
| 1017 : | before the first object is created from an extension point. Parts | ||
| 1018 : | should not be materialized until they are needed.<br> | ||
| 1019 : | <h2><a class="mozTocH3" name="mozTocId758931"></a>4.4 getters should | ||
| 1020 : | not modify the thing they are supposed to measure<br> | ||
| 1021 : | </h2> | ||
| 1022 : | This applies to any situation where there is a getter and an associated | ||
| 1023 : | listener that monitors changes in the getter's value. The getter should | ||
| 1024 : | never cause such a property change to be fired while computing its | ||
| 1025 : | return value.<br> | ||
| 1026 : | <br> | ||
| 1027 : | For example, IWorkbenchPage.getActivePart() should never create the | ||
| 1028 : | active part. Unless the active part already exists and a property | ||
| 1029 : | change was fired to all IPartListeners, getActivePart must return null.<br> | ||
| 1030 : | <br> | ||
| 1031 : | <br> | ||
| 1032 : | </body> | ||
| 1033 : | </html> |
| help@eclipse.org | ViewVC Help |
| Powered by ViewVC 1.0.3 |
