| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| |
| <head> |
| <title>Rich Client Platform</title> |
| <link href="../default_style.css" rel="stylesheet"> |
| <link href="java2html.css" rel="stylesheet"> |
| </head> |
| |
| <body> |
| |
| <div align="right"><font face="Times New Roman, Times, serif" size="2">Copyright |
| © 2004-2006 Ed Burnette.</font> |
| <table border="0" cellspacing="0" cellpadding="2" width="100%"> |
| <tbody> |
| <tr> |
| <td align="left" valign="top" colspan="2" bgcolor="#0080c0"><b><font |
| face="Arial,Helvetica"><font color="#ffffff">Eclipse Article</font></font></b></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div align="left"> |
| <h1 title="RCP Tutorial"><img src="../images/Idea.jpg" align="middle" |
| width="120" height="86" alt=""></h1> |
| </div> |
| <h1 align="center">Rich Client Tutorial Part 2</h1> |
| <p class="summary">The Rich Client Platform (RCP) allows you to build |
| Java applications that can compete with native applications on any |
| platform. Part 1 of the tutorial introduced you to the platform and the |
| steps used to build the smallest possible RCP program. In part 2 we'll |
| look at what we did in more detail and introduce some of the |
| configuration classes that let you take control of much of the layout |
| and functionality of an RCP application. This part has been updated for |
| Eclipse 3.1.2</p> |
| <p><b>By Ed Burnette, SAS</b><br> |
| <font size="-1">August 9, 2004<br> |
| <font size="-1"><b>Updated for 3.1.2:</b> February 6, 2006</font> </font></p> |
| <hr width="100%"> |
| |
| <h2>Introduction</h2> |
| <p>In early versions of Eclipse, many functions of the IDE were |
| hard-wired into the code. These included the name and location of the |
| File menu, the title of the Workbench Window, and the existence of the |
| status bar. This was fine for the IDE but when people started to use |
| Eclipse as a basis for non-IDE programs, sometimes these things didn't |
| make sense. Although all the source code was provided, it was |
| inconvenient to find the right places that had to be changed.</p> |
| <p>So, beginning in Eclipse 3.0, the designers refactored the API to |
| make these and other hard-wired aspects of the user interface |
| controllable through public API. Subsequent releases have fine tuned |
| that API and provided tooling in the Plug-in Development Environment |
| (PDE) to lower the barriers to getting started using it. However, you'll |
| eventually need to look behind the PDE wizards and editors to really |
| understand what is going on.</p> |
| <p>In this part we'll examine the code and configuration files created |
| in Part 1 of the tutorial. To keep the parts separate I've recreated the |
| examples for each part under a different name. All the sample code for |
| Part 2 may be found in the <a href="part2.zip">part2.zip archive file</a>. |
| </p> |
| |
| <p><img src="../images/note.gif" alt="Note: " width="62" height="13"> If |
| you're following along with this tutorial in Eclipse and you're thinking |
| of just renaming your old project, I don't recommend it. In Eclipse 3.1, |
| Refactor > Rename does not work well on plug-in projects due to all |
| the internal references in XML files and strings that don't participate. |
| Hopefully this will be fixed in a future release.</p> |
| |
| <p>Before we go any further let's clear up some possible confusion about |
| the relationship between Applications, Workbenches, and Workbench |
| Windows.</p> |
| |
| <h2>Applications, Workbenches, and Workbench Windows</h2> |
| <p>The Application is a class you create that acts as your RCP program's |
| main routine. You can think of it as the controller for the program. |
| Just like the controller in a Model2 architecture, it is short and sweet |
| and doesn't change significantly for different projects. All it does is |
| create a Workbench and attach another class called a Workbench Advisor |
| to it (Workbench Advisors will be covered more later).</p> |
| <p>The Workbench is declared and maintained for you as part of the RCP |
| framework. There is only one Workbench but it can have more than one |
| visible top-level Workbench Window. For example, in the Eclipse IDE, |
| when you first start Eclipse you will see one Workbench Window, but if |
| you select <b>Window > New Window</b> a second window pops up -- two |
| Workbench Windows, but only one Workbench.</p> |
| |
| <p>Ok, now that that's out of the way, let's see what those PDE wizards |
| did for us, starting with the plug-in manifest.</p> |
| |
| <h2>Plug-in manifest</h2> |
| <p>The plug-in manifest ties all the code and resources together. When |
| you first create a plug-in, Eclipse will create and open the manifest |
| for you automatically. The manifest is split into two files: MANIFEST.MF |
| and plugin.xml. PDE provides a fancy editor to modify the options stored |
| in these files (see Figure 1) but also allows you to edit the source |
| directly.</p> |
| |
| <img src="images/manifest-editor-overview_s.png" alt=""> |
| <p><b> Figure 1. The plug-in manifest editor provides a single interface |
| for editing the manifest and related files. The tabs along the bottom of |
| the editor access all the different sections in the GUI or the raw text |
| files.</b></p> |
| |
| |
| <h3>MANIFEST.MF</h3> |
| <p>The OSGi bundle manifest is stored in MANIFEST.MF. OSGi is the name |
| of a standard that Eclipse uses for dynamically loading plug-ins (see |
| refererences). Listing 1 shows the OSGi bundle manifest generated by the |
| plug-in wizard. Everything in this file can be edited by the Manifest |
| editor, so there should be no need to edit it by hand. However if you |
| need to, just double-click it in the Package Explorer to bring up the |
| Manifest editor, then click on the MANIFEST.MF tab in the editor to see |
| and modify the source.</p> |
| |
| <p><img src="../images/note.gif" alt="Note: " width="62" height="13"> |
| For backwards compatability with Eclipse 2.1, Eclipse will recognize and |
| load plug-ins that do not use MANIFEST.MF. However, this incurs a small |
| performance penalty and is not recommended for plug-ins targeting |
| Eclipse 3.0 and later.</p> |
| |
| <p><b>Listing 1. MANIFEST.MF </b></p> |
| |
| <pre> |
| Manifest-Version: <font class="java5">1.0</font> |
| Bundle-ManifestVersion: <font class="java5">2</font> |
| Bundle-Name: <font class="java5">Part2 Plug-in</font> |
| Bundle-SymbolicName: <font class="java5">org.eclipse.ui.tutorials.rcp.part2; singleton:=true</font> |
| Bundle-Version: <font class="java5">1.0.0</font> |
| Bundle-Activator: <font class="java5">org.eclipse.ui.tutorials.rcp.part2.Part2Plugin</font> |
| Bundle-Localization: <font class="java5">plugin</font> |
| Require-Bundle: <font class="java5">org.eclipse.ui, |
| org.eclipse.core.runtime</font> |
| Eclipse-AutoStart: <font class="java5">true</font> |
| </pre> |
| |
| <h3>plugin.xml</h3> |
| <p>The Eclipse extension manifest is called plugin.xml. It's used for |
| defining and using Eclipse extension points, so if you're not using |
| extension points then this file may be omitted. Extension points are the |
| fundamental way that Eclipse plug-ins are tied together so if you're not |
| familiar with them see one of the articles in the Reference section. |
| Listing 2 shows the plugin.xml file created by the PDE wizard.</p> |
| |
| <p><b>Listing 2. plugin.xml </b></p> |
| <pre> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <?eclipse version="3.0"?> |
| <plugin> |
| |
| <extension |
| id=<font class="java5">"application"</font> |
| point=<font class="java5">"org.eclipse.core.runtime.applications"</font>> |
| <application> |
| <run |
| class=<font class="java5">"org.eclipse.ui.tutorials.rcp.part2.Application"</font>> |
| </run> |
| </application> |
| </extension> |
| <extension |
| point=<font class="java5">"org.eclipse.ui.perspectives"</font>> |
| <perspective |
| name=<font class="java5">"Part2 Perspective"</font> |
| class=<font class="java5">"org.eclipse.ui.tutorials.rcp.part2.Perspective"</font> |
| id=<font class="java5">"org.eclipse.ui.tutorials.rcp.part2.perspective"</font>> |
| </perspective> |
| </extension> |
| <extension |
| id=<font class="java5">"product"</font> |
| point=<font class="java5">"org.eclipse.core.runtime.products"</font>> |
| <product |
| application=<font class="java5">"org.eclipse.ui.tutorials.rcp.part2.application"</font> |
| name=<font class="java5">"RCP Tutorial 2"</font>/> |
| </extension> |
| |
| </plugin> |
| </pre> |
| |
| <p>The class name of the main program is defined with the <code>org.eclipse.core.runtime.applications</code> |
| extension.</p> |
| <p><img src="../images/note.gif" alt="Note: " width="62" height="13"> |
| Although it's not an absolute requirement, I recommend keeping your id's |
| and your class names the same except possibly for case. For historical |
| reasons, Eclipse prepends the plug-in's id to the id of your top level |
| plug-in elements (like <code>extension</code>). For example, even though |
| the plugin.xml in listing 2 says <code>id="application"</code>, the |
| fully qualified id for that extension is <code>org.eclipse.ui.tutorials.rcp.part2.application</code>. |
| Since the perspective's id is written on a sub-element (<code>perspective</code>) |
| it has to be spelled out completely in the manifest (<code>org.eclipse.ui.tutorials.rcp.part2.perspective</code>). |
| By convention only, package names and ids are lower case and class names are Pascal Case. |
| </p> |
| <h2>The main program</h2> |
| <p>The <code>org.eclipse.core.runtime.applications</code> extension |
| tells the Eclipse runtime the name of your main program. This is a class |
| that implements <code>IPlatformRunnable</code> and a <code>run()</code> |
| method. Listing 3 shows the simple implementation supplied by the |
| plug-in wizard.</p> |
| |
| <p><b>Listing 3. Application.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.core.runtime.IPlatformRunnable;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.swt.widgets.Display;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.PlatformUI;<br /> |
| <br /> |
| </font><font class="java14">/**<br /> |
| * This class controls all aspects of the application's execution<br /> |
| */<br /> |
| </font><font class="java4">public class </font><font class="java10">Application |
| </font><font class="java4">implements </font><font class="java10">IPlatformRunnable |
| </font><font class="java8">{<br /> |
| <br /> |
|   </font><font class="java2">/* (non-Javadoc)<br /> |
|    * @see |
| org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)<br /> |
|    */<br /> |
|   </font><font class="java4">public </font><font class="java10">Object |
| run</font><font class="java8">(</font><font class="java10">Object args</font><font |
| class="java8">) </font><font class="java4">throws </font><font |
| class="java10">Exception </font><font class="java8">{<br /> |
|     </font><font class="java10">Display display = |
| PlatformUI.createDisplay</font><font class="java8">()</font><font |
| class="java10">;<br /> |
|     </font><font class="java4">try </font><font |
| class="java8">{<br /> |
|       </font><font class="java9">int </font><font |
| class="java10">returnCode = PlatformUI.createAndRunWorkbench</font><font |
| class="java8">(</font><font class="java10">display, </font><font |
| class="java4">new </font><font class="java10">ApplicationWorkbenchAdvisor</font><font |
| class="java8">())</font><font class="java10">;<br /> |
|       </font><font class="java4">if </font><font |
| class="java8">(</font><font class="java10">returnCode == |
| PlatformUI.RETURN_RESTART</font><font class="java8">) {<br /> |
|         </font><font class="java4">return |
| </font><font class="java10">IPlatformRunnable.EXIT_RESTART;<br /> |
|       </font><font class="java8">}<br /> |
|       </font><font class="java4">return </font><font |
| class="java10">IPlatformRunnable.EXIT_OK;<br /> |
|     </font><font class="java8">} </font><font |
| class="java4">finally </font><font class="java8">{<br /> |
|       </font><font class="java10">display.dispose</font><font |
| class="java8">()</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
|   }<br /> |
| }</font></tt> |
| |
| <h2>The default perspective</h2> |
| |
| <p>A Perspective is a set of visible views, editors, and menus including |
| their positions and sizes. In an RCP program you must define at least |
| one perspective and make it the default. Perspectives are created by |
| implementing <code>IPerspectiveFactory</code> using the class name |
| referred to by the <code>org.eclipse.ui.perspectives</code> extension. |
| See Listing 4 for the implementation provided by the plug-in wizard. The |
| important part of this interface is the <code>createInitialLayout()</code> |
| method where you position and open any views and/or editors you'd like |
| the user to start with. So far in this example we haven't created any |
| views so it's a pretty boring perspective.</p> |
| |
| <p><b>Listing 4. Perspective.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.IPageLayout;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.IPerspectiveFactory;<br /> |
| <br /> |
| </font><font class="java4">public class </font><font class="java10">Perspective |
| </font><font class="java4">implements </font><font class="java10">IPerspectiveFactory |
| </font><font class="java8">{<br /> |
| <br /> |
|   </font><font class="java4">public </font><font class="java9">void |
| </font><font class="java10">createInitialLayout</font><font |
| class="java8">(</font><font class="java10">IPageLayout layout</font><font |
| class="java8">) {<br /> |
|   }<br /> |
| }</font></tt> |
| |
| <h2>The Advisor classes</h2> |
| <p>The main program referenced a class called <code>ApplicationWorkbenchAdvisor</code>. |
| This is one of three Advisor classes that you use to configure all |
| aspects of the Workbench such as the title, menu bars, and so on. <b>These |
| are the most important classes for an RCP developer to understand.</b> |
| You extend the base version of the class, for example <code>WorkbenchAdvisor</code>, |
| in your RCP application and override one or more of the methods to set |
| whatever options you want. Let's examine these classes now in more |
| detail.</p> |
| |
| <h3>Workbench Advisor</h3> |
| <p>Methods in this class are called from the platform to notify you at |
| every point in the lifecycle of the Workbench. They also provide a way |
| to handle exceptions in the event loop, and provide important parameters |
| to the Workbench such as the default perspective. With the exception of |
| <code>createWorkbenchWindowAdvisor()</code> and <code>getInitialWindowPerspectiveId()</code>, |
| the methods on <code>WorkbenchAdvisor</code> do not have to be |
| overridden. Listing 5 shows the implementation that was provided by the |
| plug-in wizard.</p> |
| |
| <p><b>Listing 5. ApplicationWorkbenchAdvisor.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.IWorkbenchWindowConfigurer;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.WorkbenchAdvisor;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.WorkbenchWindowAdvisor;<br /> |
| <br /> |
| </font><font class="java4">public class </font><font class="java10">ApplicationWorkbenchAdvisor |
| </font><font class="java4">extends </font><font class="java10">WorkbenchAdvisor |
| </font><font class="java8">{<br /> |
| <br /> |
|   </font><font class="java4">private static final </font><font |
| class="java10">String PERSPECTIVE_ID = </font><font class="java5">"org.eclipse.ui.tutorials.rcp.part2.perspective"</font><font |
| class="java10">;<br /> |
| <br /> |
|     </font><font class="java4">public </font><font |
| class="java10">WorkbenchWindowAdvisor createWorkbenchWindowAdvisor</font><font |
| class="java8">(</font><font class="java10">IWorkbenchWindowConfigurer |
| configurer</font><font class="java8">) {<br /> |
|         </font><font class="java4">return |
| new </font><font class="java10">ApplicationWorkbenchWindowAdvisor</font><font |
| class="java8">(</font><font class="java10">configurer</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
| <br /> |
|   </font><font class="java4">public </font><font class="java10">String |
| getInitialWindowPerspectiveId</font><font class="java8">() {<br /> |
|     </font><font class="java4">return </font><font |
| class="java10">PERSPECTIVE_ID;<br /> |
|   </font><font class="java8">}<br /> |
| }</font></tt> |
| |
| <p><img src="../images/note.gif" alt="Note: " width="62" height="13"> |
| Why not an interface? You'll notice that <code>WorkbenchAdvisor</code> |
| is an abstract class. For the most part, Eclipse APIs shun abstract |
| classes in favor of interfaces and base classes that implement those |
| interfaces. In this case, the designers intend for <code>WorkbenchAdvisor</code> |
| to <i>always</i> be implemented by the RCP application, and the base |
| class doesn't contain any significant functionality. Also it is very |
| likely that new methods will need to be added to the base class in the |
| future (something that is difficult using interfaces). So this was a |
| deliberate design choice. See the article on evolving Java APIs in the |
| reference section for more tips.</p> |
| |
| |
| <h4>Workbench lifecycle hooks</h4> |
| |
| <p>The Workbench Advisor class has several methods that are called at |
| defined points in the Workbench's lifecycle (see Table 1). By overriding |
| these you can run whatever code you want at these points.</p> |
| |
| <p><b>Table 1. Workbench lifecycle hooks provided by <code>WorkbenchAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>initialize</td> |
| <td>Called first to perform any setup such as parsing the command |
| line, registering adapters, declaring images, etc..</td> |
| <td><code>IWorkbenchConfigurer</code></td> |
| </tr> |
| <tr> |
| <td>preStartup</td> |
| <td>Called after initialization but before the first window is opened. |
| May be used to set options affecting which editors and views are |
| initially opened.</td> |
| <td> </td> |
| </tr> |
| <tr> |
| <td>postStartup</td> |
| <td>Called after all windows have been opened or restored, but before |
| the event loop starts. It can be used to start automatic processes and |
| to open tips or other windows.</td> |
| <td> </td> |
| </tr> |
| <tr> |
| <td>preShutdown</td> |
| <td>Called after the event loop has terminated but before any windows |
| have been closed.</td> |
| <td> </td> |
| </tr> |
| <tr> |
| <td>postShutdown</td> |
| <td>Called after all windows are closed during Workbench shutdown. |
| This can be used to save the current application state and clean up |
| anything created by <code>initialize</code>.</td> |
| <td> </td> |
| </tr> |
| </table> |
| |
| |
| <h4>Event loop hooks</h4> |
| |
| <p>The event loop is the code that is running most of the time during |
| the life of the Workbench. It handles all user inputs and dispatches |
| them to the right listeners. RCP provides a couple of hooks to handle |
| crashes and perform work during idle time (see Table 2). Note however |
| that the Jobs interface (see References) is a better way of performing |
| long running work than this idle hook.</p> |
| |
| <p><b>Table 2. Event loop hooks provided by <code>WorkbenchAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>eventLoopException</td> |
| <td>Called if there is an unhandled exception in the event loop. The |
| default implementation will log the error.</td> |
| <td><code>Throwable</code></td> |
| </tr> |
| <tr> |
| <td>eventLoopIdle</td> |
| <td>Called when the event loop has nothing to do.</td> |
| <td><code>Display</code></td> |
| </tr> |
| </table> |
| |
| <h4>Information getting hooks</h4> |
| <p>Next, there are few methods you can implement that the platform will |
| call to get information about your application (see Table 3). The most |
| important one (and the only one that is not optional) is <code>getInitialWindowPerspectiveId</code>. |
| We used this in Listing 5 to return the id of the starting perspective.</p> |
| |
| <p><b>Table 3. Information request methods you can override in <code>WorkbenchAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>getDefaultPageInput</td> |
| <td>Return the default input for new workbench pages. Defaults to |
| null.</td> |
| <td> </td> |
| </tr> |
| <tr> |
| <td>getInitialWindowPerspectiveId</td> |
| <td>Return the initial perspective used for new workbench windows. |
| This is a required function that has no default.</td> |
| <td> </td> |
| </tr> |
| <tr> |
| <td>getMainPreferencePageId</td> |
| <td>Return the preference page that should be displayed first. |
| Defaults to null, meaning the pages should be arranged alphabetically. |
| </td> |
| <td> </td> |
| </tr> |
| </table> |
| |
| <h4>Advanced configuration</h4> |
| <p>The <code>WorkbenchAdvisor</code> events above should be sufficient |
| for most applications, but just in case, RCP provides another method to |
| take complete control of how your application windows and controls are |
| created. It's listed in Table 4 for completeness but I don't expect many |
| programs will need it.</p> |
| |
| <p><b>Table 4. Advanced methods in <code>org.eclipse.ui.application.WorkbenchAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>openWindows</td> |
| <td>Open all Workbench windows on startup. The default implementation |
| tries to restore the previously saved workbench state.</td> |
| <td> </td> |
| </tr> |
| </table> |
| |
| |
| <h3>Workbench Window Advisor</h3> |
| <p>This class is used to control the status line, toolbar, title, window |
| size, and other things you'll almost certainly want to customize. You |
| can also use it to hook into all the various lifecycle events of the |
| Workbench Windows. Listing 6 shows the implementation provided by the |
| plug-in wizard.</p> |
| |
| <p><b>Listing 6. ApplicationWorkbenchWindowAdvisor.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.swt.graphics.Point;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.ActionBarAdvisor;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.IActionBarConfigurer;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.IWorkbenchWindowConfigurer;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.WorkbenchWindowAdvisor;<br /> |
| <br /> |
| </font><font class="java4">public class </font><font class="java10">ApplicationWorkbenchWindowAdvisor |
| </font><font class="java4">extends </font><font class="java10">WorkbenchWindowAdvisor |
| </font><font class="java8">{<br /> |
| <br /> |
|     </font><font class="java4">public </font><font |
| class="java10">ApplicationWorkbenchWindowAdvisor</font><font |
| class="java8">(</font><font class="java10">IWorkbenchWindowConfigurer |
| configurer</font><font class="java8">) {<br /> |
|         </font><font class="java4">super</font><font |
| class="java8">(</font><font class="java10">configurer</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
| <br /> |
|     </font><font class="java4">public </font><font |
| class="java10">ActionBarAdvisor createActionBarAdvisor</font><font |
| class="java8">(</font><font class="java10">IActionBarConfigurer |
| configurer</font><font class="java8">) {<br /> |
|         </font><font class="java4">return |
| new </font><font class="java10">ApplicationActionBarAdvisor</font><font |
| class="java8">(</font><font class="java10">configurer</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
|     <br /> |
|     </font><font class="java4">public </font><font |
| class="java9">void </font><font class="java10">preWindowOpen</font><font |
| class="java8">() {<br /> |
|         </font><font class="java10">IWorkbenchWindowConfigurer |
| configurer = getWindowConfigurer</font><font class="java8">()</font><font |
| class="java10">;<br /> |
|         configurer.setInitialSize</font><font |
| class="java8">(</font><font class="java4">new </font><font |
| class="java10">Point</font><font class="java8">(</font><font |
| class="java7">400</font><font class="java10">, </font><font |
| class="java7">300</font><font class="java8">))</font><font |
| class="java10">;<br /> |
|         configurer.setShowCoolBar</font><font |
| class="java8">(</font><font class="java4">false</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|         configurer.setShowStatusLine</font><font |
| class="java8">(</font><font class="java4">false</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|         configurer.setTitle</font><font |
| class="java8">(</font><font class="java5">"Hello RCP"</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
| }</font></tt> |
| |
| <p>Methods on WorkbenchWindowAdvisor (see Table 5 and Table 6) will all |
| need access to a Configurer interface (in this case, <code>IWorkbenchWindowConfigurer</code>) |
| in order to do anything so they're expected to call <code>getWindowConfigurer()</code> |
| to fetch it. You call methods on the Configurer interfaces to actually |
| change the options. These interfaces are not covered in any detail in |
| this tutorial but you can refer to their Javadoc for more information.</p> |
| |
| <p><b>Table 5. Workbench window lifecycle hooks provided by <code>WorkbenchWindowAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>preWindowOpen</td> |
| <td>Called in the constructor of the Workbench Window. Use this method |
| to set options such as whether or not the window will have a menu bar. |
| However none of the window's widgets have been created yet so they |
| can't be referenced in this method.</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>postWindowRestore</td> |
| <td>Optionally called for cases when a window has been restored from |
| saved state but before it is opened.</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>postWindowCreate</td> |
| <td>Called after a window has been restored from saved state or |
| created from scratch but before it is opened.</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>openIntro</td> |
| <td>Called immediately before a window is opened in order to create |
| the Intro component (if any).</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>postWindowOpen</td> |
| <td>Called right after the Workbench window is opened. Can be used to |
| tweak any of the window's widgets, for example to set a title or |
| change its size.</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>preWindowShellClose</td> |
| <td>Called before the Workbench window is closed (technically, before |
| its shell is closed). This is the only function that can veto the |
| close, so it's a good place for an "Are you sure" kind of dialog.</td> |
| <td><code></code></td> |
| </tr> |
| <tr> |
| <td>postWindowClose</td> |
| <td>Called after the Workbench window is closed. Can be used to clean |
| up anything created by <code>preWindowOpen</code>.</td> |
| <td><code></code></td> |
| </tr> |
| </table> |
| |
| |
| <p><b>Table 6. Advanced methods in <code>WorkbenchWindowAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>createWindowContents</td> |
| <td>Creates the contents of one window. Override this method to define |
| custom contents and layout.</td> |
| <td><code>Shell</code></td> |
| </tr> |
| <tr> |
| <td>createEmptyWindowContents</td> |
| <td>Like <code>createWindowContents</code>, but used when the window |
| has no open pages. Override this method to show something other than |
| the default window background.</td> |
| <td><code>Composite</code></td> |
| </tr> |
| </table> |
| |
| <h3>ActionBar Advisor</h3> |
| <p>In Eclipse jargon, "action bar" is a catch-all term for menus, |
| toolbars, and status bars. The ActionBar Advisor handles creating |
| Actions within these locations. A plug-in can also contribute actions |
| dynamically with its plugin.xml file. See Listing 7 for the |
| implementation provided by the plug-in wizard and Table 7 for the |
| methods.</p> |
| |
| <p><img src="../images/note.gif" alt="Note: " width="62" height="13">The |
| whole action, command and keybinding system is a bit of a mess in |
| Eclipse 3.1. For example you can't add combo boxes to action bars, and |
| plugin.xml can't contribute actions to the status bar. Getting key |
| bindings to work involves multiple steps. Hopefully this will be cleaned |
| up in a future release.</p> |
| |
| <p><b>Listing 7. ApplicationActionBarAdvisor.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.jface.action.IMenuManager;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.IWorkbenchWindow;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.ActionBarAdvisor;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.application.IActionBarConfigurer;<br /> |
| <br /> |
| </font><font class="java4">public class </font><font class="java10">ApplicationActionBarAdvisor |
| </font><font class="java4">extends </font><font class="java10">ActionBarAdvisor |
| </font><font class="java8">{<br /> |
| <br /> |
|     </font><font class="java4">public </font><font |
| class="java10">ApplicationActionBarAdvisor</font><font class="java8">(</font><font |
| class="java10">IActionBarConfigurer configurer</font><font |
| class="java8">) {<br /> |
|         </font><font class="java4">super</font><font |
| class="java8">(</font><font class="java10">configurer</font><font |
| class="java8">)</font><font class="java10">;<br /> |
|     </font><font class="java8">}<br /> |
| <br /> |
|     </font><font class="java4">protected </font><font |
| class="java9">void </font><font class="java10">makeActions</font><font |
| class="java8">(</font><font class="java10">IWorkbenchWindow window</font><font |
| class="java8">) {<br /> |
|     }<br /> |
| <br /> |
|     </font><font class="java4">protected </font><font |
| class="java9">void </font><font class="java10">fillMenuBar</font><font |
| class="java8">(</font><font class="java10">IMenuManager menuBar</font><font |
| class="java8">) {<br /> |
|     }<br /> |
|     <br /> |
| }</font></tt> |
| |
| <p><b>Table 7. Methods you can override in <code>ActionBarAdvisor</code>. |
| </b></p> |
| <table border="1"> |
| <tr> |
| <th>Method</th> |
| <th>Description</th> |
| <th>Parameter(s)</th> |
| </tr> |
| <tr> |
| <td>makeActions</td> |
| <td>Called to create the actions used in the fill methods.</td> |
| <td><code>IWorkbenchWindow</code></td> |
| </tr> |
| <tr> |
| <td>fillMenuBar</td> |
| <td>Called to fill the menu bar with the main menus for the window.</td> |
| <td><code>IMenuManager</code></td> |
| </tr> |
| <tr> |
| <td>fillCoolBar</td> |
| <td>Called to fill the cool bar with the main toolbars for the window.</td> |
| <td><code>ICoolBarManager</code></td> |
| </tr> |
| <tr> |
| <td>fillStatusLine</td> |
| <td>Called to fill the status line with the main status line |
| contributions for the window.</td> |
| <td><code>IStatusLineManager</code></td> |
| </tr> |
| <tr> |
| <td>isApplicationMenu</td> |
| <td>Return true if the menu is one of yours. OLE specific; see Javadoc |
| for details.</td> |
| <td><code>String</code></td> |
| </tr> |
| |
| </table> |
| |
| <h2>Plug-in class</h2> |
| <p>The plug-in class is an optional singleton class that can be used to |
| store global information for the plug-in. It's also a convenient place |
| to put a few static utility functions used by other classes in the |
| plug-in. See Listing 8 for the plug-in class that was created for us by |
| the plug-in wizard.</p> |
| |
| <p><b>Listing 8. Part2Plugin.java </b></p> |
| |
| <tt class="java"><font class="java4">package </font><font class="java10">org.eclipse.ui.tutorials.rcp.part2;<br /> |
| <br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.ui.plugin.*;<br /> |
| </font><font class="java4">import </font><font class="java10">org.eclipse.jface.resource.ImageDescriptor;<br /> |
| </font><font class="java4">import </font><font class="java10">org.osgi.framework.BundleContext;<br /> |
| <br /> |
| </font><font class="java14">/**<br /> |
| * The main plugin class to be used in the desktop.<br /> |
| */<br /> |
| </font><font class="java4">public class </font><font class="java10">Part2Plugin |
| </font><font class="java4">extends </font><font class="java10">AbstractUIPlugin |
| </font><font class="java8">{<br /> |
| <br /> |
|   </font><font class="java3">//The shared instance.<br /> |
|   </font><font class="java4">private static </font><font |
| class="java10">Part2Plugin plugin;<br /> |
|   <br /> |
|   </font><font class="java14">/**<br /> |
|    * The constructor.<br /> |
|    */<br /> |
|   </font><font class="java4">public </font><font class="java10">Part2Plugin</font><font |
| class="java8">() {<br /> |
|     </font><font class="java10">plugin = </font><font |
| class="java4">this</font><font class="java10">;<br /> |
|   </font><font class="java8">}<br /> |
| <br /> |
|   </font><font class="java14">/**<br /> |
|    * This method is called upon plug-in activation<br /> |
|    */<br /> |
|   </font><font class="java4">public </font><font class="java9">void |
| </font><font class="java10">start</font><font class="java8">(</font><font |
| class="java10">BundleContext context</font><font class="java8">) </font><font |
| class="java4">throws </font><font class="java10">Exception </font><font |
| class="java8">{<br /> |
|     </font><font class="java4">super</font><font |
| class="java10">.start</font><font class="java8">(</font><font |
| class="java10">context</font><font class="java8">)</font><font |
| class="java10">;<br /> |
|   </font><font class="java8">}<br /> |
| <br /> |
|   </font><font class="java14">/**<br /> |
|    * This method is called when the plug-in is stopped<br /> |
|    */<br /> |
|   </font><font class="java4">public </font><font class="java9">void |
| </font><font class="java10">stop</font><font class="java8">(</font><font |
| class="java10">BundleContext context</font><font class="java8">) </font><font |
| class="java4">throws </font><font class="java10">Exception </font><font |
| class="java8">{<br /> |
|     </font><font class="java4">super</font><font |
| class="java10">.stop</font><font class="java8">(</font><font |
| class="java10">context</font><font class="java8">)</font><font |
| class="java10">;<br /> |
|     plugin = </font><font class="java4">null</font><font |
| class="java10">;<br /> |
|   </font><font class="java8">}<br /> |
| <br /> |
|   </font><font class="java14">/**<br /> |
|    * Returns the shared instance.<br /> |
|    */<br /> |
|   </font><font class="java4">public static </font><font |
| class="java10">Part2Plugin getDefault</font><font class="java8">() {<br /> |
|     </font><font class="java4">return </font><font |
| class="java10">plugin;<br /> |
|   </font><font class="java8">}<br /> |
| <br /> |
|   </font><font class="java14">/**<br /> |
|    * Returns an image descriptor for the image file at the |
| given<br /> |
|    * plug-in relative path.<br /> |
|    *<br /> |
|    * </font><font class="java11">@param </font><font |
| class="java14">path the path<br /> |
|    * </font><font class="java11">@return </font><font |
| class="java14">the image descriptor<br /> |
|    */<br /> |
|   </font><font class="java4">public static </font><font |
| class="java10">ImageDescriptor getImageDescriptor</font><font |
| class="java8">(</font><font class="java10">String path</font><font |
| class="java8">) {<br /> |
|     </font><font class="java4">return </font><font |
| class="java10">AbstractUIPlugin.imageDescriptorFromPlugin</font><font |
| class="java8">(</font><font class="java5">"org.eclipse.ui.tutorials.rcp.part2"</font><font |
| class="java10">, path</font><font class="java8">)</font><font |
| class="java10">;<br /> |
|   </font><font class="java8">}<br /> |
| }</font></tt> |
| |
| <h2>Build properties</h2> |
| <p>The build.properties file (see Listing 9) will be needed when |
| exporting the application for others to use. In particular if your |
| application needs any resources like icons they should be listed here in |
| the <code>bin.includes</code> section. The Plug-in Manifest editor |
| provides a convenient interface to modify this file that is less |
| error-prone than modifying it by hand.</p> |
| |
| <p><b>Listing 9. build.properties </b></p> |
| |
| <pre> |
| source.. = <font class="java5">src/</font> |
| output.. = <font class="java5">bin/</font> |
| bin.includes = <font class="java5">plugin.xml,\ |
| META-INF/,\ |
| .</font> |
| </pre> |
| |
| <h2>Conclusion</h2> |
| <p>In part 2 of this tutorial, we looked at some of the API of the Rich |
| Client Platform that allows you to develop customized native-looking |
| client-side Java programs. The next part will delve into branding and |
| deploying your application so others can use it. All the sample code for |
| this part is included in the <a href="part2.zip">part2.zip archive file</a> |
| that accompanies this document.</p> |
| |
| <h2>References</h2> |
| <p><a href="../Article-RCP-1/tutorial1.html"> RCP Tutorial Part 1</a><br> |
| <a href="../Article-RCP-3/tutorial3.html"> RCP Tutorial Part 3</a><br> |
| <a href="http://www.eclipse.org/rcp" target="_blank"> Eclipse Rich |
| Client Platform</a><br> |
| <a href="http://www.eclipse.org/equinox" target="_blank">The Equinox |
| project (OSGi in Eclipse)</a><br> |
| <a href="../Article-Internationalization/how2I18n.html" target="_blank"> |
| How to Internationalize your Eclipse Plug-in</a><br> |
| <a |
| href="http://www.eclipse.org/articles/Article-PDE-does-plugins/PDE-intro.html">PDE |
| Does Plug-ins</a><br> |
| <a |
| href="http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html">Notes |
| on the Eclipse Plug-in Architecture</a><br> |
| <a |
| href="http://www.eclipse.org/articles/Article-Concurrency/jobs-api.html">On |
| the Job: The Eclipse Jobs API</a><br> |
| <a |
| href="http://www.fawcette.com/javapro/2002_06/online/servlets_06_11_02/" |
| target="_blank">Almost All Java Web Apps Need Model 2 (introduction to |
| the Model 2 architecture)</a><br> |
| <a |
| href="http://www.eclipse.org/eclipse/development/java-api-evolution.html" |
| target="_blank"> Evolving Java-based APIs</a><br> |
| </p> |
| |
| |
| <p>To discuss or report problems in this article see <a |
| href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=104170">bug 104170</a>.</p> |
| |
| <p><small>IBM is trademark of International Business Machines |
| Corporation in the United States, other countries, or both.</small></p> |
| <p><small>Java and all Java-based trademarks and logos are trademarks or |
| registered trademarks of Sun Microsystems, Inc. in the United States, |
| other countries, or both.</small></p> |
| <p><small>Microsoft and Windows are trademarks of Microsoft Corporation |
| in the United States, other countries, or both.</small></p> |
| <p><small>Other company, product, and service names may be trademarks or |
| service marks of others.</small></p> |
| |
| </body> |
| |
| </html> |