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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (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>Component Framework proposal</title>
7 :     </head>
8 :     <body>
9 :     <span style="font-weight: bold;"></span>
10 :     <br>
11 :     <div style="text-align: center;"><font size="+3"><span
12 :     style="font-weight: bold;">Component Framework Proposal</span></font><br>
13 :     </div>
14 :     <br>
15 :     <div style="text-align: center;">Revision 1.0.3<br>
16 :     By Stefan Xenos and Nick Edgar<br>
17 :     Last modified 2004/11/02<br>
18 :     </div>
19 :     <br>
20 :     <br>
21 :     <br>
22 :     <font size="+3"><span style="font-weight: bold;">Table of Contents</span></font><br>
23 :     <ul id="mozToc">
24 :     <!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId511305">1.0
25 :     Introduction
26 :     </a>
27 :     <ul>
28 :     <li><a href="#mozTocId29093">1.1 Robustness / leak proofing
29 :     </a></li>
30 :     <li><a href="#mozTocId223982">1.2 Nesting of components</a></li>
31 :     <li><a href="#mozTocId634024">1.3 Creating parts outside the
32 :     workbench</a></li>
33 :     <li><a href="#mozTocId800379">1.4 Scalability</a></li>
34 :     <li><a href="#mozTocId866479">1.5 Ease of use
35 :     </a></li>
36 :     </ul>
37 :     </li>
38 :     <li><a href="#mozTocId416167">2.0 Component Framework
39 :     </a>
40 :     <ul>
41 :     <li><a href="#mozTocId489102">2.1 Instantiating a view
42 :     </a></li>
43 :     <li><a href="#mozTocId717633">2.2 Instantiating components in
44 :     general
45 :     </a></li>
46 :     <li><a href="#mozTocId450231">2.3 Creating dependent components
47 :     on demand </a></li>
48 :     <li><a href="#mozTocId928619">2.4 Declaring Global Services
49 :     </a></li>
50 :     <li><a href="#mozTocId749133">2.5 Using services</a></li>
51 :     <li><a href="#mozTocId705695">2.6 Lifecycle</a></li>
52 :     <li><a href="#mozTocId543223">2.7 Dynamic Services</a></li>
53 :     <li><a href="#mozTocId886834">2.8 Optional Services</a></li>
54 :     <li><a href="#mozTocId163729">2.9 Multiplexing services</a></li>
55 :     </ul>
56 :     </li>
57 :     <li><a href="#mozTocId707022">3.0 Views and Editors as Components</a></li>
58 :     </ul>
59 :     <br>
60 :     <h1><a class="mozTocH1" name="mozTocId511305"></a>1.0 Introduction<br>
61 :     </h1>
62 :     This proposal outlines a framework for managing complex executable
63 :     extensions. This framework is a first step toward allowing views and
64 :     editors to be combined recursively, and created inside arbitrary SWT
65 :     composites. Although it is intended for creating reusable UI
66 :     components, the framework is useful for any extension point that
67 :     creates complicated Java objects. For this reason, we will refer to the
68 :     objects being created as "components" even though our components are
69 :     typically views and editors.<br>
70 :     <br>
71 :     This proposal is broken into three parts. The introduction describes
72 :     the motivation for creating the component framework and its
73 :     requirements. The second section describes the component framework in
74 :     itself, which could be used for any executable extension point. The
75 :     third section describes how the workbench will use the component
76 :     framework for views and editors.<br>
77 :     <br>
78 :     Primary goals:<br>
79 :     <ul>
80 :     <li>Robustness / leak proofing</li>
81 :     <li>Nesting of components</li>
82 :     <li>Allow components to be reused outside the workbench</li>
83 :     <li>Scalability (allow an open-ended set of components)</li>
84 :     <li>API versioning<br>
85 :     </li>
86 :     <li>Ease of use</li>
87 :     </ul>
88 :     <h2><a class="mozTocH2" name="mozTocId29093"></a>1.1 Robustness / leak
89 :     proofing<br>
90 :     </h2>
91 :     Much of the Eclipse API is currently accessed through singleton
92 :     objects. This makes it easy for a view or editor to leak listeners,
93 :     fail to clean up reference counts, leak OS resources, etc. since there
94 :     is no way of tracking which resources were allocated by a particular
95 :     view. This problem would be reduced if views and editors were more like
96 :     mini-applications. The view or editor would access the rest of the
97 :     world through a set of local services. When the view or editor is
98 :     destroyed so would all of the services allocated for it. This gives
99 :     each service a chance to clean up after itself. <br>
100 :     <br>
101 :     For example, instead of reaching into a global
102 :     preference store, a view or editor could access all preferences through
103 :     a local preference
104 :     service. A unique instance of the local preference service would be
105 :     created for each view, and would be disposed with the view. When the
106 :     preference service is destroyed it would clear its listener list,
107 :     ensuring that the view will not leak any global listeners. This example
108 :     shows what we mean by a component. Essentially, a
109 :     component is an object that communicates with the rest of the
110 :     application through a set of interfaces given to it in its constructor.<br>
111 :     <span style="font-weight: bold;"></span>
112 :     <h2><a class="mozTocH2" name="mozTocId223982"></a>1.2 Nesting of
113 :     components</h2>
114 :     There is demand for the ability to embed views and editors inside one
115 :     another. Some examples:<br>
116 :     <ul>
117 :     <li>An XML editor might embed the properties view</li>
118 :     <li>A refactoring wizard might include a source editor</li>
119 :     <li>A plugin may wish to create a set of pluggable UI components that
120 :     are not views or editors themselves, but can be used inside any view or
121 :     editor</li>
122 :     <li>Various workbench objects (like the PartSashContainer that
123 :     handles the layout of docked parts within the workbench) could be
124 :     exposed as API<br>
125 :     </li>
126 :     </ul>
127 :     Many downstream plugins have solved these problems by creating their
128 :     own frameworks for reusable UI components. Unfortunately, only works
129 :     for specific views and editors, does not encourage interoperability
130 :     between plugins that have adopted different frameworks, and requires a
131 :     lot of work. The goal here is to adopt a framework in the workbench
132 :     itself that allows all editors, views, and other workbench objects to
133 :     be easily nested.<br>
134 :     <h2><a class="mozTocH2" name="mozTocId634024"></a>1.3 Creating parts
135 :     outside the workbench</h2>
136 :     It should be possible to instantiate views and editors outside the
137 :     workbench. Some examples:<br>
138 :     <ul>
139 :     <li>Unit-test editors and views by instantiating them within a JUnit
140 :     test suite.</li>
141 :     <li>Create an RCP application that does not depend on the workbench
142 :     but includes view-like pluggable parts
143 :     that could also be used as views within Eclipse</li>
144 :     </ul>
145 :     <h2><a class="mozTocH2" name="mozTocId800379"></a>1.4 Scalability</h2>
146 :     The workbench currently offers a closed set of services to parts. This
147 :     forces parts to reach to global objects whenever they need something
148 :     that isn't available from their site. It should be possible for any
149 :     plugin to contribute to the set of local API available to a part, and
150 :     it
151 :     should be possible to instantiate a part even if its parent doesn't
152 :     know about all of a part's dependencies.<br>
153 :     <h2><a class="mozTocH2" name="mozTocId866479"></a>1.5 Ease of use<br>
154 :     </h2>
155 :     Views and editors currently have a complicated lifecycle that must be
156 :     managed by the workbench. This complexity should not be exposed to
157 :     client code. <br>
158 :     <ul>
159 :     <li>It should only require one method call to create a component and
160 :     one method call to destroy it.</li>
161 :     <li>There should not be unnecessary duplication between XML and java
162 :     code.</li>
163 :     <li>Components should not
164 :     be responsible for dealing with error conditions (such as missing
165 :     dependencies) that can be detected by the framework.</li>
166 :     <li>Components should not need to implement interfaces they don't
167 :     care about.</li>
168 :     <li>A parent context should not need to provide child components with
169 :     interfaces it doesn't care about.<span style="font-weight: bold;"></span></li>
170 :     </ul>
171 :     <h1><a class="mozTocH1" name="mozTocId416167"></a>2.0 Component
172 :     Framework<br>
173 :     </h1>
174 :     Components are pluggable objects that are build using constructor
175 :     injection. Constructor injection means that the framework looks at the
176 :     object's constructor to determine what it needs to do to build that
177 :     object.<br>
178 :     <br>
179 :     Components:<br>
180 :     <ul>
181 :     <li>Have exactly one constructor</li>
182 :     <li>Take zero or more other components as arguments to their
183 :     constructor</li>
184 :     <li>Are fully initialized by their constructor</li>
185 :     </ul>
186 :     Components do not:<br>
187 :     <ul>
188 :     <li>Take arrays or primitives as arguments to their constructor</li>
189 :     <li>Take more than one argument of the same type in their constructor<br>
190 :     </li>
191 :     <li>Need to support any particular base class or interface</li>
192 :     </ul>
193 :     Any class with these properties can be used as a component. Since
194 :     components are plain-old-java-objects, they do not need to depend on
195 :     the component framework. Components are fully initialized by
196 :     their constructor, meaning it is never necessary
197 :     to call an initialize method or any combination of set methods after
198 :     constructing the object. Components never accept null as an argument
199 :     to their constructor.<br>
200 :     <br>
201 :     For example, if a view could be created as a component it might look
202 :     like this:<br>
203 :     <br>
204 :     <div style="margin-left: 40px;"><code>/**</code><br>
205 :     <code>&nbsp;* "Hello world" view using the service framework</code><br>
206 :     <code>&nbsp;*/</code><br>
207 :     <code>public class HelloWorldView {</code><br>
208 :     <code>&nbsp;&nbsp;&nbsp; public HelloWorldView(Composite parent) {</code><br>
209 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label helloWorld = new
210 :     Label(parent, SWT.NONE);</code><br>
211 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
212 :     helloWorld.setText("Hello
213 :     world");</code><br>
214 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
215 :     <code>}</code><br>
216 :     <code></code></div>
217 :     <code><br>
218 :     </code>The HelloWorldView component depends on one service: a Composite
219 :     created for it by whoever instantiated the view. Compare this with the
220 :     same view written using the existing API:<br>
221 :     <br>
222 :     <div style="margin-left: 40px;"><code>/**</code><br>
223 :     <code>&nbsp;* "hello world" view using the Eclipse 3.0 API.</code><br>
224 :     <code>&nbsp;*/</code><br>
225 :     <code>public class HelloWorldView extends ViewPart {</code><br>
226 :     <code>&nbsp;&nbsp;&nbsp; public void createPartControl(Composite
227 :     parent) {</code><br>
228 :     <code></code><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label
229 :     helloWorld = new Label(parent, SWT.NONE);</code><br>
230 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
231 :     helloWorld.setText("Hello
232 :     world");</code><code>&nbsp;&nbsp; </code><br>
233 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
234 :     <code></code><br>
235 :     <code>&nbsp;&nbsp;&nbsp; public void setFocus() {</code><br>
236 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
237 :     <code>}</code><br>
238 :     </div>
239 :     <br>
240 :     The main difference is that the component version does not require the
241 :     ViewPart base class and is fully initialized after construction. In
242 :     both cases, the extension point markup would look like this:<br>
243 :     <br>
244 :     <div style="margin-left: 40px;"><code>&lt;extension
245 :     point="org.eclipse.ui.views"&gt;</code><br>
246 :     <code>&nbsp;&nbsp;&nbsp; &lt;view</code><br>
247 :     <code>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; name="Title Test View"</code><br>
248 :     <code>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; icon="icons\view.gif"</code><br>
249 :     <code>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
250 :     class="org.eclipse.ui.mytest.HelloWorldView"</code><br>
251 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; id="</code><code>org.eclipse.ui.mytest.HelloWorldView</code><code>ID"&gt;</code><br>
252 :     <code>&nbsp;&nbsp;&nbsp; &lt;/view&gt;</code><br>
253 :     <code>&lt;/extension&gt;</code><br>
254 :     </div>
255 :     <br>
256 :     <h2><a class="mozTocH2" name="mozTocId489102"></a>2.1 Instantiating a
257 :     view<br>
258 :     </h2>
259 :     Components are instantiated using factories. For the moment, let's
260 :     focus on views before we explore components in general. Views could be
261 :     created using a method on IWorkbenchPage that would look something like
262 :     this. Note that this example is only intended to illustrate the general
263 :     idea -- the actual protocol for creating views is likely to change.<br>
264 :     <br>
265 :     <div style="margin-left: 40px;"><code>/**</code><br>
266 :     <code>&nbsp;* Creates a view of the given type inside the given
267 :     composite.
268 :     The caller must dispose the container once they are done with it.</code><br>
269 :     <code>&nbsp;*</code><br>
270 :     <code>&nbsp;* @param viewId id of the view extension to use</code><br>
271 :     <code>&nbsp;* @param parentComposite parent composite for the view</code><br>
272 :     <code>&nbsp;* @return an IContainer that contains all components needed
273 :     for the view</code><br>
274 :     <code>&nbsp;*/</code><br>
275 :     <code>IContainer createView(String viewId, Composite parentComposite);</code><br>
276 :     <code></code></div>
277 :     <code></code><br>
278 :     <br>
279 :     This creates a new instance of the view in the given composite. Notice
280 :     that the factory method doesn't return an instance of the view itself
281 :     but an instance of IContainer, which looks something like this:<br>
282 :     <br>
283 :     <div style="margin-left: 40px;"><code>/**</code><br>
284 :     <code>&nbsp;* Main interface to a component.</code><br>
285 :     <code>&nbsp;*/</code><br>
286 :     <code>public interface IContainer extends IAdaptable {</code><br>
287 :     <code></code>&nbsp; &nbsp;&nbsp; public void dispose();<br>
288 :     }<br>
289 :     </div>
290 :     <br>
291 :     This interface wraps the component and all of its dependencies. Once
292 :     we've obtained an IContainer handle, we are obligated to dispose it
293 :     when we are done with it. All access to the component is done through
294 :     adapters, which insulates
295 :     the application from changes in individual views. For example, if a
296 :     view that previously implemented the IViewInterface1 migrates to using
297 :     the newer IViewInterface2, its container will continue to work as long
298 :     as someone has provided an adapter between the two versions of
299 :     IViewInterface. The getAdapter() method on IComponent searches for
300 :     adapters in the following order:<br>
301 :     <br>
302 :     1. If the component itself implements the adapter type, it returns the
303 :     component.<br>
304 :     2. If the component itself implements IAdapter, and the component's
305 :     getAdapter(...) method returns non-null, we return that adapter.<br>
306 :     3. If the adapter manager has an adapter between the component and the
307 :     adapter type, we return that adapter.<br>
308 :     4. If the container's factory can construct a component of the
309 :     requested type, we
310 :     create that component, add it as a local dependency to the IContainer,
311 :     and
312 :     return it.<br>
313 :     5. Return null<br>
314 :     <br>
315 :     For example, it would be possible to create our HelloWorldView (above)
316 :     in a modal dialog like this:<br>
317 :     <br>
318 :     <div style="margin-left: 40px;"><code>void
319 :     createHelloWorldViewInADialog(IWorkbenchPage page) {</code><br>
320 :     <code>&nbsp;&nbsp;&nbsp; Display display = Display.getDefault()</code><br>
321 :     <code>&nbsp;&nbsp;&nbsp; Shell shell = new Shell(Display.getDefault());</code><br>
322 :     <code></code><br>
323 :     <code>&nbsp;&nbsp;&nbsp; shell.setLayout(new FillLayout());</code><br>
324 :     <code></code><br>
325 :     <code>&nbsp;&nbsp;&nbsp; // Create the view and its widgets</code><br>
326 :     <code>&nbsp;&nbsp;&nbsp; IContainer myView =
327 :     workbenchPage.createView("org.eclipse.ui.mytest.HelloWorldViewID",
328 :     shell);</code><br>
329 :     <code></code><br>
330 :     <code>&nbsp;&nbsp;&nbsp; shell.open();</code><br>
331 :     <code></code><br>
332 :     <code>&nbsp;&nbsp;&nbsp; while (!shell.isDisposed()) {</code><br>
333 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (!display.readAndDispatch ())
334 :     display.sleep ();</code><br>
335 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
336 :     <code></code><br>
337 :     <code>&nbsp;&nbsp;&nbsp; // Dispose the view</code><br>
338 :     <code>&nbsp;&nbsp;&nbsp; myView.dispose();</code><br>
339 :     <code>}</code><br>
340 :     <code></code></div>
341 :     <h2><a class="mozTocH2" name="mozTocId717633"></a>2.2 Instantiating
342 :     components in general<br>
343 :     </h2>
344 :     All components are constructed using an IContainerFactory, however most
345 :     component-based extension points will provide some
346 :     sort of convenience method to wrap their IContainerFactory. The
347 :     IWorkbenchPage.createView method in the
348 :     previous section is a convenience method for the <span
349 :     style="font-style: italic;">org.eclipse.ui.views </span>extension
350 :     point.<br style="font-style: italic;">
351 :     &nbsp;<br>
352 :     IContainerFactory looks like this:<br>
353 :     <br>
354 :     <div style="margin-left: 40px;"><code>/**<br>
355 :     &nbsp;* Factory for IContainer instances. The default factory is
356 :     returned by<br>
357 :     &nbsp;* Components.getFactory(). Clients wishing to implement their own
358 :     specialized <br>
359 :     &nbsp;* factories should call createDerivedFactory() to get access to a
360 :     factory<br>
361 :     &nbsp;* whose behavior can be modified programmatically. Not intended
362 :     to be <br>
363 :     &nbsp;* implemented by clients. <br>
364 :     &nbsp;* <br>
365 :     &nbsp;* @since 3.1<br>
366 :     &nbsp;*/<br>
367 :     public interface IContainerFactory {<br>
368 :     &nbsp;&nbsp;&nbsp; <br>
369 :     &nbsp;&nbsp;&nbsp; /**<br>
370 :     &nbsp;&nbsp;&nbsp;&nbsp; * Creates and returns a new IContainer
371 :     instance, given the <br>
372 :     &nbsp;&nbsp;&nbsp;&nbsp; * implementation class for its component. The
373 :     caller MUST call IContainer.dispose() <br>
374 :     &nbsp;&nbsp;&nbsp;&nbsp; * when it is done with the component. The
375 :     factory does not need any prior<br>
376 :     &nbsp;&nbsp;&nbsp;&nbsp; * knowledge of the component class be<br>
377 :     &nbsp;&nbsp;&nbsp;&nbsp; * <br>
378 :     &nbsp;&nbsp;&nbsp;&nbsp; * @param componentImplementation concrete
379 :     class to be instantiated by the factory. The class<br>
380 :     &nbsp;&nbsp;&nbsp;&nbsp; * &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
381 :     must be a valid component (it must have exactly one constructor which
382 :     only<br>
383 :     &nbsp;&nbsp;&nbsp;&nbsp; * &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
384 :     references other component interfaces known to this factory).<br>
385 :     &nbsp;&nbsp;&nbsp;&nbsp; * @return a newly constructed
386 :     &lt;code&gt;IContainer&lt;/code&gt; instance<br>
387 :     &nbsp;&nbsp;&nbsp;&nbsp; * @throws MissingDependencyException if the
388 :     requested component depends on another component that<br>
389 :     &nbsp;&nbsp;&nbsp;&nbsp;
390 :     *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cannot be constructed
391 :     by this factory<br>
392 :     &nbsp;&nbsp;&nbsp;&nbsp; * @throws CoreException if there is a more
393 :     permanent problem with using the given class as <br>
394 :     &nbsp;&nbsp;&nbsp;&nbsp;
395 :     *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a component <br>
396 :     &nbsp;&nbsp;&nbsp;&nbsp; * @since 3.1<br>
397 :     &nbsp;&nbsp;&nbsp;&nbsp; */<br>
398 :     &nbsp;&nbsp;&nbsp; public IContainer createContainer(Class
399 :     componentImplementation) throws MissingDependencyException,
400 :     CoreException;<br>
401 :     &nbsp;&nbsp;&nbsp; <br>
402 :     &nbsp;&nbsp;&nbsp; /**<br>
403 :     &nbsp;&nbsp;&nbsp;&nbsp; * Creates a specialization of this factory. By
404 :     default, the specialized<br>
405 :     &nbsp;&nbsp;&nbsp;&nbsp; * factory will have the same behavior as its
406 :     parent. However, the derived<br>
407 :     &nbsp;&nbsp;&nbsp;&nbsp; * factory can add, or override the
408 :     implementation for any components.<br>
409 :     &nbsp;&nbsp;&nbsp;&nbsp; * <br>
410 :     &nbsp;&nbsp;&nbsp;&nbsp; * @return new factory instance that allows
411 :     individual components to be overridden.<br>
412 :     &nbsp;&nbsp;&nbsp;&nbsp; * By default, the derived factory will
413 :     delegate all of its behavior to the receiver.<br>
414 :     &nbsp;&nbsp;&nbsp;&nbsp; * Changes in the receiver will affect the
415 :     derived factory.<br>
416 :     &nbsp;&nbsp;&nbsp;&nbsp; * @since 3.1<br>
417 :     &nbsp;&nbsp;&nbsp;&nbsp; */<br>
418 :     &nbsp;&nbsp;&nbsp; public IMutableContainerFactory
419 :     createDerivedFactory();<br>
420 :     }</code><code></code><br>
421 :     <code></code></div>
422 :     <code></code><br>
423 :     Notice that createComponent throws two types of exception. A
424 :     CoreException indicates a problem with the component itself, and a
425 :     MissingDependencyException indicates that some other component or
426 :     adapter could not be found. This can help locate the cause of problems,
427 :     and a robust extension point may want to disable components that throw
428 :     CoreExceptions.<br>
429 :     <br>
430 :     All arguments to a component's constructor are provided by its factory.
431 :     Different
432 :     factories know how to create different types of components or will
433 :     provide
434 :     different implementations for the same components. All factories are
435 :     derived from the root factory, which is returned by
436 :     Components.getFactory(). A plugin can create derived factories to
437 :     supply services to one specific extension point. It is also possible to
438 :     create a derived factory in order to pass information to the
439 :     constructor of one specific object, as we will do in this example. In
440 :     our case, we will create a container factory to pass a specific
441 :     Composite into the constructor of HelloWorldView. The code looks like
442 :     this:<br>
443 :     <code></code><code><br>
444 :     </code>
445 :     <div style="margin-left: 40px;"><code>// Get the global factory</code><br>
446 :     <code>IContainerFactory viewFactory =
447 :     Components.getFactory();</code><br>
448 :     <code></code><br>
449 :     <code>// Create the Composite for the view</code><br>
450 :     <code></code><code>Composite viewComposite = new
451 :     Composite(parentComposite, SWT.NONE);</code><br>
452 :     <code>viewComposite.setLayout(new FillLayout();</code><br>
453 :     <code></code><br>
454 :     <code>// Create a specialized factory that knows about the view's
455 :     composite and plugin bundle</code><br>
456 :     <code>IMutableContainerFactory derivedFactory =
457 :     viewFactory.createDerivedFactory();</code><br>
458 :     <code></code><br>
459 :     <code>// Add the view's composite as a service instance</code><br>
460 :     <code>derivedFactory.addComponentInstance(viewComposite);</code><br>
461 :     <code></code><br>
462 :     <code>// Add the view's plugin bundle as a service instance (not
463 :     required in this example, but this</code><br>
464 :     <code>// is recommended practise for any component created from an
465 :     extension point).</code><br>
466 :     <code>derivedFactory.addComponentInstance(pluginBundle);</code><br>
467 :     <code></code><br>
468 :     <code>// Create the view. Provide its constructor and some
469 :     context (the page that created it).</code><br>
470 :     <code>IContainer view =
471 :     derivedFactory.createContainer(HelloWorldView.class);</code><br>
472 :     <code></code><br>
473 :     <code>// Do something with the view</code><br>
474 :     <code>// ...</code><br>
475 :     <code></code><br>
476 :     <code>// Now clean up</code><br>
477 :     <code>view.dispose();</code><br>
478 :     <code>viewComposite.dispose();</code><br>
479 :     <code></code></div>
480 :     <code><br>
481 :     </code><br>
482 :     This code will work, but it has two problems:<br>
483 :     <br>
484 :     1. Even if HelloWorldView didn't require a Composite, we would still
485 :     have created one (which is wasteful).<br>
486 :     2. We need to manually dispose the view's composite after we're done
487 :     with it. This defeats the point of IComponent.dispose(), which is
488 :     supposed to clean up all of the component's dependencies automatically.<br>
489 :     <h2><a class="mozTocH2" name="mozTocId450231"></a>2.3 Creating
490 :     dependent components on demand </h2>
491 :     Rather than managing the view's Composite ourselves, we could supply a
492 :     factory that knows how to create and destroy Composites as needed. Such
493 :     a factory would look like this:<br>
494 :     <br>
495 :     <div style="margin-left: 40px;"><code>/**</code><br>
496 :     <code>&nbsp;* ServiceAdapter for creating and managing SWT Composites
497 :     as services.</code><br>
498 :     <code>&nbsp;*/</code><br>
499 :     <code>public class CompositeFactory extends ComponentAdapter {</code><br>
500 :     <code></code><br>
501 :     <code>&nbsp;&nbsp;&nbsp; private Composite parent;</code><br>
502 :     <code>&nbsp;&nbsp;&nbsp; </code><br>
503 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
504 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * The SWT composites created by this
505 :     factory will all be children of the given</code><br>
506 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * composite.</code><br>
507 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
508 :     <code>&nbsp;&nbsp;&nbsp; public CompositeFactory(Composite parent) {</code><br>
509 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.parent = parent;</code><br>
510 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
511 :     <code>&nbsp;&nbsp;&nbsp; </code><br>
512 :     <code>&nbsp;&nbsp;&nbsp; protected Object create(IAdaptable
513 :     availableServices) throws CoreException {</code><br>
514 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Create a new Composite
515 :     which will be used as a service.</code><br>
516 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // If we needed any
517 :     additional</code><br>
518 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Composite newChild =
519 :     new Composite(parent, SWT.NONE);</code><br>
520 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newChild.setLayout(new
521 :     FillLayout());</code><br>
522 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return newChild;</code><br>
523 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
524 :     <code></code><br>
525 :     <code>&nbsp;&nbsp;&nbsp; protected void dispose(Object service) {</code><br>
526 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
527 :     ((Composite)service).dispose();</code><br>
528 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
529 :     <code></code><br>
530 :     <code>&nbsp;&nbsp;&nbsp; public String getInterfaceName() {</code><br>
531 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Return the fully
532 :     qualified class name of the Composite class. The framework will call</code><br>
533 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // this method to determine
534 :     what type of service will be constructed by this factory.</code><br>
535 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return
536 :     Composite.class.getName();</code><br>
537 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
538 :     <code>}</code><br>
539 :     <code></code></div>
540 :     <br>
541 :     Using CompositeFactory, we could construct HelloWorldView like this:<br>
542 :     <br>
543 :     <div style="margin-left: 40px;"><code>// Get the global factory</code><br>
544 :     <code>IContainerFactory viewFactory =
545 :     Components.getFactory();</code><code></code><br>
546 :     <code></code><br>
547 :     <code>// Create a specialized factory that knows about the view's
548 :     composite and plugin bundle</code><br>
549 :     <code>IMutableContainerFactory derivedFactory =
550 :     viewFactory.createDerivedFactory();</code><br>
551 :     <code></code><br>
552 :     <code>// Add the view's composite as a service instance</code><br>
553 :     <code>derivedFactory.addComponentFactory(new
554 :     CompositeFactory(parentComposite));</code><br>
555 :     <code></code><br>
556 :     <code>// Add the view's plugin bundle as a service instance (not
557 :     required in this example, but this</code><br>
558 :     <code>// is recommended practise for any component created from an
559 :     extension point).</code><br>
560 :     <code>derivedFactory.addComponentInstance(pluginBundle);</code><br>
561 :     <code></code><br>
562 :     <code>// Create the view. Provide its constructor and some
563 :     context (the page that created it).</code><br>
564 :     <code>IContainer view =
565 :     derivedFactory.createComponent(HelloWorldView.class);</code><br>
566 :     <code></code><br>
567 :     <code>// Do something with the view</code><br>
568 :     <code>// ...</code><br>
569 :     <code></code><br>
570 :     <code>// Now clean up</code><br>
571 :     <code>view.dispose();</code><br>
572 :     <code></code></div>
573 :     <code>
574 :     </code><br>
575 :     The composite will now be allocated as needed and disposed inside the
576 :     call to view.dispose().<br>
577 :     <br>
578 :     <code></code>
579 :     <h2><a class="mozTocH2" name="mozTocId928619"></a>2.4 Declaring Global
580 :     Services<br>
581 :     </h2>
582 :     Services are a type of component that can be used by other components.
583 :     Services are registered through the <span style="font-style: italic;">org.eclipse.ui.component.service
584 :     </span>extension
585 :     point. Services are global in the sense that they are created by
586 :     factories
587 :     that are visible everywhere, however each instance of a services is
588 :     associated with a specific IContainer. Each service implements a
589 :     service interface. Other components can use the service interface in
590 :     their constructor. When they do so, a new instance of the service will
591 :     be created for that component which will be managed by the same
592 :     IContainer. <br>
593 :     <br>
594 :     Each component supplies an implementation and an interface. Here is an
595 :     example service interface:<br>
596 :     <code><br>
597 :     </code>
598 :     <div style="margin-left: 40px;"><code>/**</code><br>
599 :     <code>&nbsp;* Service interface: </code><br>
600 :     <code>&nbsp;*</code><br>
601 :     <code>&nbsp;* Provides a context for reporting and logging exceptions.</code><br>
602 :     <code>&nbsp;*/</code><br>
603 :     <code>public interface IErrorContext {</code><br>
604 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
605 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * Create an IStatus error describing the
606 :     given
607 :     throwable</code><br>
608 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
609 :     <code>&nbsp;&nbsp;&nbsp; public IStatus createStatus(Throwable t);</code><br>
610 :     <code></code><br>
611 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
612 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * Create an IStatus message with the
613 :     given
614 :     severity, message, and (optional) throwable</code><br>
615 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
616 :     <code>&nbsp;&nbsp;&nbsp; public IStatus createStatus(int severity,
617 :     String
618 :     message, Throwable t);</code><br>
619 :     <code></code><br>
620 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
621 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * Logs an IStatus message</code><br>
622 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
623 :     <code>&nbsp;&nbsp;&nbsp; public void log(IStatus status);</code><br>
624 :     <code></code><br>
625 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
626 :     <code>&nbsp; &nbsp;&nbsp; * Logs an exception to the system log</code><br>
627 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
628 :     <code>&nbsp;&nbsp;&nbsp; public void log(Throwable t);</code><br>
629 :     <code>}</code><br>
630 :     <code></code></div>
631 :     <code><br>
632 :     <br>
633 :     </code>Here is the associated service implementation:<br>
634 :     <code><br>
635 :     </code>
636 :     <div style="margin-left: 40px;"><code>/**</code><br>
637 :     <code>&nbsp;* Service implementation:</code><br>
638 :     <code>&nbsp;*</code><br>
639 :     <code>&nbsp;* Creates and logs errors in the context of a plugin bundle</code><br>
640 :     <code>&nbsp;*/</code><br>
641 :     <code>public class ErrorContext implements IErrorContext {</code><br>
642 :     <code>&nbsp;&nbsp;&nbsp; private Bundle pluginBundle;</code><br>
643 :     <code></code><br>
644 :     <code>&nbsp;&nbsp;&nbsp; public ExceptionLoggingService(Bundle
645 :     pluginBundle) {</code><br>
646 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; this.pluginBundle =
647 :     pluginBundle;</code><br>
648 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
649 :     <code></code><br>
650 :     <code>&nbsp;&nbsp;&nbsp; public IStatus createStatus(Throwable t) {</code><br>
651 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; String message = t.getMessage();</code><br>
652 :     <code>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (message == null) {</code><br>
653 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; message =
654 :     t.getString();</code><br>
655 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</code><br>
656 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return createStatus(Status.ERROR,
657 :     message, t);</code><br>
658 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
659 :     <code></code><br>
660 :     <code>&nbsp;&nbsp;&nbsp; public IStatus createStatus(int severity,
661 :     String
662 :     message, Throwable t) {</code><br>
663 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return new Status(severity,
664 :     pluginBundle.getSymbolicName(), Status.OK, message, t);</code><br>
665 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
666 :     <code></code><br>
667 :     <code>&nbsp;&nbsp;&nbsp; public void log(Throwable t) {</code><br>
668 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; log(createStatus(t));</code><br>
669 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
670 :     <code></code><br>
671 :     <code>&nbsp;&nbsp;&nbsp; public void log(IStatus status) {</code><br>
672 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Plugin plugin =
673 :     Platform.getPlugin(pluginBundle.getSymbolicName());</code><br>
674 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; plugin.getLog().log(status);</code><br>
675 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
676 :     <code>}</code><br>
677 :     <code></code></div>
678 :     <code></code><br>
679 :     Finally, here is the extension markup:<br>
680 :     <br>
681 :     <div style="margin-left: 40px;"><code>&lt;extension
682 :     point="org.eclipse.ui.component.service"&gt;</code><br>
683 :     <code>&nbsp;&nbsp; &lt;service
684 :     </code><br>
685 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;
686 :     class="org.eclipse.ui.workbench.ErrorContext"</code><br>
687 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; </code><code>interface="</code><code>org.eclipse.ui.workbench.IErrorContext</code><code>"</code><code>&gt;</code><br>
688 :     <code>&nbsp;&nbsp; &lt;/service&gt;</code><br>
689 :     <code>&lt;/extension&gt;</code><br>
690 :     </div>
691 :     <br>
692 :     Notice that the extension XML needs to indicate which service interface
693 :     is being implemented by the service, but not its dependencies. When it
694 :     comes time to create the service, the framework detects that the
695 :     ErrorContext needs to be associated with a plugin Bundle by examining
696 :     its constructor. This means that if plugin A defines the ErrorContext
697 :     service and plugin B defines a view that uses the service, then all of
698 :     the status messages constructed by the view will be associated with the
699 :     view's own plugin - not the plugin that defined the ErrorContext
700 :     service.<br>
701 :     <h2><a class="mozTocH2" name="mozTocId749133"></a>2.5 Using services</h2>
702 :     This example shows how a component can use a service.<br>
703 :     <br>
704 :     <div style="margin-left: 40px;"><code>public class MyView {</code><br>
705 :     <code>&nbsp;&nbsp;&nbsp; private IErrorContext errorContext;</code><br>
706 :     <code></code><br>
707 :     <code>&nbsp;&nbsp;&nbsp; public MyView(</code><code>Composite parent, </code><code>IErrorContext
708 :     errorContext) {</code><br>
709 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; this.errorContext = errorContext;</code><br>
710 :     <code></code><br>
711 :     <code></code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Button errorButton =
712 :     new
713 :     Button(parent, SWT.PUSH);</code><br>
714 :     <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errorButton.setText("Log an
715 :     exception");</code><br>
716 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </code><br>
717 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
718 :     errorButton.addSelectionListener(new
719 :     SelectionAdapter() {</code><br>
720 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; public void
721 :     widgetSelected(SelectionEvent e) {</code><br>
722 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
723 :     &nbsp;&nbsp;
724 :     try {</code><br>
725 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
726 :     &nbsp;&nbsp;
727 :     &nbsp;&nbsp; // Throw a NPE</code><br>
728 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
729 :     &nbsp;&nbsp;
730 :     &nbsp;&nbsp; String myString = null;</code><br>
731 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
732 :     &nbsp;&nbsp;
733 :     &nbsp;&nbsp; String bogusCode = myString.substring(10, 30);</code><br>
734 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
735 :     &nbsp;&nbsp;
736 :     } catch (Exception e) {</code><br>
737 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
738 :     &nbsp;&nbsp;
739 :     &nbsp;&nbsp; // Log the NPE using the error context service</code><br>
740 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
741 :     &nbsp;&nbsp; &nbsp; errorContext.log(e);</code><br>
742 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
743 :     &nbsp;&nbsp; }</code><br>
744 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</code><br>
745 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; });</code><br>
746 :     <code></code><code>&nbsp;&nbsp;&nbsp; }</code><br>
747 :     <code></code><code>}</code><br>
748 :     <code></code></div>
749 :     <code><br>
750 :     </code>This view creates a button which, when pressed, will throw a NPE
751 :     and log it. The status message will be constructed and logged using the
752 :     IErrorContext service we defined above.<br>
753 :     <br>
754 :     <h2><a class="mozTocH2" name="mozTocId705695"></a>2.6 Lifecycle</h2>
755 :     Many components need to do explicit cleanup. Components
756 :     that need to perform cleanup will implement the
757 :     IDisposable interface. For example, the following component attaches a
758 :     listener to a global preference store and detaches it when done.<br>
759 :     <br>
760 :     <div style="margin-left: 40px;"><code>/**</code><br>
761 :     <code>&nbsp;* Provides access to a plugin's preference store in a
762 :     manner that
763 :     prevents listener leaks.</code><br>
764 :     <code>&nbsp;*/</code><br>
765 :     <code>public interface IPreferences {</code><br>
766 :     <code>&nbsp;&nbsp;&nbsp; public String getString(String prefId);</code><br>
767 :     <code>&nbsp;&nbsp;&nbsp; public void setString(String prefId, String
768 :     value);</code><br>
769 :     <code>&nbsp;&nbsp;&nbsp; public void
770 :     addListener(IPropertyChangeListener l);</code><br>
771 :     <code>&nbsp;&nbsp;&nbsp; public void
772 :     removeListener(IPropertyChangeListener
773 :     l);</code><br>
774 :     <code>}</code><br>
775 :     <code></code><br>
776 :     <code>/**</code><br>
777 :     <code>&nbsp;* Concrete implementation of the IPreferences interface</code><br>
778 :     <code>&nbsp;*/</code><br>
779 :     <code>public LocalPreferenceStore implements IPreferences, IDisposable {</code><br>
780 :     <code>&nbsp;&nbsp;&nbsp; ListenerList listeners = new ListenerList();</code><br>
781 :     <code>&nbsp;&nbsp;&nbsp; Preferences prefs;</code><br>
782 :     <code>&nbsp;&nbsp;&nbsp; </code><br>
783 :     <code>&nbsp;&nbsp;&nbsp; private class PropertyChangeListener
784 :     implements
785 :     Preferences.IPropertyChangeListener {</code><br>
786 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*</code><br>
787 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* @see
788 :     org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)</code><br>
789 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;*/</code><br>
790 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void
791 :     propertyChange(Preferences.PropertyChangeEvent event) {</code><br>
792 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
793 :     firePropertyChangeEvent(event.getProperty(), event.getOldValue(),
794 :     event.getNewValue());</code><br>
795 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</code><br>
796 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
797 :     <code></code><br>
798 :     <code>&nbsp;&nbsp;&nbsp; PropertyChangeListener listener = new
799 :     PropertyChangeListener();</code><br>
800 :     <code></code><br>
801 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
802 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * Create a wrapper around the given
803 :     bundle's
804 :     preference store.</code><br>
805 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
806 :     <code>&nbsp;&nbsp;&nbsp; public LocalPreferenceStore(Bundle
807 :     pluginBundle) {</code><br>
808 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Plugin plugin =
809 :     Platform.getPlugin(pluginBundle.getSymbolicName());</code><br>
810 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; prefs =
811 :     plugin.getPluginPreferences();</code><br>
812 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; prefs.addListener(listener);</code><br>
813 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
814 :     <code></code><br>
815 :     <code>&nbsp;&nbsp;&nbsp; private void firePropertyChange(String name,
816 :     Object
817 :     oldValue, Object newValue) {</code><br>
818 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PropertyChangeEvent event =
819 :     new
820 :     PropertyChangeEvent(this, name, oldValue, newValue);</code><br>
821 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object[] listeners =
822 :     this.listeners.getListeners();</code><br>
823 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i= 0; i &lt;
824 :     listeners.length; i++)</code><br>
825 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
826 :     ((IPropertyChangeListener) listeners[i]).propertyChange(event);</code><br>
827 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
828 :     <code></code><br>
829 :     <code>&nbsp;&nbsp;&nbsp; /**</code><br>
830 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * This method will automatically be
831 :     called
832 :     when the component that uses this service is disposed.</code><br>
833 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; * It should clean up anything that has
834 :     been
835 :     allocated by the service.</code><br>
836 :     <code>&nbsp;&nbsp;&nbsp;&nbsp; */</code><br>
837 :     <code>&nbsp;&nbsp;&nbsp; public void dispose() {</code><br>
838 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; prefs.removeListener(listener);</code><br>
839 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
840 :     <code></code><br>
841 :     <code>&nbsp;&nbsp;&nbsp; public String getString(String prefId) {</code><br>
842 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; return prefs.getString(prefId);</code><br>
843 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
844 :     <code></code><br>
845 :     <code>&nbsp;&nbsp;&nbsp; public void setString(String prefId, String
846 :     value) {</code><br>
847 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; prefs.setValue(prefId, value);</code><br>
848 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
849 :     <code>}</code><br>
850 :     <code></code></div>
851 :     <code></code><br>
852 :     Similarly, components may implement the IDisposable interface. A
853 :     component that implements IDisposable will be disposed before any of
854 :     its services, as shown by the following example:<br>
855 :     <br>
856 :     <div style="margin-left: 40px;"><code>public LifecycleService
857 :     implements IDisposable {</code><br>
858 :     <code>&nbsp;&nbsp;&nbsp; public LifecycleService() {</code><br>
859 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
860 :     System.out.println("LifecycleService
861 :     created");</code><br>
862 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
863 :     <code></code><br>
864 :     <code>&nbsp;&nbsp;&nbsp; public void dispose() {</code><br>
865 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
866 :     System.out.println("LifecycleService
867 :     destroyed");</code><br>
868 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
869 :     <code>}</code><br>
870 :     <code></code><br>
871 :     <code>public LifecycleView implements IDisposable {</code><br>
872 :     <code>&nbsp;&nbsp;&nbsp; public LifecycleView(LifecycleService service)
873 :     {</code><br>
874 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("LifecycleView
875 :     created");</code><br>
876 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
877 :     <code></code><br>
878 :     <code>&nbsp;&nbsp;&nbsp; public void dispose() {</code><br>
879 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("LifecycleView
880 :     destroyed");</code><br>
881 :     <code>&nbsp;&nbsp;&nbsp; }</code><br>
882 :     <code>}</code><br>
883 :     <code></code><br>
884 :     </div>
885 :     Finally, we could execute the following code to trace when the service
886 :     is created and destroyed:<br>
887 :     <div style="margin-left: 40px;"><br>
888 :     IMutableContainerFactory factory =
889 :     Components.getFactory().createDerivedFactory();<br>
890 :     factory.addComponentImplementation(LifecycleService.class);<br>
891 :     <br>
892 :     System.out.println("Creating a LifecycleView");<br>
893 :     <br>
894 :     IContainer viewComponent = factory.createComponent(LifecycleView.class);<br>
895 :     viewComponent.dispose();<br>
896 :     <br>
897 :     System.out.println("Creating two LifecycleViews");<br>
898 :     <br>
899 :     IContainer viewComponent2 =
900 :     factory.createComponent(LifecycleView.class);<br>
901 :     IContainer viewComponent3 =
902 :     factory.createComponent(LifecycleView.class);<br>
903 :     viewComponent3.dispose();<br>
904 :     viewComponent2.dispose();<br>
905 :     <br>
906 :     </div>
907 :     The code will generate the following output:<br>
908 :     <br>
909 :     <div style="margin-left: 40px;">Creating a LifecycleView<br>
910 :     LifecycleService created<br>
911 :     LifecycleView created<br>
912 :     LifecycleView destroyed<br>
913 :     LifecycleService destroyed<br>
914 :     <br>
915 :     Creating two LifecycleViews<br>
916 :     LifecycleService created<br>
917 :     LifecycleView created<br>
918 :     LifecycleService created<br>
919 :     LifecycleView created<br>
920 :     LifecycleView destroyed<br>
921 :     LifecycleService destroyed<br>
922 :     LifecycleView destroyed<br>
923 :     LifecycleService destroyed<br>
924 :     <br>
925 :     </div>
926 :     <h2><a class="mozTocH2" name="mozTocId543223"></a>2.7 Dynamic Services</h2>
927 :     Global service factories are dynamic in the sense that they come and go
928 :     as plugins are installed or uninstalled. If a plugin providing a
929 :     service is uninstalled, a new implementation is selected from a
930 :     different plugin. If no other plugin provides that service, the service
931 :     becomes unavailable and it will not be possible to construct components
932 :     that use it.<br>
933 :     <br>
934 :     Service instances themselves are not dynamic. Once a service is
935 :     created, it will exist for as long as the component it was created for.
936 :     Even if the a plugin stops providing a service, all instances of that
937 :     service will continue to exist until disposed. All services used by a
938 :     component will be created before that component, so components do not
939 :     need to query for the existence of services or to wait for services
940 :     that will be created after-the-fact. <br>
941 :     <br>
942 :     Plugins that need more advanced dynamic support should use OSGI
943 :     services. The component framework is not intended as a replacement for
944 :     OSGI, and there is no point in reimplmenting things that OSGI already
945 :     does well.<br>
946 :     <h2><a class="mozTocH2" name="mozTocId886834"></a>2.8 Optional Services<br>
947 :     </h2>
948 :     Sometimes a component does not require a service but can make use of it
949 :     service if it exists. This should usually be handled by explicitly
950 :     creating an empty global implementation of the service, but sometimes
951 :     it is more efficient to have the component explicitly check if the
952 :     service exists. This can be done by taking an argument of type
953 :     IAdaptable, like this:<br>
954 :     <br>
955 :     <div style="margin-left: 40px;"><code>/**<br>
956 :     &nbsp;* A component with no dependencies, but which can optionally
957 :     accept an IMemento for initialization.<br>
958 :     &nbsp;*/<br>
959 :     public class MyComponent {<br>
960 :     <br>
961 :     &nbsp;&nbsp;&nbsp; String myName = "default name";<br>
962 :     <br>
963 :     &nbsp;&nbsp;&nbsp; public MyComponent(IAdaptable optionalServices) {<br>
964 :     <br>
965 :     </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Check if an IMemento
966 :     service exists.</code><br>
967 :     <code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; IMemento memento =
968 :     (IMemento)optionalServices.getAdapter(IMemento.class);<br>
969 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br>
970 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (memento != null) {<br>
971 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; String name =
972 :     memento.getString("name");<br>
973 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; if (name != null) {<br>
974 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; myName = name;<br>
975 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; }<br>
976 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
977 :     <br>
978 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println("created component
979 :     with name = " + myName);<br>
980 :     &nbsp;&nbsp;&nbsp; }<br>
981 :     }<br>
982 :     <br>
983 :     </code></div>
984 :     We could create the component like this:<br>
985 :     <br>
986 :     <div style="margin-left: 40px;"><code>// Create a memento with the name
987 :     "custom name"<br>
988 :     IMemento memento = XMLMemento.createWriteRoot("test");<br>
989 :     memento.putString("name", "custom name");<br>
990 :     <br>
991 :     // Create a factory which knows about our memento<br>
992 :     IMutableContainerFactory context =
993 :     Components.getFactory().createDerivedFactory();<br>
994 :     context.addComponentInstance(memento);<br>
995 :     <br>
996 :     // Use the factory to instantiate MyComponent<br>
997 :     IContainer component = context.createContainer(MyComponent.class);<br>
998 :     // Will print the message "created component with name = custom name"<br>
999 :     component.dispose();</code><br>
1000 :     <br>
1001 :     </div>
1002 :     We can also create the component without the optional IMemento:<br>
1003 :     <br>
1004 :     <div style="margin-left: 40px;"><code>IContainer component =
1005 :     Components.getFactory().createContainer(MyComponent.class);<br>
1006 :     // Will print the message "create component with name = default name"<br>
1007 :     component.dispose();</code><code></code><br>
1008 :     </div>
1009 :     <br>
1010 :     WARNING: This pattern should be used with care since it adds special
1011 :     cases to the component code. It is mainly inteded for situations where
1012 :     a component requires an open-ended set of services or where it is not
1013 :     possible to offer a default implementation of a service.<br>
1014 :     <br>
1015 :     <h2><a class="mozTocH2" name="mozTocId163729"></a>2.9 Multiplexing
1016 :     services</h2>
1017 :     In UI code, it is common to create aggregate components that have an
1018 :     "active" child. Many of the adapters that the aggregate offers its
1019 :     parent will redirect their implementation to the active child. We refer
1020 :     to this as "multiplexing" the service. The aggregate itself will know
1021 :     how to select its active child, but it may not know about all the
1022 :     services that need to be multiplexed. The default implementation of a
1023 :     service determines how and if it should be multiplexed.<br>
1024 :     <br>
1025 :     This can be explained better using a concrete example. Workbench parts
1026 :     offer an IFocusable adapter to their parent that allows their parent to
1027 :     give them focus. <br>
1028 :     <br>
1029 :     <code></code>
1030 :     <div style="margin-left: 40px;"><code>/**<br>
1031 :     &nbsp;* Parts can implement this interface if they wish to overload the
1032 :     default<br>
1033 :     &nbsp;* setFocus behavior.<br>
1034 :     &nbsp;*/<br>
1035 :     public interface IFocusable {<br>
1036 :     &nbsp;&nbsp;&nbsp; /**<br>
1037 :     &nbsp;&nbsp;&nbsp; &nbsp;* Gives focus to the part<br>
1038 :     &nbsp;&nbsp;&nbsp; &nbsp;*/<br>
1039 :     &nbsp;&nbsp;&nbsp; public void setFocus();<br>
1040 :     }</code><br>
1041 :     <br>
1042 :     </div>
1043 :     This interface should be multiplexed by default. For example, if we
1044 :     call setFocus() on a multi-page editor that doesn't explicitly
1045 :     implement the IFocusable interface, it should redirect focus to its
1046 :     active child. If the part doesn't have an active child, focus should go
1047 :     directly to the part's main control. To supply this default behavior,
1048 :     we provide an implementation of IFocusable as a global service:<br>
1049 :     <br>
1050 :     <code></code>
1051 :     <div style="margin-left: 40px;"><code>/**<br>
1052 :     &nbsp;* Default implementation of the IFocusable service. If a part
1053 :     doesn't explicitly<br>
1054 :     &nbsp;* provide an adapter for IFocusable, this implementation will be
1055 :     used.<br>
1056 :     &nbsp;*/<br>
1057 :     public class DefaultFocusable implements IFocusable {<br>
1058 :     <br>
1059 :     &nbsp;&nbsp;&nbsp; private Composite control;<br>
1060 :     &nbsp;&nbsp;&nbsp; private IMultiplexer activePart;<br>
1061 :     &nbsp;&nbsp;&nbsp; <br>
1062 :     &nbsp;&nbsp;&nbsp; /**<br>
1063 :     &nbsp;&nbsp;&nbsp; &nbsp;* Creates the default implementation of
1064 :     IFocusable, given the main control<br>
1065 :     &nbsp;&nbsp;&nbsp; &nbsp;* of the part and an IMultiplexer that can be
1066 :     queried for the active child.<br>
1067 :     &nbsp;&nbsp;&nbsp; &nbsp;* <br>
1068 :     &nbsp;&nbsp;&nbsp; &nbsp;* @param toGiveFocus main control of the pane<br>
1069 :     &nbsp;&nbsp;&nbsp; &nbsp;* @param activePartProvider multiplexer that
1070 :     returns the active part<br>
1071 :     &nbsp;&nbsp;&nbsp; &nbsp;*/<br>
1072 :     &nbsp;&nbsp;&nbsp; public DefaultFocusable(Composite toGiveFocus,
1073 :     IMultiplexer activePartProvider) {<br>
1074 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; control = toGiveFocus;<br>
1075 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; activePart = activePartProvider;<br>
1076 :     &nbsp;&nbsp;&nbsp; }<br>
1077 :     &nbsp;&nbsp;&nbsp; <br>
1078 :     &nbsp;&nbsp;&nbsp; /**<br>
1079 :     &nbsp;&nbsp;&nbsp;&nbsp; * First, try to give focus to the active
1080 :     child. If there is no active child, give focus to<br>
1081 :     &nbsp;&nbsp;&nbsp;&nbsp; * the main control.<br>
1082 :     &nbsp;&nbsp;&nbsp;&nbsp; */<br>
1083 :     &nbsp;&nbsp;&nbsp; public void setFocus() {<br>
1084 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // If this part has the notion of
1085 :     an active child, give that child focus<br>
1086 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object current =
1087 :     activePart.getCurrent();<br>
1088 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (current != null) {<br>
1089 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IFocusable
1090 :     focusable = (IFocusable)Components.getAdapter(current,
1091 :     IFocusable.class);<br>
1092 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (focusable
1093 :     != null) {<br>
1094 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
1095 :     &nbsp;&nbsp;&nbsp; focusable.setFocus();<br>
1096 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
1097 :     &nbsp;&nbsp;&nbsp; return;<br>
1098 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
1099 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
1100 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
1101 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // If the part has no children,
1102 :     then give focus to the part itself.&nbsp;&nbsp;&nbsp;
1103 :     &nbsp;&nbsp;&nbsp; <br>
1104 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; control.setFocus();<br>
1105 :     &nbsp;&nbsp;&nbsp; }<br>
1106 :     }</code><br>
1107 :     <br>
1108 :     </div>
1109 :     Here is the XML markup to register the service:<br>
1110 :     <br>
1111 :     <div style="margin-left: 40px;"><code>&lt;service<br>
1112 :     &nbsp;&nbsp;&nbsp;
1113 :     interface="org.eclipse.ui.workbench.services.IFocusable"<br>
1114 :     &nbsp;&nbsp;&nbsp;
1115 :     class="org.eclipse.ui.internal.part.serviceimplementation.DefaultFocusable"/&gt;</code><code></code><br>
1116 :     </div>
1117 :     <br>
1118 :     All of the services we have looked at so far have been offered by a
1119 :     parent for use in a child's constructor. In this case, the service is
1120 :     offered as an adapter on the child to be used by the parent. In both
1121 :     cases, the service is declared in the same way. Any service that
1122 :     supports multiplexing takes an IMultiplexer in its constructor. If the
1123 :     part does not support multiplexing, the IMultiplexer will always
1124 :     returns null from getCurrent. Here is an example part that supports
1125 :     multiplexing:<br>
1126 :     <code><br>
1127 :     </code>
1128 :     <div style="margin-left: 40px;"><code>/**<br>
1129 :     &nbsp;* Part that explicitly implements IFocusable.<br>
1130 :     &nbsp;*/<br>
1131 :     public class Page implements IFocusable {<br>
1132 :     &nbsp;&nbsp;&nbsp; Text textField;<br>
1133 :     <br>
1134 :     &nbsp;&nbsp;&nbsp; public Page(Composite control) {<br>
1135 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; textField = new Text(control, SWT.NONE);<br>
1136 :     &nbsp;&nbsp;&nbsp; }<br>
1137 :     <br>
1138 :     &nbsp;&nbsp;&nbsp; public void setFocus() {<br>
1139 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; textField.setFocus();<br>
1140 :     &nbsp;&nbsp;&nbsp; }<br>
1141 :     }<br>
1142 :     <br>
1143 :     /**<br>
1144 :     &nbsp;* Non-multiplexing part that relies on the DefaultFocusable
1145 :     service<br>
1146 :     &nbsp;* to give focus to its composite.<br>
1147 :     &nbsp;*/<br>
1148 :     public class Page2 {<br>
1149 :     &nbsp;&nbsp;&nbsp; Text textField;<br>
1150 :     &nbsp;&nbsp;&nbsp; <br>
1151 :     &nbsp;&nbsp;&nbsp; public Page(Composite control) {<br>
1152 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; textField = new Text(control, SWT.NONE);<br>
1153 :     &nbsp;&nbsp;&nbsp; }<br>
1154 :     }<br>
1155 :     <br>
1156 :     /**<br>
1157 :     &nbsp;* Multiplexing part that contains a Page, a Page2, and a checkbox.<br>
1158 :     &nbsp;* When the checkbox is selected, the first page will be active.
1159 :     When the<br>
1160 :     &nbsp;* checkbox is deselected, the second page will be active. Calling
1161 :     setFocus<br>
1162 :     &nbsp;* on the MultiplexingView will always give focus to the active
1163 :     page.<br>
1164 :     &nbsp;*/<br>
1165 :     public class MultiplexingView implements IDisposable, IAdaptable {<br>
1166 :     &nbsp;&nbsp;&nbsp; private IContainer page1;<br>
1167 :     &nbsp;&nbsp;&nbsp; private IContainer page2;<br>
1168 :     <br>
1169 :     &nbsp;&nbsp;&nbsp; // Helper class that implements the IMultiplexer
1170 :     interface<br>
1171 :     &nbsp;&nbsp;&nbsp; private Multiplexer multiplexer = new Multiplexer();<br>
1172 :     &nbsp;&nbsp;&nbsp; private Button checkBox;<br>
1173 :     <br>
1174 :     &nbsp;&nbsp;&nbsp; public MultiplexingView(Composite myControl) {<br>
1175 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; myControl.setLayout(new RowLayout());<br>
1176 :     <br>
1177 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; checkBox = new Button(myControl,
1178 :     SWT.CHECK);<br>
1179 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; checkBox.addSelectionListener(new
1180 :     SelectionAdapter() {<br>
1181 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; public void
1182 :     widgetSelected(SelectionEvent e) {<br>
1183 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
1184 :     updateActivePart();<br>
1185 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
1186 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; });<br>
1187 :     <br>
1188 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; checkBox.setText("Activate part 1");<br>
1189 :     <br>
1190 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Create the child controls<br>
1191 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; IMutableComponentFactory childFactory =
1192 :     Components.getFactory().createDerivedFactory();<br>
1193 :     <br>
1194 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Use the CompositeAdapter class we
1195 :     created earlier in order to provide each page<br>
1196 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // with its own control.<br>
1197 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; childFactory.addComponentInstance(new
1198 :     CompositeAdapter(myControl));<br>
1199 :     <br>
1200 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; page1 =
1201 :     childFactory.createContainer(Page.class);<br>
1202 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; page2 =
1203 :     childFactory.createContainer(Page2.class);<br>
1204 :     <br>
1205 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Activate the initial part<br>
1206 :     </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; updateActivePart();</code><br>
1207 :     <code>&nbsp;&nbsp;&nbsp; }<br>
1208 :     <br>
1209 :     &nbsp;&nbsp;&nbsp; private final void updateActivePart() {<br>
1210 :     </code><code>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
1211 :     (checkBox.getSelection()) {<br>
1212 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
1213 :     multiplexer.setCurrent(page1);<br>
1214 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
1215 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
1216 :     multiplexer.setCurrent(page2);<br>
1217 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</code><br>
1218 :     <code>&nbsp;&nbsp;&nbsp; }<br>
1219 :     <br>
1220 :     &nbsp;&nbsp;&nbsp; /**<br>
1221 :     &nbsp;&nbsp;&nbsp;&nbsp; * In order to indicate that this is a
1222 :     multiplexing part, we need to implement<br>
1223 :     &nbsp;&nbsp;&nbsp;&nbsp; * the IMultiplexer adapter. We simply redirect
1224 :     to the multiplexer object.<br>
1225 :     &nbsp;&nbsp;&nbsp;&nbsp; */<br>
1226 :     &nbsp;&nbsp;&nbsp; public Object getAdapter(Class adapterType) {<br>
1227 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if (adapterType == IMultiplexer.class) {<br>
1228 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; return multiplexer;<br>
1229 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br>
1230 :     &nbsp;&nbsp;&nbsp; }<br>
1231 :     <br>
1232 :     &nbsp;&nbsp;&nbsp; /**<br>
1233 :     &nbsp;&nbsp;&nbsp;&nbsp; * Release any resources allocated in the
1234 :     constructor<br>
1235 :     &nbsp;&nbsp;&nbsp;&nbsp; */<br>
1236 :     &nbsp;&nbsp;&nbsp; public void dispose() {<br>
1237 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; page1.dispose();<br>
1238 :     &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; page2.dispose();<br>
1239 :     &nbsp;&nbsp;&nbsp; }<br>
1240 :     }</code><br>
1241 :     </div>
1242 :     <br>
1243 :     Notice that MultiplexingView itself doesn't know about the IFocusable
1244 :     interface, however if we were to create a MultiplexingView and ask its
1245 :     container for an IFocusable interface, we would get an interface that
1246 :     behaves as expected. <br>
1247 :     <br>
1248 :     <div style="margin-left: 40px;"><code></code><code>// Stupid example
1249 :     that creates a MultiplexingView, gives it focus, then destroys it<br>
1250 :     <br>
1251 :     // Create a MultiplexingView</code><br>
1252 :     <code>IMutableComponentFactory childFactory =
1253 :     Components.getFactory().createDerivedFactory();<br>
1254 :     </code><code>childFactory.addComponentInstance(new
1255 :     CompositeAdapter(myControl));<br>
1256 :     <br>
1257 :     IContainer viewContainer =
1258 :     childFactory.createContainer(MultiplexingView.class);<br>
1259 :     <br>
1260 :     // Give focus to the active part<br>
1261 :     IFocusable focusable = viewContainer.getAdapter(IFocusable.class);<br>
1262 :     focusable.setFocus();<br>
1263 :     </code><code></code><code><br>
1264 :     // Destroy the view<br>
1265 :     viewContainer.dispose();<br>
1266 :     </code><code></code></div>
1267 :     <code>&nbsp;&nbsp;&nbsp; <br>
1268 :     </code>This example also shows how the same service can work for both
1269 :     multiplexing and non-multiplexing parts. The Page2 class doesn't
1270 :     implement IFocusable or IMultiplexing part, but we are still able to
1271 :     ask for an IFocusable interface and use it to give focus to the part.<br>
1272 :     <h1><a class="mozTocH1" name="mozTocId707022"></a>3.0 Views and Editors
1273 :     as Components</h1>
1274 :     TODO<br>
1275 :     <br>
1276 :     <br>
1277 :     </body>
1278 :     </html>