platform-ui-home/components-proposal/ComponentFrameworkProposal.html

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Tue Nov 2 22:51:37 2004 UTC revision 1.2, Sat Nov 6 00:49:47 2004 UTC
# Line 12  Line 12 
12   style="font-weight: bold;">Component Framework Proposal</span></font><br>   style="font-weight: bold;">Component Framework Proposal</span></font><br>
13  </div>  </div>
14  <br>  <br>
15  <div style="text-align: center;">Revision 1.0.3<br>  <div style="text-align: center;">Draft<br>
16    Revision 1.0.4<br>
17  By Stefan Xenos and Nick Edgar<br>  By Stefan Xenos and Nick Edgar<br>
18  Last modified 2004/11/02<br>  Last modified 2004/11/05<br>
19  </div>  </div>
20  <br>  <br>
21  <br>  <br>
# Line 25  Line 26 
26  Introduction  Introduction
27      </a>      </a>
28      <ul>      <ul>
29        <li><a href="#mozTocId29093">1.1 Robustness / leak proofing        <li><a href="#mozTocId619855">1.1 Understanding the problem</a></li>
30          <li><a href="#mozTocId340323">1.2 Requirements
31            </a>
32            <ul>
33              <li><a href="#mozTocId29093">1.2.1 Robustness /
34    leak
35    proofing
36          </a></li>          </a></li>
37        <li><a href="#mozTocId223982">1.2 Nesting of components</a></li>            <li><a href="#mozTocId223982">1.2.2 Nesting of
38        <li><a href="#mozTocId634024">1.3 Creating parts outside the  components</a></li>
39  workbench</a></li>            <li><a href="#mozTocId634024">1.2.3 Creating parts
40        <li><a href="#mozTocId800379">1.4 Scalability</a></li>  outside the workbench</a></li>
41        <li><a href="#mozTocId866479">1.5 Ease of use            <li><a href="#mozTocId800379">1.2.4 Scalability</a></li>
42              <li><a href="#mozTocId866479">1.2.5 Ease of use
43          </a></li>          </a></li>
44      </ul>      </ul>
45    </li>    </li>
46    <li><a href="#mozTocId416167">2.0 Component Framework      </ul>
47      </li>
48      <li><a href="#mozTocId416167">2.0 Component
49    Framework
50      </a>      </a>
51      <ul>      <ul>
52        <li><a href="#mozTocId489102">2.1 Instantiating a view        <li><a href="#mozTocId489102">2.1 Instantiating a
53    view
54          </a></li>          </a></li>
55        <li><a href="#mozTocId717633">2.2 Instantiating components in        <li><a href="#mozTocId717633">2.2 Instantiating
56  general  components in general
57          </a></li>          </a></li>
58        <li><a href="#mozTocId450231">2.3 Creating dependent components        <li><a href="#mozTocId450231">2.3 Creating
59  on demand </a></li>  dependent components on demand </a></li>
60        <li><a href="#mozTocId928619">2.4 Declaring Global Services        <li><a href="#mozTocId928619">2.4 Declaring Component Interfaces</a></li>
61          </a></li>        <li><a href="#mozTocId749133">2.5 Using Component Interfaces</a></li>
       <li><a href="#mozTocId749133">2.5 Using services</a></li>  
62        <li><a href="#mozTocId705695">2.6 Lifecycle</a></li>        <li><a href="#mozTocId705695">2.6 Lifecycle</a></li>
63        <li><a href="#mozTocId543223">2.7 Dynamic Services</a></li>        <li><a href="#mozTocId543223">2.7 Dynamic Interfaces</a></li>
64        <li><a href="#mozTocId886834">2.8 Optional Services</a></li>        <li><a href="#mozTocId886834">2.8 Optional Interface
65        <li><a href="#mozTocId163729">2.9 Multiplexing services</a></li>          </a></li>
66          <li><a href="#mozTocId578639">2.8 Component Scopes</a></li>
67          <li><a href="#mozTocId762751">2.9 Shared Adapters</a></li>
68        </ul>
69      </li>
70      <li><a href="#mozTocId707022">3.0 Views and Editors
71    as Components</a>
72        <ul>
73          <li><a href="#mozTocId125361">3.1 Interfaces offered by the
74    workbench</a>
75            <ul>
76              <li><a href="#mozTocId163729">3.1.1 IMultiPart: Redirecting
77    adapters from the active child
78                </a></li>
79              <li><a href="#mozTocId483376">3.1.2 INameable: Changing the
80    name of a part</a></li>
81              <li><a href="#mozTocId969580">3.1.3 IPartFactory: Creating
82    child parts</a></li>
83            </ul>
84          </li>
85      </ul>      </ul>
86    </li>    </li>
   <li><a href="#mozTocId707022">3.0 Views and Editors as Components</a></li>  
87  </ul>  </ul>
88  <br>  <br>
89  <h1><a class="mozTocH1" name="mozTocId511305"></a>1.0 Introduction<br>  <h1><a class="mozTocH1" name="mozTocId511305"></a>1.0 Introduction<br>
# Line 75  Line 104 
104  third section describes how the workbench will use the component  third section describes how the workbench will use the component
105  framework for views and editors.<br>  framework for views and editors.<br>
106  <br>  <br>
107    <h2><a class="mozTocH2" name="mozTocId619855"></a>1.1 Understanding the
108    problem</h2>
109    This section explains why the component framework is needed to support
110    nested parts. We will show the problems involved in designing an
111    extensible Site interface, and will show how they can be solved using
112    the patterns in the component framework. Skip to the next sections if
113    you don't need convincing and just want to see the specification.
114    IMPORTANT NOTE:
115    the code examples in this section are only intended to illustrate
116    patterns and do not reflect the actual implementation<br>
117    <br>
118    Currently, parts communicate with their parent through their site. The
119    site provides the view with access to the outside world. In general, it
120    is better to provide new API on the part's site than have the part
121    reach to some global object, since the site can provide some context
122    and can manage resources allocated to the part.<br>
123    <br>
124    Here is a simplified version of the View and Site interface. We've
125    omitted most of the details. The important part is that the View is
126    given a Site when it is initialized, it uses various methods on the
127    Site throughout its life, and the Site has a dispose() method that can
128    clean up after the View.<br>
129    <code><br>
130    </code>
131    <div style="margin-left: 40px;"><code>/**<br>
132    &nbsp;* A view's main interface to the world.<br>
133    &nbsp;*/<br>
134    public class Site {<br>
135    &nbsp;&nbsp;&nbsp; /**<br>
136    &nbsp;&nbsp;&nbsp;&nbsp; * Create a view site, given the plugin that
137    contains the implementation for the view<br>
138    &nbsp;&nbsp;&nbsp;&nbsp; */<br>
139    &nbsp;&nbsp;&nbsp; public Site(Plugin viewPlugin) {<br>
140    &nbsp;&nbsp;&nbsp; }<br>
141    <br>
142    &nbsp;&nbsp;&nbsp; /**<br>
143    &nbsp;&nbsp;&nbsp;&nbsp; * Return the view's ID<br>
144    &nbsp;&nbsp;&nbsp;&nbsp; */<br>
145    &nbsp;&nbsp;&nbsp; public String getId() {...};<br>
146    <br>
147    &nbsp;&nbsp;&nbsp; public IActionBars getActionBars() {...};<br>
148    <br>
149    &nbsp;&nbsp;&nbsp; /**<br>
150    &nbsp;&nbsp;&nbsp;&nbsp; * Clean up any leftover resources allocated by
151    the site<br>
152    &nbsp;&nbsp;&nbsp;&nbsp; */<br>
153    &nbsp;&nbsp;&nbsp; public void dispose() {<br>
154    &nbsp;&nbsp;&nbsp; };<br>
155    }<br>
156    <br>
157    /**<br>
158    &nbsp;* Base class for all views.<br>
159    &nbsp;*/<br>
160    public abstract class View {<br>
161    &nbsp;&nbsp;&nbsp; private Site mySite;<br>
162    <br>
163    &nbsp;&nbsp;&nbsp; public View(Site viewSite) {<br>
164    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; mySite = viewSite;<br>
165    &nbsp;&nbsp;&nbsp; }<br>
166    <br>
167    &nbsp;&nbsp;&nbsp; public Site getSite() {<br>
168    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return mySite;<br>
169    &nbsp;&nbsp;&nbsp; }<br>
170    <br>
171    &nbsp;&nbsp;&nbsp; public abstract String getTitle();<br>
172    <br>
173    &nbsp;&nbsp;&nbsp; public void dispose() {};<br>
174    }<br>
175    <br>
176    /**<br>
177    &nbsp;* A factory that can create views by ID.<br>
178    &nbsp;*/<br>
179    public ViewFactory {<br>
180    &nbsp;&nbsp;&nbsp; public static View createView(String
181    viewExtensionId, Site viewSite) {<br>
182    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //... create a view and return it<br>
183    &nbsp;&nbsp;&nbsp; }<br>
184    }<br>
185    </code></div>
186    <br>
187    Anyone that wants to instantiate a view would need to create an
188    instance of Site and create the view by calling ViewFactory.createView.
189    It would be possible to subclass Site in order to provide the part with
190    additional context. For example, a subclass of Site could overload
191    getActionBars() to substitute a different implementation of IActionBars
192    to be used by the view. <br>
193    <br>
194    One of the problems with using the Site as the main interface to a view
195    is that we continually need to add new methods to the Site base class.
196    For example, we might decide to add a logError method that allows views
197    to log exceptions to their plugin log without needing to reach to their
198    Plugin object or worry about constructing IStatus instances with the
199    correct plugin ID.<br>
200    <br>
201    <div style="margin-left: 40px;"><code>/**</code><br>
202    <code>&nbsp;* A view's main interface to the world.</code><br>
203    <code>&nbsp;*/</code><br>
204    <code>public class Site {<br>
205    &nbsp;&nbsp;&nbsp; Plugin plugin;<br>
206    <br>
207    </code><code></code><code>&nbsp;&nbsp;&nbsp; public Site(Plugin
208    viewPlugin) {<br>
209    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; plugin = viewPlugin;<br>
210    &nbsp;&nbsp;&nbsp; }<br>
211    <br>
212    &nbsp;&nbsp;&nbsp; // ...all other Site methods omitted...<br>
213    <br>
214    </code><code>&nbsp;&nbsp;&nbsp; public void logError(Throwable t) {<br>
215    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; plugin.getLog().log(new Status(..., t));<br>
216    &nbsp;&nbsp;&nbsp; };<br>
217    </code><code>}</code><br>
218    </div>
219    <br>
220    The site could also provide the view with localized ways to allocate
221    resources. For example, if the view could allocate Images through its
222    site, the Site could guarantee that the images would be cleaned up
223    properly when the view is destroyed.<br>
224    <div style="margin-left: 40px;"><code><br>
225    /**</code><br>
226    <code>
227    &nbsp;* A view's main interface to the world.</code><br>
228    <code>
229    &nbsp;*/</code><br>
230    <code>
231    public class Site {<br>
232    <br>
233    &nbsp;&nbsp;&nbsp; // .... everything in the above version of Site plus
234    this:<br>
235    <br>
236    &nbsp;&nbsp;&nbsp; Map allocatedImages = new HashMap();<br>
237    <br>
238    &nbsp;&nbsp;&nbsp; public Image createImage(ImageDescriptor toCreate) {<br>
239    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Image image =
240    toCreate.createImage(true);<br>
241    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; allocatedImages.put(toCreate, image);<br>
242    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return image;<br>
243    &nbsp;&nbsp;&nbsp; }<br>
244    <br>
245    &nbsp;&nbsp;&nbsp; public void destroyImage(ImageDescriptor toDestroy) {<br>
246    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Image image =
247    allocatedImages.get(toDestroy);<br>
248    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (image != null) {<br>
249    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
250    allocatedImages.remove(toDestroy);<br>
251    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; image.dispose();<br>
252    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
253    &nbsp;&nbsp;&nbsp; }<br>
254    <br>
255    &nbsp;&nbsp;&nbsp; public void dispose() {<br>
256    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Collection values =
257    allocatedImages.getValueSet();<br>
258    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Iterator iter = values.iterator();<br>
259    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; while (iter.hasNext()) {<br>
260    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; Image img =
261    (Image)iter.next();<br>
262    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; img.dispose();<br>
263    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
264    &nbsp;&nbsp;&nbsp; }</code><code><br>
265    </code><code>
266    }<br>
267    <br>
268    </code></div>
269    In order to provide the best protection against leaks, new API should
270    use this pattern as much as possible for views. The obvious problems
271    with this are:<br>
272    <ol>
273      <li>Whoever implements the Site class can't possibly know about every
274    type of resource that might be allocated by every view</li>
275      <li>The Site interface would become ridiculously large and
276    complicated.<br>
277      </li>
278    </ol>
279    It would be possible to work around this by writing new subclasses of
280    Site that add new methods, but then Views that use the new APIs would
281    not function properly when given a different Site implementation. The
282    ideal solution would allow plugins to contribute new default behavior
283    to the Site base class, and only require the Site class to be
284    subclassed when this behavior needs to be specialized. This can be
285    achieved by making Site adaptable. Rather than always adding new
286    methods to Site, plugins couldcontribute adapters. Subclasses of site
287    would still be able to override the default adapter behavior by
288    explicitly implementing the adapter interface, but parts that use the
289    adapter would no longer be tied to a particular Site implementation.<br>
290    <br>
291    Here is an example that demonstrates the pattern:<br>
292    <br>
293    <div style="margin-left: 40px;"><code>/**</code><br>
294    <code>
295    &nbsp;* Adapter for a view site that allows allocation/deallocation of
296    images</code><br>
297    <code>
298    &nbsp;*/</code><br>
299    <code>
300    public interface IImageAllocator {<br>
301    &nbsp;&nbsp;&nbsp; public Image createImage(ImageDescriptor toCreate);<br>
302    &nbsp;&nbsp;&nbsp; public void destroyImage(ImageDescriptor toDestroy);<br>
303    </code><code>}<br>
304    <br>
305    /**<br>
306    &nbsp;* Implementation of the image allocator adapter provided via XML<br>
307    &nbsp;* by some plugin.<br>
308    &nbsp;*/<br>
309    public class ImageAllocator implements IImageAllocator, IDisposable {<br>
310    &nbsp;&nbsp;&nbsp; </code><code>public Image
311    createImage(ImageDescriptor toCreate) {<br>
312    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...<br>
313    &nbsp;&nbsp;&nbsp; };<br>
314    <br>
315    &nbsp;&nbsp;&nbsp; public void destroyImage(ImageDescriptor toDestroy) {<br>
316    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ...<br>
317    &nbsp;&nbsp;&nbsp; };<br>
318    <br>
319    &nbsp;&nbsp;&nbsp; public void dispose() {<br>
320    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Dispose any images leaked through
321    createImage<br>
322    &nbsp;&nbsp;&nbsp; };<br>
323    </code><code>}<br>
324    <br>
325    /**<br>
326    &nbsp;* Next attempt at a site interface<br>
327    &nbsp;*/<br>
328    public class Site implements IAdaptable {<br>
329    <br>
330    &nbsp;&nbsp;&nbsp; List disposableAdapters = new ArrayList();<br>
331    <br>
332    &nbsp;&nbsp;&nbsp; public Object getAdapter(Class adapterType) {<br>
333    </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Object result = //</code><code>...some
334    magic that looks through the adapter extension point and<br>
335    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
336    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //creates an instance of ImageAllocator<br>
337    <br>
338    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (adapter instanceof IDisposable) {<br>
339    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
340    disposableAdapters.add(adapter);<br>
341    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
342    <br>
343    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return result;<br>
344    &nbsp;&nbsp;&nbsp; }<br>
345    <br>
346    &nbsp;&nbsp;&nbsp; /**<br>
347    &nbsp;&nbsp;&nbsp;&nbsp; * Allow all the adapters to clean up anything
348    they allocated.<br>
349    &nbsp;&nbsp;&nbsp;&nbsp; */<br>
350    &nbsp;&nbsp;&nbsp; public void dispose() {<br>
351    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Iterator iter =
352    disposableAdapters.iterator();<br>
353    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; while(iter.hasNext()) {<br>
354    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; IDisposable next =
355    (IDisposable)iter.next();<br>
356    <br>
357    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; next.dispose();<br>
358    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
359    &nbsp;&nbsp;&nbsp; }<br>
360    }<br>
361    <br>
362    </code><code>/**<br>
363    &nbsp;* Base class for all views.<br>
364    &nbsp;*/<br>
365    public abstract class View {<br>
366    &nbsp;&nbsp;&nbsp; private IAdaptable mySite;<br>
367    <br>
368    &nbsp;&nbsp;&nbsp; public View(IAdaptable viewSite) {<br>
369    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; mySite = viewSite;<br>
370    &nbsp;&nbsp;&nbsp; }<br>
371    <br>
372    &nbsp;&nbsp;&nbsp; public IAdaptable getSite() {<br>
373    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return mySite;<br>
374    &nbsp;&nbsp;&nbsp; }<br>
375    <br>
376    &nbsp;&nbsp;&nbsp; public abstract String getTitle();<br>
377    <br>
378    &nbsp;&nbsp;&nbsp; public void dispose() {};<br>
379    }</code><br>
380    </div>
381    <br>
382    Notice that this type of adapter is slightly different from most other
383    adapters in Eclipse since it keeps some state and need to be notified
384    when the Site is disposed. <br>
385    <br>
386    A particular view would look like this:<br>
387    <br>
388    <div style="margin-left: 40px;"><code>/**<br>
389    &nbsp;* My implementation of a view<br>
390    &nbsp;*/<br>
391    public class MyView extends View {<br>
392    &nbsp;&nbsp;&nbsp; IImageAllocator allocator;<br>
393    <br>
394    &nbsp;&nbsp;&nbsp; public MyView(IAdaptable viewSite) {<br>
395    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; allocator =
396    (IImageAllocator)viewSite.getAdapter(IImageAllocator.class);<br>
397    <br>
398    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (allocator == null) {<br>
399    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; throw new Exception("I
400    can't exist without images!");<br>
401    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
402    &nbsp;&nbsp;&nbsp; }<br>
403    <br>
404    &nbsp;&nbsp;&nbsp; //...<br>
405    }<br>
406    <br>
407    </code></div>
408    Most views will contain similar code in their constructor that requests
409    a set of adapters from their site and check that they aren't null. We
410    can add some syntactic sugar to remove this repetition. Rather than
411    having the view explicitly request every adapter it needs, it can take
412    them as arguments to its constructor and the factory that creates the
413    view can use reflection to ensure that it gets all the adapters it
414    needs. Using this pattern, the same view would look like this:<br>
415    <br>
416    <div style="margin-left: 40px;"><code>/**</code><br>
417    <code>&nbsp;* My implementation of a view</code><br>
418    <code>&nbsp;*/</code><br>
419    <code>public class MyView extends View {</code><br>
420    <code>&nbsp;&nbsp;&nbsp; IImageAllocator allocator;</code><br>
421    <code></code><br>
422    <code>&nbsp;&nbsp;&nbsp; public MyView(IImageAllocator imageAllocator) {<br>
423    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; allocator = imageAllocator;<br>
424    </code><code></code><code>&nbsp;&nbsp;&nbsp; }</code><br>
425    <code></code><br>
426    <code>&nbsp;&nbsp;&nbsp; //...</code><br>
427    <code>}<br>
428    <br>
429    </code></div>
430    Since the entire Site API would be provided by adapters, the Site class
431    could be reduced to this:<br>
432    <br>
433    <div style="margin-left: 40px;"><code>/**</code><br>
434    <code>&nbsp;* My implementation of a view</code><br>
435    <code>&nbsp;*/</code><br>
436    <code>public abstract class Site implements IAdaptable {<br>
437    &nbsp;&nbsp;&nbsp; public abstract Object getAdapter(Class adapter);<br>
438    &nbsp;&nbsp;&nbsp; public abstract void dispose();<br>
439    </code><code></code><code>}</code><br>
440    </div>
441    <br>
442    In the component framework, this simplified Site interface is called
443    IContainer. We now have a highly extensible Site interface, however the
444    same versioning problems apply to the view as well. The parent of the
445    view may want to access methods on the View, but we don't want to be
446    continually adding things to the View base class. For this reason, we
447    communicate with the view through adapters as well.<br>
448    <br>
449    This is the core pattern behind the component framework. It consists of:<br>
450    <ol>
451      <li>An extension point that allows 3rd party plugins to contribute
452    interfaces to components (views and their sites)<br>
453      </li>
454      <li>A factory that allows components to be created through
455    constructor injection</li>
456      <li>A container interface that manages the lifecycle of components
457    and their adapters </li>
458    </ol>
459    <div style="margin-left: 40px;"></div>
460    <h2><a class="mozTocH2" name="mozTocId340323"></a>1.2 Requirements<br>
461    </h2>
462  Primary goals:<br>  Primary goals:<br>
463  <ul>  <ul>
464    <li>Robustness / leak proofing</li>    <li>Robustness / leak proofing</li>
# Line 85  Line 469 
469    </li>    </li>
470    <li>Ease of use</li>    <li>Ease of use</li>
471  </ul>  </ul>
472  <h2><a class="mozTocH2" name="mozTocId29093"></a>1.1 Robustness / leak  <h3><a class="mozTocH2" name="mozTocId29093"></a>1.2.1 Robustness /
473    leak
474  proofing<br>  proofing<br>
475  </h2>  </h3>
476  Much of the Eclipse API is currently accessed through singleton  Much of the Eclipse API is currently accessed through singleton
477  objects. This makes it easy for a view or editor to leak listeners,  objects. This makes it easy for a view or editor to leak listeners,
478  fail to clean up reference counts, leak OS resources, etc. since there  fail to clean up reference counts, leak OS resources, etc. since there
479  is no way of tracking which resources were allocated by a particular  is no way of tracking which resources were allocated by a particular
480  view. This problem would be reduced if views and editors were more like  view. This problem would be reduced if views and editors were more like
481  mini-applications. The view or editor would access the rest of the  mini-applications. The view or editor would access the rest of the
482  world through a set of local services. When the view or editor is  world through a set of local interfaces. When the view or editor is
483  destroyed so would all of the services allocated for it. This gives  destroyed, all the interfaces would be notified giving them a chance to
484  each service a chance to clean up after itself. <br>  clean up any leaked resources.<br>
485  <br>  <br>
486  For example, instead of reaching into a global  For example, instead of reaching into a global
487  preference store, a view or editor could access all preferences through  preference store, a view or editor could access all preferences through
488  a local preference  a local preference adapter. A unique instance of the local preference
489  service. A unique instance of the local preference service would be  adapter would be
490  created for each view, and would be disposed with the view. When the  created for each view, and would be disposed with the view. When the
491  preference service is destroyed it would clear its listener list,  preference adapter is destroyed it would clear its listener list,
492  ensuring that the view will not leak any global listeners. This example  ensuring that the view will not leak any global listeners. This example
493  shows what we mean by a component. Essentially, a  shows what we mean by a component. Essentially, a
494  component is an object that communicates with the rest of the  component is an object that communicates with the rest of the
495  application through a set of interfaces given to it in its constructor.<br>  application through a set of interfaces given to it in its constructor.<br>
496  <span style="font-weight: bold;"></span>  <span style="font-weight: bold;"></span>
497  <h2><a class="mozTocH2" name="mozTocId223982"></a>1.2 Nesting of  <h3><a class="mozTocH2" name="mozTocId223982"></a>1.2.2 Nesting of
498  components</h2>  components</h3>
499  There is demand for the ability to embed views and editors inside one  There is demand for the ability to embed views and editors inside one
500  another. Some examples:<br>  another. Some examples:<br>
501  <ul>  <ul>
# Line 125  Line 510 
510    </li>    </li>
511  </ul>  </ul>
512  Many downstream plugins have solved these problems by creating their  Many downstream plugins have solved these problems by creating their
513  own frameworks for reusable UI components. Unfortunately, only works  own frameworks for reusable UI components. Unfortunately, this only
514    works
515  for specific views and editors, does not encourage interoperability  for specific views and editors, does not encourage interoperability
516  between plugins that have adopted different frameworks, and requires a  between plugins that have adopted different frameworks, and requires a
517  lot of work. The goal here is to adopt a framework in the workbench  lot of work. The goal here is to adopt a framework in the workbench
518  itself that allows all editors, views, and other workbench objects to  itself that allows all editors, views, and other workbench objects to
519  be easily nested.<br>  be easily nested.<br>
520  <h2><a class="mozTocH2" name="mozTocId634024"></a>1.3 Creating parts  <h3><a class="mozTocH2" name="mozTocId634024"></a>1.2.3 Creating parts
521  outside the workbench</h2>  outside the workbench</h3>
522  It should be possible to instantiate views and editors outside the  It should be possible to instantiate views and editors outside the
523  workbench. Some examples:<br>  workbench. Some examples:<br>
524  <ul>  <ul>
# Line 142  Line 528 
528  but includes view-like pluggable parts  but includes view-like pluggable parts
529  that could also be used as views within Eclipse</li>  that could also be used as views within Eclipse</li>
530  </ul>  </ul>
531  <h2><a class="mozTocH2" name="mozTocId800379"></a>1.4 Scalability</h2>  <h3><a class="mozTocH2" name="mozTocId800379"></a>1.2.4 Scalability</h3>
532  The workbench currently offers a closed set of services to parts. This  The workbench currently offers a closed interface to parts. This
533  forces parts to reach to global objects whenever they need something  forces parts to reach to global objects whenever they need something
534  that isn't available from their site. It should be possible for any  that isn't available from their site. It should be possible for any
535  plugin to contribute to the set of local API available to a part, and  plugin to contribute to the set of local API available to a part, and
536  it  it
537  should be possible to instantiate a part even if its parent doesn't  should be possible to instantiate a part even if its parent doesn't
538  know about all of a part's dependencies.<br>  know about all of a part's dependencies.<br>
539  <h2><a class="mozTocH2" name="mozTocId866479"></a>1.5 Ease of use<br>  <h3><a class="mozTocH2" name="mozTocId866479"></a>1.2.5 Ease of use<br>
540  </h2>  </h3>
541  Views and editors currently have a complicated lifecycle that must be  Views and editors currently have a complicated lifecycle that must be
542  managed by the workbench. This complexity should not be exposed to  managed by the workbench. This complexity should not be exposed to
543  client code. <br>  client code. <br>
# Line 171  Line 557 
557  <h1><a class="mozTocH1" name="mozTocId416167"></a>2.0 Component  <h1><a class="mozTocH1" name="mozTocId416167"></a>2.0 Component
558  Framework<br>  Framework<br>
559  </h1>  </h1>
560  Components are pluggable objects that are build using constructor  First, some terminology. The pluggable objects that clients write are
561    called "components". For example, the class that contains the
562    implementation of a view itself would be called a component. A
563    component exists inside an IContainer. In the case of editors and
564    views, IContainer replaces the existing IWorkbenchSite. Unlike
565    IWorkbenchSite, the component never needs to directly access the
566    IContainer since all of its useful interface is provided through
567    adapters. Instead, the component supplies a constructor that takes all
568    the interfaces it needs, and it communicates with the outside world
569    through these interfaces.<br>
570    <br>
571    Components are built using constructor
572  injection. Constructor injection means that the framework looks at the  injection. Constructor injection means that the framework looks at the
573  object's constructor to determine what it needs to do to build that  object's constructor to determine what it needs to do to build that
574  object.<br>  object.<br>
# Line 202  Line 599 
599  like this:<br>  like this:<br>
600  <br>  <br>
601  <div style="margin-left: 40px;"><code>/**</code><br>  <div style="margin-left: 40px;"><code>/**</code><br>
602  <code>&nbsp;* "Hello world" view using the service framework</code><br>  <code>&nbsp;* "Hello world" view using the component framework</code><br>
603  <code>&nbsp;*/</code><br>  <code>&nbsp;*/</code><br>
604  <code>public class HelloWorldView {</code><br>  <code>public class HelloWorldView {</code><br>
605  <code>&nbsp;&nbsp;&nbsp; public HelloWorldView(Composite parent) {</code><br>  <code>&nbsp;&nbsp;&nbsp; public HelloWorldView(Composite parent) {</code><br>
# Line 215  Line 612 
612  <code>}</code><br>  <code>}</code><br>
613  <code></code></div>  <code></code></div>
614  <code><br>  <code><br>
615  </code>The HelloWorldView component depends on one service: a Composite  </code>The HelloWorldView component depends on one other object: a
616    Composite
617  created for it by whoever instantiated the view. Compare this with the  created for it by whoever instantiated the view. Compare this with the
618  same view written using the existing API:<br>  same view written using the existing API:<br>
619  <br>  <br>
# Line 296  Line 694 
694  view that previously implemented the IViewInterface1 migrates to using  view that previously implemented the IViewInterface1 migrates to using
695  the newer IViewInterface2, its container will continue to work as long  the newer IViewInterface2, its container will continue to work as long
696  as someone has provided an adapter between the two versions of  as someone has provided an adapter between the two versions of
697  IViewInterface. The getAdapter() method on IComponent searches for  IViewInterface. The getAdapter() method on IContainer searches for
698  adapters in the following order:<br>  adapters in the following order:<br>
699  <br>  <br>
700  1. If the component itself implements the adapter type, it returns the  1. If the component itself implements the adapter type, it returns the
# Line 373  Line 771 
771  caller MUST call IContainer.dispose() <br>  caller MUST call IContainer.dispose() <br>
772  &nbsp;&nbsp;&nbsp;&nbsp; * when it is done with the component. The  &nbsp;&nbsp;&nbsp;&nbsp; * when it is done with the component. The
773  factory does not need any prior<br>  factory does not need any prior<br>
774  &nbsp;&nbsp;&nbsp;&nbsp; * knowledge of the component class be<br>  &nbsp;&nbsp;&nbsp;&nbsp; * knowledge of the component class.<br>
775  &nbsp;&nbsp;&nbsp;&nbsp; * <br>  &nbsp;&nbsp;&nbsp;&nbsp; * <br>
776  &nbsp;&nbsp;&nbsp;&nbsp; * @param componentImplementation concrete  &nbsp;&nbsp;&nbsp;&nbsp; * @param componentImplementation concrete
777  class to be instantiated by the factory. The class<br>  class to be instantiated by the factory. The class<br>
# Line 384  Line 782 
782  references other component interfaces known to this factory).<br>  references other component interfaces known to this factory).<br>
783  &nbsp;&nbsp;&nbsp;&nbsp; * @return a newly constructed  &nbsp;&nbsp;&nbsp;&nbsp; * @return a newly constructed
784  &lt;code&gt;IContainer&lt;/code&gt; instance<br>  &lt;code&gt;IContainer&lt;/code&gt; instance<br>
785  &nbsp;&nbsp;&nbsp;&nbsp; * @throws MissingDependencyException if the  &nbsp;&nbsp;&nbsp;&nbsp; * @throws CoreException if unable to create
786  requested component depends on another component that<br>  the component<br>
 &nbsp;&nbsp;&nbsp;&nbsp;  
 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cannot be constructed  
 by this factory<br>  
 &nbsp;&nbsp;&nbsp;&nbsp; * @throws CoreException if there is a more  
 permanent problem with using the given class as <br>  
 &nbsp;&nbsp;&nbsp;&nbsp;  
 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a component <br>  
 &nbsp;&nbsp;&nbsp;&nbsp; * @since 3.1<br>  
787  &nbsp;&nbsp;&nbsp;&nbsp; */<br>  &nbsp;&nbsp;&nbsp;&nbsp; */<br>
788  &nbsp;&nbsp;&nbsp; public IContainer createContainer(Class  &nbsp;&nbsp;&nbsp; public IContainer createContainer(Class
789  componentImplementation) throws MissingDependencyException,  componentImplementation) throws CoreException;<br>
 CoreException;<br>  
790  &nbsp;&nbsp;&nbsp; <br>  &nbsp;&nbsp;&nbsp; <br>
791  &nbsp;&nbsp;&nbsp; /**<br>  &nbsp;&nbsp;&nbsp; /**<br>
792  &nbsp;&nbsp;&nbsp;&nbsp; * Creates a specialization of this factory. By  &nbsp;&nbsp;&nbsp;&nbsp; * Creates a specialization of this factory. By
# Line 413  Line 802 
802  delegate all of its behavior to the receiver.<br>  delegate all of its behavior to the receiver.<br>
803  &nbsp;&nbsp;&nbsp;&nbsp; * Changes in the receiver will affect the  &nbsp;&nbsp;&nbsp;&nbsp; * Changes in the receiver will affect the
804  derived factory.<br>  derived factory.<br>
 &nbsp;&nbsp;&nbsp;&nbsp; * @since 3.1<br>  
805  &nbsp;&nbsp;&nbsp;&nbsp; */<br>  &nbsp;&nbsp;&nbsp;&nbsp; */<br>
806  &nbsp;&nbsp;&nbsp; public IMutableContainerFactory  &nbsp;&nbsp;&nbsp; public IMutableContainerFactory
807  createDerivedFactory();<br>  createDerivedFactory();<br>
808  }</code><code></code><br>  }</code><code></code><br>
809  <code></code></div>  <code></code></div>
810  <code></code><br>  <code></code><br>
 Notice that createComponent throws two types of exception. A  
 CoreException indicates a problem with the component itself, and a  
 MissingDependencyException indicates that some other component or  
 adapter could not be found. This can help locate the cause of problems,  
 and a robust extension point may want to disable components that throw  
 CoreExceptions.<br>  
 <br>  
811  All arguments to a component's constructor are provided by its factory.  All arguments to a component's constructor are provided by its factory.
812  Different  Different
813  factories know how to create different types of components or will  factories know how to create different types of components or will
# Line 434  Line 815 
815  different implementations for the same components. All factories are  different implementations for the same components. All factories are
816  derived from the root factory, which is returned by  derived from the root factory, which is returned by
817  Components.getFactory(). A plugin can create derived factories to  Components.getFactory(). A plugin can create derived factories to
818  supply services to one specific extension point. It is also possible to  supply alternative adapter implementations to the components it creates.<br>
819  create a derived factory in order to pass information to the  <br>
820  constructor of one specific object, as we will do in this example. In  In
821  our case, we will create a container factory to pass a specific  our case, we will create a container factory to pass a specific
822  Composite into the constructor of HelloWorldView. The code looks like  Composite into the constructor of HelloWorldView. The code looks like
823  this:<br>  this:<br>
# Line 456  Line 837 
837  <code>IMutableContainerFactory derivedFactory =  <code>IMutableContainerFactory derivedFactory =
838  viewFactory.createDerivedFactory();</code><br>  viewFactory.createDerivedFactory();</code><br>
839  <code></code><br>  <code></code><br>
840  <code>// Add the view's composite as a service instance</code><br>  <code>// Add the view's composite to the factory so that it can be seen
841  <code>derivedFactory.addComponentInstance(viewComposite);</code><br>  by the view constructor<br>
842    </code><code>derivedFactory.addComponentInstance(viewComposite);</code><br>
843  <code></code><br>  <code></code><br>
844  <code>// Add the view's plugin bundle as a service instance (not  <code>// Add the view's plugin bundle to the factory (not
845  required in this example, but this</code><br>  required in this example, but this</code><br>
846  <code>// is recommended practise for any component created from an  <code>// is recommended practise for any component created from an
847  extension point).</code><br>  extension point).</code><br>
# Line 484  Line 866 
866  1. Even if HelloWorldView didn't require a Composite, we would still  1. Even if HelloWorldView didn't require a Composite, we would still
867  have created one (which is wasteful).<br>  have created one (which is wasteful).<br>
868  2. We need to manually dispose the view's composite after we're done  2. We need to manually dispose the view's composite after we're done
869  with it. This defeats the point of IComponent.dispose(), which is  with it. This defeats the point of IContainer.dispose(), which is
870  supposed to clean up all of the component's dependencies automatically.<br>  supposed to clean up all of the component's dependencies automatically.<br>
871  <h2><a class="mozTocH2" name="mozTocId450231"></a>2.3 Creating  <h2><a class="mozTocH2" name="mozTocId450231"></a>2.3 Creating
872  dependent components on demand </h2>  dependent components on demand </h2>
# Line 493  Line 875 
875  a factory would look like this:<br>  a factory would look like this:<br>
876  <br>  <br>
877  <div style="margin-left: 40px;"><code>/**</code><br>  <div style="margin-left: 40px;"><code>/**</code><br>
878  <code>&nbsp;* ServiceAdapter for creating and managing SWT Composites  <code>&nbsp;* ComponentAdapter for creating and managing SWT Composites.</code><br>
 as services.</code><br>  
879  <code>&nbsp;*/</code><br>  <code>&nbsp;*/</code><br>
880  <code>public class CompositeFactory extends ComponentAdapter {</code><br>  <code>public class CompositeFactory extends ComponentAdapter {</code><br>
881  <code></code><br>  <code></code><br>
# Line 510  Line 891 
891  <code>&nbsp;&nbsp;&nbsp; }</code><br>  <code>&nbsp;&nbsp;&nbsp; }</code><br>
892  <code>&nbsp;&nbsp;&nbsp; </code><br>  <code>&nbsp;&nbsp;&nbsp; </code><br>
893  <code>&nbsp;&nbsp;&nbsp; protected Object create(IAdaptable  <code>&nbsp;&nbsp;&nbsp; protected Object create(IAdaptable
894  availableServices) throws CoreException {</code><br>  availableAdapters) throws CoreException {</code><br>
895  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Create a new Composite  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Create a new Composite</code><code></code><br>
 which will be used as a service.</code><br>  
 <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // If we needed any  
 additional</code><br>  
896  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Composite newChild =  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Composite newChild =
897  new Composite(parent, SWT.NONE);</code><br>  new Composite(parent, SWT.NONE);</code><br>
898  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newChild.setLayout(new  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newChild.setLayout(new
# Line 522  Line 900 
900  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return newChild;</code><br>  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return newChild;</code><br>
901  <code>&nbsp;&nbsp;&nbsp; }</code><br>  <code>&nbsp;&nbsp;&nbsp; }</code><br>
902  <code></code><br>  <code></code><br>
903  <code>&nbsp;&nbsp;&nbsp; protected void dispose(Object service) {</code><br>  <code>&nbsp;&nbsp;&nbsp; protected void dispose(Object toDispose) {</code><br>
904  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
905  ((Composite)service).dispose();</code><br>  ((Composite)toDispose).dispose();</code><br>
906  <code>&nbsp;&nbsp;&nbsp; }</code><br>  <code>&nbsp;&nbsp;&nbsp; }</code><br>
907  <code></code><br>  <code></code><br>
908  <code>&nbsp;&nbsp;&nbsp; public String getInterfaceName() {</code><br>  <code>&nbsp;&nbsp;&nbsp; public String getInterfaceName() {</code><br>
909  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Return the fully  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Return the fully
910  qualified class name of the Composite class. The framework will call</code><br>  qualified class name of the Composite class. The framework will call</code><br>
911  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // this method to determine  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // this method to determine
912  what type of service will be constructed by this factory.</code><br>  what type of interface will be implemented by the objects <br>
913    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // constructed by this factory.</code><br>
914  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return  <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return
915  Composite.class.getName();</code><br>  Composite.class.getName();</code><br>
916  <code>&nbsp;&nbsp;&nbsp; }</code><br>  <code>&nbsp;&nbsp;&nbsp; }</code><br>
# Line 549  Line 928 
928  <code>IMutableContainerFactory derivedFactory =  <code>IMutableContainerFactory derivedFactory =
929  viewFactory.createDerivedFactory();</code><br>  viewFactory.createDerivedFactory();</code><br>
930  <code></code><br>  <code></code><br>
931  <code>// Add the view's composite as a service instance</code><br>  <code>// Add a factory that can create the view's composite</code><br>
932  <code>derivedFactory.addComponentFactory(new  <code>derivedFactory.addComponentFactory(new
933  CompositeFactory(parentComposite));</code><br>  CompositeFactory(parentComposite));</code><br>
934  <code></code><br>  <code></code><br>
935  <code>// Add the view's plugin bundle as a service instance (not  <code>// Add the view's plugin bundle to the factory (not
936  required in this example, but this</code><br>  required in this example, but this</code><br>
937  <code>// is recommended practise for any component created from an  <code>// is recommended practise for any component created from an
938  extension point).</code><br>  extension point).</code><br>
# Line 576  Line 955 
955  call to view.dispose().<br>  call to view.dispose().<br>
956  <br>  <br>
957  <code></code>  <code></code>
958  <h2><a class="mozTocH2" name="mozTocId928619"></a>2.4 Declaring Global  <h2><a class="mozTocH2" name="mozTocId928619"></a>2.4 Declaring
959  Services<br>  Component Interfaces</h2>
960  </h2>  The types that a component receives in its constructor are called
961  Services are a type of component that can be used by other components.  component interfaces. Component interfaces are registered through the <span
962  Services are registered through the <span style="font-style: italic;">org.eclipse.ui.component.service   style="font-style: italic;">org.eclipse.core.component.interface</span>
963  </span>extension  extension point, and each has a default implementation. When a
964  point. Services are global in the sense that they are created by  component is
965  factories  created, its parent may provide an implementation of any service
966  that are visible everywhere, however each instance of a services is  it knows about. If the component requests an interface that isn't
967  associated with a specific IContainer. Each service implements a  provided explicitly by the parent, the default implementation is used.<br>
 service interface. Other components can use the service interface in  
 their constructor. When they do so, a new instance of the service will  
 be created for that component which will be managed by the same  
 IContainer. <br>  
968  <br>  <br>
969  Each component supplies an implementation and an interface. Here is an  Here is an
970  example service interface:<br>  example component interface:<br>
971  <code><br>  <code><br>
972  </code>  </code>
973  <div style="margin-left: 40px;"><code>/**</code><br>  <div style="margin-left: 40px;"><code>/**</code><br>
974  <code>&nbsp;* Service interface: </code><br>  <code>&nbsp;* Component interface: </code><br>
975  <code>&nbsp;*</code><br>  <code>&nbsp;*</code><br>
976  <code>&nbsp;* Provides a context for reporting and logging exceptions.</code><br>  <code>&nbsp;* Provides a context for reporting and logging exceptions.</code><br>
977  <code>&nbsp;*/</code><br>  <code>&nbsp;*/</code><br>
# Line 630  Line 1005 
1005  <code></code></div>  <code></code></div>
1006  <code><br>  <code><br>
1007  <br>  <br>
1008  </code>Here is the associated service implementation:<br>  </code>Here is the associated default implementation:<br>
1009  <code><br>  <code><br>
1010  </code>  </code>
1011  <div style="margin-left: 40px;"><code>/**</code><br>  <div style="margin-left: 40px;"><code>/**</code><br>
1012  <code>&nbsp;* Service implementation:</code><br>  <code>&nbsp;* Default implementation of the IErrorContext interface:</code><br>
1013  <code>&nbsp;*</code><br>  <code>&nbsp;*</code><br>
1014  <code>&nbsp;* Creates and logs errors in the context of a plugin bundle</code><br>  <code>&nbsp;* Creates and logs errors in the context of a plugin bundle</code><br>
1015  <code>&nbsp;*/</code><br>  <code>&nbsp;*/</code><br>
1016  <code>public class ErrorContext implements IErrorContext {</code><br>  <code>public class ErrorContext implements IErrorContext {</code><br>
1017  <code>&nbsp;&nbsp;&nbsp; private Bundle pluginBundle;</code><br>  <code>&nbsp;&nbsp;&nbsp; private Bundle pluginBundle;</code><br>
1018  <code></code><br>  <code></code><br>
1019  <code>&nbsp;&nbsp;&nbsp; public ExceptionLoggingService(Bundle  <code>&nbsp;&nbsp;&nbsp; public ErrorContext(Bundle
1020  pluginBundle) {</code><br>  pluginBundle) {</code><br>
1021  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; this.pluginBundle =  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; this.pluginBundle =
1022  pluginBundle;</code><br>  pluginBundle;</code><br>
# Line 679  Line 1054 
1054  Finally, here is the extension markup:<br>  Finally, here is the extension markup:<br>
1055  <br>  <br>
1056  <div style="margin-left: 40px;"><code>&lt;extension  <div style="margin-left: 40px;"><code>&lt;extension
1057  point="org.eclipse.ui.component.service"&gt;</code><br>  point="org.eclipse.core.component.interface"&gt;</code><br>
1058  <code>&nbsp;&nbsp; &lt;service  <code>&nbsp;&nbsp; &lt;interface
1059  </code><br>  </code><br>
1060  <code>&nbsp;&nbsp;&nbsp;&nbsp;  <code>&nbsp;&nbsp;&nbsp;&nbsp;
1061  class="org.eclipse.ui.workbench.ErrorContext"</code><br>  class="org.eclipse.ui.workbench.ErrorContext"</code><br>
1062  <code>&nbsp;&nbsp;&nbsp;&nbsp; </code><code>interface="</code><code>org.eclipse.ui.workbench.IErrorContext</code><code>"</code><code>&gt;</code><br>  <code>&nbsp;&nbsp;&nbsp;&nbsp; </code><code>interface="</code><code>org.eclipse.ui.workbench.IErrorContext</code><code>"<br>
1063  <code>&nbsp;&nbsp; &lt;/service&gt;</code><br>  &nbsp;&nbsp;&nbsp;&nbsp; childadapter="false"<br>
1064    </code><code>&nbsp;&nbsp;&nbsp;&nbsp; scope="plugin"&gt;</code><br>
1065    <code>&nbsp;&nbsp; &lt;/interface&gt;</code><br>
1066  <code>&lt;/extension&gt;</code><br>  <code>&lt;/extension&gt;</code><br>
1067  </div>  </div>
1068  <br>  <br>
# Line 698  Line 1075 
1075  the status messages constructed by the view will be associated with the  the status messages constructed by the view will be associated with the
1076  view's own plugin - not the plugin that defined the ErrorContext  view's own plugin - not the plugin that defined the ErrorContext
1077  service.<br>  service.<br>
1078  <h2><a class="mozTocH2" name="mozTocId749133"></a>2.5 Using services</h2>  <br>
1079  This example shows how a component can use a service.<br>  The <span style="font-style: italic;">scope</span> attribute is a path
1080    indicating how much context is needed to create the service. The <span
1081     style="font-style: italic;">plugin </span>scope indicates that this
1082    service is associated with a plugin, which is why it is allowed to take
1083    a Bundle in its constructor. More on scopes later.<br>
1084    <br>
1085    The <span style="font-style: italic;">childadapter="false" </span>tag
1086    is optional. The default value, false, indicates that a component can
1087    take the interface in its constructor and/or supply an alternative
1088    implementation to its children. If <span style="font-style: italic;">childadapter="true"</span>
1089    were specified, the component would be allowed to implement the
1090    interface or request it from its children. Essentially, this determines
1091    if the interface is intended for top-down or bottom-up communication
1092    between a component and its parent.<br>
1093    <br>
1094    Plugins are not allowed to declare services using interfaces defined in
1095    another plugin. This prevents two plugins from defining a service using
1096    the same interface, and ensures that circular dependencies can only
1097    occur within the same plugin.<br>
1098    <h2><a class="mozTocH2" name="mozTocId749133"></a>2.5 Using Component
1099    Interfaces<br>
1100    </h2>
1101    This example shows how a component can use an interface supplied by its
1102    parent.<br>
1103  <br>  <br>
1104  <div style="margin-left: 40px;"><code>public class MyView {</code><br>  <div style="margin-left: 40px;"><code>public class MyView {</code><br>
1105  <code>&nbsp;&nbsp;&nbsp; private IErrorContext errorContext;</code><br>  <code>&nbsp;&nbsp;&nbsp; private IErrorContext errorContext;</code><br>
# Line 736  Line 1136 
1136  } catch (Exception e) {</code><br>  } catch (Exception e) {</code><br>
1137  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
1138  &nbsp;&nbsp;  &nbsp;&nbsp;
1139  &nbsp;&nbsp; // Log the NPE using the error context service</code><br>  &nbsp;&nbsp; // Log the NPE using the error context</code><br>
1140  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
1141  &nbsp;&nbsp; &nbsp; errorContext.log(e);</code><br>  &nbsp;&nbsp; &nbsp; errorContext.log(e);</code><br>
1142  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
# Line 749  Line 1149 
1149  <code><br>  <code><br>
1150  </code>This view creates a button which, when pressed, will throw a NPE  </code>This view creates a button which, when pressed, will throw a NPE
1151  and log it. The status message will be constructed and logged using the  and log it. The status message will be constructed and logged using the
1152  IErrorContext service we defined above.<br>  IErrorContext interface we defined above. The default implementation of
1153    the interface is associated with a
1154    unique component instance, so if we were to create two instances of
1155    MyView we would also end up with two instances of ErrorContext. <br>
1156    <br>
1157    There
1158    is never any ambiguity about which implementation of IErrorContext to
1159    use. If the parent of MyView explicitly supplies an IErrorContext
1160    service, that implementation is used. Otherwise, the unique default
1161    implementation is used. There can never be two global implementations.<br>
1162  <br>  <br>
1163  <h2><a class="mozTocH2" name="mozTocId705695"></a>2.6 Lifecycle</h2>  <h2><a class="mozTocH2" name="mozTocId705695"></a>2.6 Lifecycle</h2>
1164  Many components need to do explicit cleanup. Components  Many components need to do explicit cleanup. Components
# Line 829  Line 1238 
1238  <code>&nbsp;&nbsp;&nbsp; /**</code><br>  <code>&nbsp;&nbsp;&nbsp; /**</code><br>
1239  <code>&nbsp;&nbsp;&nbsp;&nbsp; * This method will automatically be  <code>&nbsp;&nbsp;&nbsp;&nbsp; * This method will automatically be
1240  called  called
1241  when the component that uses this service is disposed.</code><br>  when the component that uses this adapter is disposed.</code><br>
1242  <code>&nbsp;&nbsp;&nbsp;&nbsp; * It should clean up anything that has  <code>&nbsp;&nbsp;&nbsp;&nbsp; * It should clean up anything that has
1243  been  been
1244  allocated by the service.</code><br>  allocated by the service.</code><br>
# Line 850  Line 1259 
1259  <code></code></div>  <code></code></div>
1260  <code></code><br>  <code></code><br>
1261  Similarly, components may implement the IDisposable interface. A  Similarly, components may implement the IDisposable interface. A
1262  component that implements IDisposable will be disposed before any of  component that implements IDisposable will be disposed before the
1263  its services, as shown by the following example:<br>  objects it depends on, as shown by the following example:<br>
1264  <br>  <br>
1265  <div style="margin-left: 40px;"><code>public LifecycleService  <div style="margin-left: 40px;"><code>public LifecycleService
1266  implements IDisposable {</code><br>  implements IDisposable {</code><br>
# Line 882  Line 1291 
1291  <code>}</code><br>  <code>}</code><br>
1292  <code></code><br>  <code></code><br>
1293  </div>  </div>
1294  Finally, we could execute the following code to trace when the service  Finally, we could execute the following code to trace when the
1295  is created and destroyed:<br>  LifecycleService is created and destroyed:<br>
1296  <div style="margin-left: 40px;"><br>  <div style="margin-left: 40px;"><br>
1297  IMutableContainerFactory factory =  IMutableContainerFactory factory =
1298  Components.getFactory().createDerivedFactory();<br>  Components.getFactory().createDerivedFactory();<br>
# Line 923  Line 1332 
1332  LifecycleService destroyed<br>  LifecycleService destroyed<br>
1333  <br>  <br>
1334  </div>  </div>
1335  <h2><a class="mozTocH2" name="mozTocId543223"></a>2.7 Dynamic Services</h2>  <h2><a class="mozTocH2" name="mozTocId543223"></a>2.7 Dynamic Interfaces<br>
1336  Global service factories are dynamic in the sense that they come and go  </h2>
1337  as plugins are installed or uninstalled. If a plugin providing a  Component interfaces are dynamic in the sense that they may be
1338  service is uninstalled, a new implementation is selected from a  registered or unregistered as their plugins are installed or
1339  different plugin. If no other plugin provides that service, the service  uninstalled. If a plugin providing component interface is uninstalled,
1340  becomes unavailable and it will not be possible to construct components  that interface will become unavailable and it will no longer be
1341  that use it.<br>  possible to construct objects that depend on the interface.<br>
1342  <br>  <br>
1343  Service instances themselves are not dynamic. Once a service is  The objects instances themselves are not dynamic. Once an adapter is
1344  created, it will exist for as long as the component it was created for.  created to supply an interface, it will exist for as long as the
1345  Even if the a plugin stops providing a service, all instances of that  component it was created for.
1346  service will continue to exist until disposed. All services used by a  Even if the a plugin stops providing an interface, all instances of
1347    that
1348    interface will continue to exist until disposed. All interfaces used by
1349    a
1350  component will be created before that component, so components do not  component will be created before that component, so components do not
1351  need to query for the existence of services or to wait for services  need to query for the existence of services or to wait for services
1352  that will be created after-the-fact. <br>  that will be created after-the-fact. <br>
1353  <br>  <h2><a class="mozTocH2" name="mozTocId886834"></a>2.8 Optional Interface<br>
 Plugins that need more advanced dynamic support should use OSGI  
 services. The component framework is not intended as a replacement for  
 OSGI, and there is no point in reimplmenting things that OSGI already  
 does well.<br>  
 <h2><a class="mozTocH2" name="mozTocId886834"></a>2.8 Optional Services<br>  
1354  </h2>  </h2>
1355  Sometimes a component does not require a service but can make use of it  Sometimes a component does not require an interface but can make use of
1356  service if it exists. This should usually be handled by explicitly  it if it exists. This is normally not necessary for any interface
1357  creating an empty global implementation of the service, but sometimes  registered through the <code>org.eclipse.core.component.interface</code>
1358  it is more efficient to have the component explicitly check if the  extension point since the default implementation will guarantee that
1359  service exists. This can be done by taking an argument of type  the interface always exists even if the parent context doesn't know
1360    about it. However, this situation can occur if a parent and child are
1361    communicating with an interface that wasn't originally intended for use
1362    as a component interface, or if the child requires a variable set of
1363    interfaces.<br>
1364    <br>
1365    Note: this pattern doesn't actually allow the component to be used in a
1366    wider context, but it does allow the component to request interfaces
1367    that aren't registered by the normal means.<br>
1368    <br>
1369    This can be done by taking an argument of type
1370  IAdaptable, like this:<br>  IAdaptable, like this:<br>
1371  <br>  <br>
1372  <div style="margin-left: 40px;"><code>/**<br>  <div style="margin-left: 40px;"><code>public interface INameService {<br>
1373    &nbsp;&nbsp;&nbsp; public String getName();<br>
1374    }<br>
1375    <br>
1376    <br>
1377    /**<br>
1378  &nbsp;* A component with no dependencies, but which can optionally  &nbsp;* A component with no dependencies, but which can optionally
1379  accept an IMemento for initialization.<br>  accept an IMemento for initialization.<br>
1380  &nbsp;*/<br>  &nbsp;*/<br>
# Line 960  Line 1382 
1382  <br>  <br>
1383  &nbsp;&nbsp;&nbsp; String myName = "default name";<br>  &nbsp;&nbsp;&nbsp; String myName = "default name";<br>
1384  <br>  <br>
1385  &nbsp;&nbsp;&nbsp; public MyComponent(IAdaptable optionalServices) {<br>  &nbsp;&nbsp;&nbsp; public MyComponent(IAdaptable optionalInterfaces) {<br>
1386  <br>  <br>
1387  </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Check if an IMemento  </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Check if an
1388    INameService
1389  service exists.</code><br>  service exists.</code><br>
1390  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; IMemento memento =  <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; INameService nameService =
1391  (IMemento)optionalServices.getAdapter(IMemento.class);<br>  (INameService)optionalInterfaces.getAdapter(INameService.class);<br>
1392  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br>  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br>
1393  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (memento != null) {<br>  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (memento != null) {<br>
1394  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; String name =  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; myName =
1395  memento.getString("name");<br>  nameService.getName();<br>
 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; if (name != null) {<br>  
 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; myName = name;<br>  
 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; }<br>  
1396  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
1397  <br>  <br>
1398  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("created component  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("created component
# Line 985  Line 1405 
1405  <br>  <br>
1406  <div style="margin-left: 40px;"><code>// Create a memento with the name  <div style="margin-left: 40px;"><code>// Create a memento with the name
1407  "custom name"<br>  "custom name"<br>
1408  IMemento memento = XMLMemento.createWriteRoot("test");<br>  INameService nameService = new INameService() {<br>
1409  memento.putString("name", "custom name");<br>  &nbsp;&nbsp;&nbsp; public String getName() {<br>
1410    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return "custom name";<br>
1411    &nbsp;&nbsp;&nbsp; }<br>
1412    }<br>
1413  <br>  <br>
1414  // Create a factory which knows about our memento<br>  // Create a factory which knows about our memento<br>
1415  IMutableContainerFactory context =  IMutableContainerFactory context =
1416  Components.getFactory().createDerivedFactory();<br>  Components.getFactory().createDerivedFactory();<br>
1417  context.addComponentInstance(memento);<br>  context.addComponentInstance(nameService);<br>
1418  <br>  <br>
1419  // Use the factory to instantiate MyComponent<br>  // Use the factory to instantiate MyComponent<br>
1420  IContainer component = context.createContainer(MyComponent.class);<br>  IContainer component = context.createContainer(MyComponent.class);<br>
# Line 999  Line 1422 
1422  component.dispose();</code><br>  component.dispose();</code><br>
1423  <br>  <br>
1424  </div>  </div>
1425  We can also create the component without the optional IMemento:<br>  We can also create the component without the optional INameService:<br>
1426  <br>  <br>
1427  <div style="margin-left: 40px;"><code>IContainer component =  <div style="margin-left: 40px;"><code>IContainer component =
1428  Components.getFactory().createContainer(MyComponent.class);<br>  Components.getFactory().createContainer(MyComponent.class);<br>
# Line 1007  Line 1430 
1430  component.dispose();</code><code></code><br>  component.dispose();</code><code></code><br>
1431  </div>  </div>
1432  <br>  <br>
 WARNING: This pattern should be used with care since it adds special  
 cases to the component code. It is mainly inteded for situations where  
 a component requires an open-ended set of services or where it is not  
 possible to offer a default implementation of a service.<br>  
1433  <br>  <br>
1434  <h2><a class="mozTocH2" name="mozTocId163729"></a>2.9 Multiplexing  <span style="font-weight: bold;">WARNING: </span>This pattern should
1435  services</h2>  be used with care since it adds special
1436    cases to the component code. It is mainly inteded for advanced
1437    situations where a component needs to request an interface that isn't
1438    normally visible in its scope.<br>
1439    <br>
1440    The preferred method of dealing with missing interfaces is to provide a
1441    default implementation, like this:<br>
1442    <br>
1443    <div style="margin-left: 40px;"><code>&lt;extension
1444    point="</code><code>org.eclipse.core.component.interface</code><code>"&gt;</code><br>
1445    <code>&nbsp;&nbsp; &lt;interface
1446    </code><br>
1447    <code>&nbsp;&nbsp;&nbsp;&nbsp;
1448    class="org.eclipse.ui.DefaultNameService"</code><br>
1449    <code>&nbsp;&nbsp;&nbsp;&nbsp; </code><code>interface="</code><code>org.eclipse.ui.INameService</code><code>"</code><code>&gt;</code><br>
1450    <code>&nbsp;&nbsp; &lt;/interface&gt;</code><br>
1451    <code>&lt;/extension&gt;<br>
1452    <br>
1453    <br>
1454    /**<br>
1455    &nbsp;* Default implementation of INameService that will be used if the
1456    parent doesn't explicitly provide one<br>
1457    &nbsp;*/<br>
1458    class NameService implements INameService {<br>
1459    </code><code>&nbsp;&nbsp;&nbsp; public String getName() {<br>
1460    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return "default name";<br>
1461    &nbsp;&nbsp;&nbsp; }<br>
1462    </code><code>}<br>
1463    <br>
1464    </code><code>/**<br>
1465    &nbsp;* A component with no dependencies, but which can optionally
1466    accept an INameService for initialization.<br>
1467    &nbsp;*/<br>
1468    public class MyComponent {<br>
1469    <br>
1470    &nbsp;&nbsp;&nbsp; String myName;<br>
1471    <br>
1472    &nbsp;&nbsp;&nbsp; public MyComponent(INameService nameService) {<br>
1473    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; myName = nameService.getName();<br>
1474    </code><code></code><code><br>
1475    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("created component
1476    with name = " + myName);<br>
1477    &nbsp;&nbsp;&nbsp; }<br>
1478    }</code><code><br>
1479    </code></div>
1480    <br>
1481    With this approach, it is still possible to create a MyComponent with
1482    or without an INameService, but the special-case code for handling
1483    missing interfaces is written once inside the default implementation
1484    rather than many times inside each component that uses
1485    the interface.<br>
1486    <h2><a class="mozTocH2" name="mozTocId578639"></a>2.8 Component Scopes</h2>
1487    Scopes are a way to determine what interfaces can be used in the
1488    constructor of a component. At some point, a programmer is going to ask
1489    "What interfaces am I allowed to pass into the constructor of my view?"
1490    Ultimately, this could be determined by examining the dependencies
1491    between each service, but it is not reasonable to expect a programmer
1492    to have this level of knowledge of the dependencies between services.<br>
1493    <br>
1494    Scopes limit the dependencies between services in order to make this
1495    question easier to answer. For example, views are allowed to use any
1496    service in the "/plugin/part/view" scope. This makes it easy to write a
1497    PDE extension which displays the list of interfaces available to a
1498    views. <br>
1499    <br>
1500    The only difference between scopes is how much context the components
1501    are allowed to expect. For example, components in the <span
1502     style="font-style: italic;">plugin</span> scope will be given a plugin
1503    Bundle and components in the <span style="font-style: italic;">plugin/part</span>
1504    scope need to be associated with a particular SWT Composite. Components
1505    may depend on services in the same scope or in a
1506    more general scope. It is still possible for Components to reference
1507    services in a more specific scope, but they must do so as an optional
1508    interface (as described in section 2.7).<span
1509     style="font-style: italic;"></span><br>
1510    <br>
1511    Eclipse defines the following standard scopes.<br>
1512    <br>
1513    <table style="width: 100%; text-align: left;" border="1" cellpadding="2"
1514     cellspacing="2">
1515      <tbody>
1516        <tr>
1517          <td style="vertical-align: top;">Scope path<br>
1518          </td>
1519          <td style="vertical-align: top;">Required context<br>
1520          </td>
1521          <td style="vertical-align: top;">Description<br>
1522          </td>
1523        </tr>
1524        <tr>
1525          <td style="vertical-align: top;">/<br>
1526          </td>
1527          <td style="vertical-align: top;">None<br>
1528          </td>
1529          <td style="vertical-align: top;">Any service that omits the <span
1530     style="font-style: italic;">scope</span> attribute automatically
1531    belongs to the global scope. Services in the global scope can be used
1532    by any other component, but may only depend on other global services.
1533    Global services are not given any context from the application.<br>
1534          </td>
1535        </tr>
1536        <tr>
1537          <td style="vertical-align: top;">/plugin<br>
1538          </td>
1539          <td style="vertical-align: top;">Bundle<br>
1540          </td>
1541          <td style="vertical-align: top;">Components in the /plugin scope
1542    are created in the context of a plugin bundle. All executable
1543    extensions (any component created using an extension point) belong to
1544    the plugin scope. Components in this scope can reference their own
1545    plugin Bundle in their constructor. Services can reference the Bundle
1546    associated with the component that requested them.<br>
1547          </td>
1548        </tr>
1549        <tr>
1550          <td style="vertical-align: top;">/plugin/part<br>
1551          </td>
1552          <td style="vertical-align: top;">Bundle, Composite<br>
1553          </td>
1554          <td style="vertical-align: top;">Components in the /plugin/part
1555    scope are associated with an SWT Composite. Components in this scope
1556    are given their
1557    own SWT Composite. They may change the layout on the given Composite,
1558    but may not change its layout data. The composite will be managed as a
1559    service, so the component does not need to dispose it. Components in
1560    this scope may be used as editors, views, or both.<br>
1561          </td>
1562        </tr>
1563        <tr>
1564          <td style="vertical-align: top;">/plugin/part/view<br>
1565          </td>
1566          <td style="vertical-align: top;">Bundle,<br>
1567    Composite,<br>
1568    IWorkbenchPage<br>
1569          </td>
1570          <td style="vertical-align: top;">All views belong to this scope.
1571    They are given the IConfigurationElement containing their extension
1572    markup, and an IWorkbenchPage.<br>
1573          </td>
1574        </tr>
1575        <tr>
1576          <td style="vertical-align: top;">/plugin/part/editor<br>
1577          </td>
1578          <td style="vertical-align: top;">Bundle,<br>
1579    Composite,<br>
1580    IWorkbenchPage,<br>
1581    IEditorInput<br>
1582          </td>
1583          <td style="vertical-align: top;">All editors belong to this
1584    scope. They are given the IConfigurationElement containing their
1585    extension markup, an IWorkbenchPage, and the IEditorInput containing
1586    their input.<br>
1587          </td>
1588        </tr>
1589      </tbody>
1590    </table>
1591    <br>
1592    These scopes should be sufficient for most situations. However, some
1593    plugins may wish to create new scopes in order to pass additional
1594    context to the objects in an extension point they provided.<br>
1595    <br>
1596    Any plugin that defines its own scopes must include its fully qualified
1597    plugin ID as part of the scope path. For example, if the plugin
1598    org.eclipse.myplugin extends the /plugin/part/editor scope, the new
1599    scope name would look like
1600    /plugin/part/editor/org.eclipse.myplugin.scopename. All scope paths
1601    that do not contain a period (.) are reserved by the framework.<br>
1602    <br>
1603    It is never a breaking change to move a service into a more general
1604    scope. However, it is always a breaking change to move a service into a
1605    more specific scope. A service interface may only exist in one scope.<br>
1606    <h2><a class="mozTocH2" name="mozTocId762751"></a>2.9 Shared Adapters</h2>
1607    Normally, a new instance of a default interface implementation is
1608    created for each component that requests it. This allows the adapter to
1609    keep some state associated with the component and to clean up resources
1610    once they are no longer needed by the component. However, some
1611    interface do not need any state or expose any API that could be used to
1612    create a leak. For example, the IErrorContext interface in section 2.4
1613    could safely share one instance between all components in the same
1614    plugin. In order to reduce memory consumption, the component API should
1615    support the notion of a shared adapter. A shared adapter will be reused
1616    in the broadest possible context permitted by its scope. For example,
1617    an adapter for an interface in the global scope would become a
1618    singleton, shared adapters in the plugin scope will have at most one
1619    instance per plugin, and the shared flag will be ignored in the
1620    /plugin/part scope.<br>
1621    <br>
1622    This is intended as a future optimization, and will not be included in
1623    the initial version of the component framework<br>
1624    <br>
1625    <h1><a class="mozTocH1" name="mozTocId707022"></a>3.0 Views and Editors
1626    as Components</h1>
1627    This section describes how the workbench uses the component framework
1628    to create editors and views.<br>
1629    <br>
1630    <h2><a class="mozTocH2" name="mozTocId125361"></a>3.1 Interfaces
1631    offered by the workbench</h2>
1632    Parent interfaces: (Interfaces given to a component as arguments in its
1633    constructor)<br>
1634    <br>
1635    <table style="width: 100%; text-align: left;" border="1" cellpadding="2"
1636     cellspacing="2">
1637      <tbody>
1638        <tr>
1639          <td style="vertical-align: top;">Scope<br>
1640          </td>
1641          <td style="vertical-align: top;">Interface<br>
1642          </td>
1643          <td style="vertical-align: top;">Description<br>
1644          </td>
1645        </tr>
1646        <tr>
1647          <td style="vertical-align: top;">/plugin<br>
1648          </td>
1649          <td style="vertical-align: top;">IErrorContext<br>
1650          </td>
1651          <td style="vertical-align: top;">Provides facilities for logging
1652    exceptions<br>
1653          </td>
1654        </tr>
1655        <tr>
1656          <td style="vertical-align: top;">/plugin<br>
1657          </td>
1658          <td style="vertical-align: top;">ISwtResources<br>
1659          </td>
1660          <td style="vertical-align: top;">Provides facilities for
1661    allocating SWT resources such as Fonts, Images, and Colors<br>
1662          </td>
1663        </tr>
1664        <tr>
1665          <td style="vertical-align: top;">/<br>
1666          </td>
1667          <td style="vertical-align: top;">INameable<br>
1668          </td>
1669          <td style="vertical-align: top;">Parts can use this service to
1670    change their name, content description, title image, and tooltip. The
1671    default implementation ignores all method calls.<br>
1672          </td>
1673        </tr>
1674        <tr>
1675          <td style="vertical-align: top;">/<br>
1676          </td>
1677          <td style="vertical-align: top;">IMemento<br>
1678          </td>
1679          <td style="vertical-align: top;">Parts will receive a memento
1680    which they can use to load previously-saved state<br>
1681          </td>
1682        </tr>
1683        <tr>
1684          <td style="vertical-align: top;">/plugin<br>
1685          </td>
1686          <td style="vertical-align: top;">IPartFactory<br>
1687          </td>
1688          <td style="vertical-align: top;">Interface that can be used to
1689    create child views, editors, and other UI parts<br>
1690          </td>
1691        </tr>
1692        <tr>
1693          <td style="vertical-align: top;">/plugin/part<br>
1694          </td>
1695          <td style="vertical-align: top;">IActionBars2<br>
1696          </td>
1697          <td style="vertical-align: top;">Interface used to add to the
1698    toolbar, cool bar, etc. Currently exposed on the view site.<br>
1699          </td>
1700        </tr>
1701        <tr>
1702          <td style="vertical-align: top;"><br>
1703          </td>
1704          <td style="vertical-align: top;"><br>
1705          </td>
1706          <td style="vertical-align: top;"><br>
1707          </td>
1708        </tr>
1709      </tbody>
1710    </table>
1711    <br>
1712    Child interfaces: (Services that a component offers to its parent -
1713    either by implementing directly or as an adapter)<br>
1714    <br>
1715    <table style="text-align: left; width: 1550px; height: 88px;" border="1"
1716     cellpadding="2" cellspacing="2">
1717      <tbody>
1718        <tr>
1719          <td style="vertical-align: top;">Scope<br>
1720          </td>
1721          <td style="vertical-align: top;">Interface<br>
1722          </td>
1723          <td style="vertical-align: top;">Description<br>
1724          </td>
1725        </tr>
1726        <tr>
1727          <td style="vertical-align: top;">/plugin/part<br>
1728          </td>
1729          <td style="vertical-align: top;">IFocusable<br>
1730          </td>
1731          <td style="vertical-align: top;">Parts can implement this service
1732    to allow their parent<br>
1733          </td>
1734        </tr>
1735        <tr>
1736          <td style="vertical-align: top;">/<br>
1737          </td>
1738          <td style="vertical-align: top;">IMultiPart<br>
1739          </td>
1740          <td style="vertical-align: top;">Parts should implement this if
1741    they contain other parts and have the notion of an "active" child.
1742    Other services can use this service if their default implementation
1743    should redirect to the active child.<br>
1744          </td>
1745        </tr>
1746        <tr>
1747          <td style="vertical-align: top;">/<br>
1748          </td>
1749          <td style="vertical-align: top;">IPersistable<br>
1750          </td>
1751          <td style="vertical-align: top;">Parts may implement this
1752    interface if they wish to save their state between sessions.<br>
1753          </td>
1754        </tr>
1755        <tr>
1756          <td style="vertical-align: top;"><br>
1757          </td>
1758          <td style="vertical-align: top;"><br>
1759          </td>
1760          <td style="vertical-align: top;"><br>
1761          </td>
1762        </tr>
1763      </tbody>
1764    </table>
1765    <br>
1766    <br>
1767    <h3><a class="mozTocH2" name="mozTocId163729"></a>3.1.1 IMultiPart:
1768    Redirecting
1769    adapters from the active child<br>
1770    </h3>
1771  In UI code, it is common to create aggregate components that have an  In UI code, it is common to create aggregate components that have an
1772  "active" child. Many of the adapters that the aggregate offers its  "active" child. This section suggests a general pattern for redirecting
1773  parent will redirect their implementation to the active child. We refer  components in this way. Many of the adapters that the aggregate offers
1774  to this as "multiplexing" the service. The aggregate itself will know  its
1775    parent will redirect their implementation to the active child. The
1776    aggregate itself will know
1777  how to select its active child, but it may not know about all the  how to select its active child, but it may not know about all the
1778  services that need to be multiplexed. The default implementation of a  interfaces that need to be redirected in this manner. The default
1779  service determines how and if it should be multiplexed.<br>  implementation of an interface determines how it should be redirected.<br>
1780  <br>  <br>
1781  This can be explained better using a concrete example. Workbench parts  This can be shown using a concrete example. Workbench parts
1782  offer an IFocusable adapter to their parent that allows their parent to  offer an IFocusable adapter to their parent that allows their parent to
1783  give them focus. <br>  give them focus. <br>
1784  <br>  <br>
# Line 1045  Line 1801 
1801  implement the IFocusable interface, it should redirect focus to its  implement the IFocusable interface, it should redirect focus to its
1802  active child. If the part doesn't have an active child, focus should go  active child. If the part doesn't have an active child, focus should go
1803  directly to the part's main control. To supply this default behavior,  directly to the part's main control. To supply this default behavior,
1804  we provide an implementation of IFocusable as a global service:<br>  we provide a default implementation of IFocusable:<br>
1805  <br>  <br>
1806  <code></code>  <code></code>
1807  <div style="margin-left: 40px;"><code>/**<br>  <div style="margin-left: 40px;"><code>/**<br>
# Line 1057  Line 1813 
1813  public class DefaultFocusable implements IFocusable {<br>  public class DefaultFocusable implements IFocusable {<br>
1814  <br>  <br>
1815  &nbsp;&nbsp;&nbsp; private Composite control;<br>  &nbsp;&nbsp;&nbsp; private Composite control;<br>
1816  &nbsp;&nbsp;&nbsp; private IMultiplexer activePart;<br>  &nbsp;&nbsp;&nbsp; private IMultiPart activePart;<br>
1817  &nbsp;&nbsp;&nbsp; <br>  &nbsp;&nbsp;&nbsp; <br>
1818  &nbsp;&nbsp;&nbsp; /**<br>  &nbsp;&nbsp;&nbsp; /**<br>
1819  &nbsp;&nbsp;&nbsp; &nbsp;* Creates the default implementation of  &nbsp;&nbsp;&nbsp; &nbsp;* Creates the default implementation of
1820  IFocusable, given the main control<br>  IFocusable, given the main control<br>
1821  &nbsp;&nbsp;&nbsp; &nbsp;* of the part and an IMultiplexer that can be  &nbsp;&nbsp;&nbsp; &nbsp;* of the part and an IMultiPart that can be
1822  queried for the active child.<br>  queried for the active child.<br>
1823  &nbsp;&nbsp;&nbsp; &nbsp;* <br>  &nbsp;&nbsp;&nbsp; &nbsp;* <br>
1824  &nbsp;&nbsp;&nbsp; &nbsp;* @param toGiveFocus main control of the pane<br>  &nbsp;&nbsp;&nbsp; &nbsp;* @param toGiveFocus main control of the pane<br>
# Line 1070  Line 1826 
1826  returns the active part<br>  returns the active part<br>
1827  &nbsp;&nbsp;&nbsp; &nbsp;*/<br>  &nbsp;&nbsp;&nbsp; &nbsp;*/<br>
1828  &nbsp;&nbsp;&nbsp; public DefaultFocusable(Composite toGiveFocus,  &nbsp;&nbsp;&nbsp; public DefaultFocusable(Composite toGiveFocus,
1829  IMultiplexer activePartProvider) {<br>  IMultiPart activePartProvider) {<br>
1830  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; control = toGiveFocus;<br>  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; control = toGiveFocus;<br>
1831  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; activePart = activePartProvider;<br>  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; activePart = activePartProvider;<br>
1832  &nbsp;&nbsp;&nbsp; }<br>  &nbsp;&nbsp;&nbsp; }<br>
# Line 1106  Line 1862 
1862  }</code><br>  }</code><br>
1863  <br>  <br>
1864  </div>  </div>
1865  Here is the XML markup to register the service:<br>  Here is the XML markup to register the interface:<br>
1866  <br>  <br>
1867  <div style="margin-left: 40px;"><code>&lt;service<br>  <div style="margin-left: 40px;"><code>&lt;service<br>
1868  &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
1869  interface="org.eclipse.ui.workbench.services.IFocusable"<br>  interface="org.eclipse.ui.workbench.services.IFocusable"<br>
1870  &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
1871  class="org.eclipse.ui.internal.part.serviceimplementation.DefaultFocusable"/&gt;</code><code></code><br>  class="org.eclipse.ui.internal.part.serviceimplementation.DefaultFocusable<br>
1872    &nbsp;&nbsp;&nbsp; childadapter="true"<br>
1873    &nbsp;&nbsp;&nbsp; scope="plugin/part"/&gt;</code><code></code><br>
1874  </div>  </div>
1875  <br>  <br>
1876  All of the services we have looked at so far have been offered by a  All of the interfaces we have looked at so far have been offered by a
1877  parent for use in a child's constructor. In this case, the service is  parent for use in a child's constructor. In this case, the interface is
1878  offered as an adapter on the child to be used by the parent. In both  offered as an adapter on the child to be used by the parent. In both
1879  cases, the service is declared in the same way. Any service that  cases, we support the notion of a default implementation that is
1880  supports multiplexing takes an IMultiplexer in its constructor. If the  declared through XML. Any service that should be redirected based on
1881  part does not support multiplexing, the IMultiplexer will always  the active child will take IMultiPart in its constructor. Here is an
1882  returns null from getCurrent. Here is an example part that supports  example part that supports
1883  multiplexing:<br>  multiplexing:<br>
1884  <code><br>  <code><br>
1885  </code>  </code>
# Line 1166  Line 1924 
1924  &nbsp;&nbsp;&nbsp; private IContainer page1;<br>  &nbsp;&nbsp;&nbsp; private IContainer page1;<br>
1925  &nbsp;&nbsp;&nbsp; private IContainer page2;<br>  &nbsp;&nbsp;&nbsp; private IContainer page2;<br>
1926  <br>  <br>
1927  &nbsp;&nbsp;&nbsp; // Helper class that implements the IMultiplexer  &nbsp;&nbsp;&nbsp; // Helper class that implements the IMultiPart
1928  interface<br>  interface<br>
1929  &nbsp;&nbsp;&nbsp; private Multiplexer multiplexer = new Multiplexer();<br>  &nbsp;&nbsp;&nbsp; private Multiplexer multiplexer = new Multiplexer();<br>
1930  &nbsp;&nbsp;&nbsp; private Button checkBox;<br>  &nbsp;&nbsp;&nbsp; private Button checkBox;<br>
# Line 1265  Line 2023 
2023  viewContainer.dispose();<br>  viewContainer.dispose();<br>
2024  </code><code></code></div>  </code><code></code></div>
2025  <code>&nbsp;&nbsp;&nbsp; <br>  <code>&nbsp;&nbsp;&nbsp; <br>
2026  </code>This example also shows how the same service can work for both  </code>This example also shows how the same default implementation can
2027    work for both
2028  multiplexing and non-multiplexing parts. The Page2 class doesn't  multiplexing and non-multiplexing parts. The Page2 class doesn't
2029  implement IFocusable or IMultiplexing part, but we are still able to  implement IFocusable or IMultiPart, but we are still able to
2030  ask for an IFocusable interface and use it to give focus to the part.<br>  ask for an IFocusable interface and use it to give focus to the part.<br>
2031  <h1><a class="mozTocH1" name="mozTocId707022"></a>3.0 Views and Editors  <span style="font-weight: bold;"><br>
2032  as Components</h1>  </span><span style="font-weight: bold;"></span>
2033  TODO<br>  <h3><a class="mozTocH3" name="mozTocId483376"></a>3.1.2 INameable:
2034    Changing the name of a part</h3>
2035    In order to change their name, existing parts need to implement a set
2036    of get methods, maintain a listener list, and send notifications when
2037    their name changes. Component-based parts will change their name by
2038    using an INameable interface provided by their parent. INameable looks
2039    like this:<br>
2040  <br>  <br>
2041    <div style="margin-left: 40px;"><code>public interface INameable {<br>
2042    &nbsp;&nbsp;&nbsp; public void setName(String newName);<br>
2043    &nbsp;&nbsp;&nbsp; public void setContentDescription(String
2044    contentDescription);<br>
2045    &nbsp;&nbsp;&nbsp; public void setImage(Image theImage);<br>
2046    &nbsp;&nbsp;&nbsp; public void setTooltip(String toolTip);<br>
2047    }<br>
2048    <br>
2049    </code></div>
2050    For example, a view could set its name like this:<br>
2051    <br>
2052    <div style="margin-left: 40px;"><code>public class MyView {<br>
2053    &nbsp;&nbsp;&nbsp; public MyView(Composite parent, INameable name) {<br>
2054    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; name.setName("Some tab text");<br>
2055    &nbsp;&nbsp;&nbsp; }<br>
2056    }<br>
2057  <br>  <br>
2058    </code></div>
2059    If a parent cares about the names of its children, it should provide an
2060    implementation of INameable that reacts when the child changes its
2061    name. Otherwise, the child will be given a default implementation of
2062    INameable that ignores all method calls. This eliminates the need to
2063    attach listeners to views.<br>
2064    <h3><a class="mozTocH3" name="mozTocId969580"></a>3.1.3 IPartFactory:
2065    Creating child parts<br>
2066    </h3>
2067    Any part that wants to create other nested parts would use an
2068    IPartFactory interface.<br>
2069    <br>
2070    <div style="margin-left: 40px;"><code>public interface IPartFactory {<br>
2071    &nbsp;&nbsp;&nbsp; public IContainer createView(String viewId,
2072    Composite parentComposite, IWorkbenchPage page, IContainerFactory
2073    services);<br>
2074    &nbsp;&nbsp;&nbsp; public IContainer createEditor(String editorId,
2075    Composite parentComposite, IWorkbenchPage page, </code><code>IEditorInput
2076    input, </code><code>IContainerFactory services);<br>
2077    &nbsp;&nbsp;&nbsp; public IContainer createPart(String partId,
2078    Composite parentComposite, IContainerFactory services);<br>
2079    }</code><br>
2080    <br>
2081    <br>
2082    </div>
2083    <div style="margin-left: 40px;"><code></code><code></code></div>
2084    <span style="font-weight: bold;"></span>
2085  </body>  </body>
2086  </html>  </html>

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2