| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <head> |
| <meta name="generator" content="HTML Tidy, see www.w3.org"> |
| <title>Visual Editor Tutorial</title> |
| <link rel="stylesheet" type="text/css" |
| href="../default_style.css"> |
| <style type="text/css"> |
| .PictureParagraph { margin-left: 10% } |
| .PictureStyle { border-style: ridge; border-width: 1px; padding: 1px } |
| |
| </style> |
| </head> |
| |
| <body link="#0000ff" vlink="#800080"> |
| <div align="right"> |
| <font face="Times New Roman, Times, serif" size="2">Copyright |
| © 2005 IBM and other contributors</font> |
| |
| <table border="0" cellpadding="2" cellspacing="0" width="100%"> |
| <tbody> |
| <tr> |
| <td colspan="2" align="left" bgcolor="#0080c0" valign="top"> |
| <b><font face="Arial,Helvetica"><font color="#ffffff"> Eclipse |
| Corner Article</font></font></b></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <div align="left"> |
| <h1><img src="../images/Idea.jpg" align="middle" height="86" width= |
| "120"></h1> |
| </div> |
| |
| <p> </p> |
| |
| <h1 align="center">Extending The Visual Editor:<br> |
| Enabling support for a custom widget</h1> |
| |
| <blockquote> |
| <p><b>Summary</b><br> |
| This tutorial |
| shows how to extend the Visual Editor to support a custom widget. |
| It covers topics such as adding to the Visual Editor's palette, |
| building a BeanInfo class, and working with |
| EMF .override files to |
| introduce custom editor behavior.</p> |
| <p><b>Dave Orme, db4objects</b><br> |
| <b>Gili Mendel, IBM</b><br> |
| <b>Joe Winchester, IBM</b><br> |
| <font size="-1">June 20, 2005</font></p> |
| </blockquote> |
| |
| <hr width="100%"> |
| |
| <h2><a name="Introduction"></a>Introduction</h2> |
| <p>The <a href="http://www.eclipse.org/vep">Visual Editor</a> project |
| provides reference implementations of a graphical user interface |
| builder for the JFC and SWT widget toolkits built around an extensible |
| framework. The motivation for this came from experience with |
| previous GUI builders that, while they provided high function end |
| points for particular toolkits, were unable to be adapted to support |
| custom behavior. This typically would be for areas of functionality |
| such as user defined widgets, new layout managers, or flexible code |
| generation patterns. A design goal of the Visual Editor is that is none |
| of its own custom behavior for any JFC or SWT classes is done with hard |
| coding and all logic that the VE employs to enable specific bespoke |
| function such dropping a control on a composite or showing feedback for |
| a particular layout manager is soft coded through extension points. The |
| intention is that the same techniques can be leveraged by anyone |
| wishing to employ similar techniques for their own scenario.</p> |
| <p>In this tutorial a 3.1 based Eclipse plugin <i>org.eclipse.ve.example.customwidget</i> |
| is created that illustrates some of the extension points of the visual |
| editor. To do this an SWT custom widget is built that combines a |
| Label, Text and Button in a single widget called <span |
| style="font-style: italic;">org.eclipse.ve.examples.customwidget.MyCustomPrompter</span>. </p> |
| <p><img style="width: 243px; height: 34px;" alt="CustomWidget" |
| src="images/CustomWidget.png"></p> |
| <p>MyCustomPrompter has two properties: <span |
| style="font-style: italic;">type</span> and <span |
| style="font-style: italic;">text</span>. These each have get and |
| set methods and can be used to configure the behavior of the Button and |
| the Text's text value. There is also a <span |
| style="font-style: italic;">ButtonSelectionEvent</span> event that is |
| raised when the prompter's button is pressed and listeners can register |
| for this callback using <span style="font-style: italic;">addButtonSelectionListener(ButtonSelectionListener |
| aListener);</span></p> |
| <p>In the absence of the plugin that this tutorial creates<span |
| style="font-family: monospace;">,</span> the <span |
| style="font-family: monospace;">MyCustomPrompter</span> widget can |
| still be used by a user who drops it onto an SWT composite by adding a |
| jar (or folder) containing the class to their Java project's build path<span |
| style="font-family: monospace;">.</span> Within the Visual Editor the |
| class can be selected by using <span style="font-style: italic;">ChooseBean</span> |
| from the palette to drop <span style="font-family: monospace;">MyCustomPrompter</span> |
| onto a composite. Through inheritance (<span |
| style="font-family: monospace;">MyCustomPrompter</span> extends <span |
| style="font-family: monospace;">org.eclipse.swt.widgets.Composite</span>) |
| the custom control will be rendered correctly and its properties will |
| be determined using JavaBeans<sup>TM</sup> reflection allowing it to be |
| modified using the Properties Viewer. The new event will also be |
| determined automatically through introspection by the Visual Editor and |
| available to the user to add callback logic to through the <span |
| style="font-style: italic;">Add Event</span> dialog. </p> |
| <p>This tutorial shows how to extend the edit experience by creating a |
| plugin that enables specific Visual Editor behavior over and above the |
| default that is determined through inheritance. This results in a |
| higher level edit experience for end users of the <span |
| style="font-style: italic;">MyCustomPrompter</span> class. The |
| examples given are purely for illustrative purposes only and to |
| highlight some of the available ways to extend the behavior of the |
| Visual Editor, and it is expected that the reader of this tutorial will |
| use it to learn the extension mechanism and then apply this to their |
| own custom widget or Java class. </p> |
| <h3><a name="Intro_Palette"></a>Palette</h3> |
| <p>The visual editor provides a palette of classes from which the user |
| can choose commonly used classes. The tutorial shows how to |
| create a new palette category containing the CustomWidget to allow it |
| to be brought to the user's selection and easily selected and dropped |
| without having to use <span style="font-style: italic;">ChooseBean</span> |
| and enter the class name</p> |
| <table style="text-align: left; width: 50%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before</td> |
| <td style="vertical-align: top;">With plugin showing <span |
| style="font-style: italic;">Custom</span> category with the <span |
| style="font-style: italic;">MyCustomPrompter</span> class</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><img |
| style="width: 147px; height: 241px;" alt="OriginalPalette" |
| src="images/OriginalPalette.png"><br> |
| </td> |
| <td style="vertical-align: top;"><img |
| style="width: 143px; height: 240px;" alt="NewPalette" |
| src="images/NewPalette.png"> </td> |
| </tr> |
| </tbody> |
| </table> |
| <h3><a name="Intro_Property_sheet"></a>Property sheet</h3> |
| <p><span style="font-family: monospace;">MyCustomPrompter</span> has an |
| <span style="font-style: italic;">int</span> property called <span |
| style="font-style: italic;">type</span> that affects the text shown on |
| the CustomPrompter's button. This has a set of restricted values |
| corresponding to static constraints. For example, 0 is the |
| constant <span style="font-family: monospace;">CustomPrompter.DOTS</span>, |
| 1 is <span style="font-family: monospace;">CustomPrompter.MORE</span> |
| and 2 is <span style="font-family: monospace;">CustomPrompter.OPEN.</span> |
| Rather than have the user have to remember this the property sheet will |
| be extended so that there is a drop down list of available values and |
| the existing value is shown as its meaningful name rather than its |
| internal <span style="font-style: italic;">int</span> value.</p> |
| <table style="text-align: left; width: 75%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before</td> |
| <td style="vertical-align: top;">With plugin</td> |
| <td style="vertical-align: top;">With plugin</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span style="font-style: italic;">type</span> |
| property displayed with default <span style="font-style: italic;">int</span> |
| editor</td> |
| <td style="vertical-align: top;"><span style="font-style: italic;">type</span> |
| property displayed as static constant name</td> |
| <td style="vertical-align: top;"><span style="font-style: italic;">type</span> |
| property edited with drop down list of enumerated allowable values</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><img |
| style="width: 217px; height: 85px;" alt="OriginalType" |
| src="images/OriginalTypeProperty.png"><br> |
| </td> |
| <td style="vertical-align: top;"><img |
| style="width: 216px; height: 86px;" |
| alt="TypePropertyLabelProviderWithPlugin" |
| src="images/TypePropertyLabelProvider.png"><br> |
| </td> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 216px; height: 86px;" |
| alt="TypePropertyCellEditor" src="images/TypePropertyCellEditor.png"></td> |
| </tr> |
| </tbody> |
| </table> |
| <p><span style="font-family: monospace;">MyCustomPrompter</span> has a |
| String property called <span style="font-style: italic;">text</span> |
| that reflects the value shown on the CustomPrompter's text |
| widget. The default property sheet editor for a String property |
| is a Text field that allows the value to be changed, however the |
| tutorial shows how to have a custom property editor that launches a |
| separate dialog through which the value can be changed</p> |
| <table style="text-align: left; width: 50%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before with default String |
| editor behavior for <span style="font-style: italic;">text</span> |
| property</td> |
| <td style="vertical-align: top;">With plugin showing custom |
| editor for <span style="font-style: italic;">text</span> property</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 212px; height: 47px;" |
| alt="OriginalTextProperty" src="images/OriginalTextProperty.png"> </td> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 211px; height: 46px;" |
| alt="TextPropertyCellEditor" src="images/TextPropertyCellEditor.png"> </td> |
| </tr> |
| </tbody> |
| </table> |
| <h3><a name="Intro_Graphical_behavior"></a>Graphical behavior</h3> |
| <p>The visual editor uses the graphical editor framework or GEF to |
| render the visual classes to the user. GEF is a powerful |
| framework which uses EditPart classes as mediators between the |
| underlying model and the draw2d view layer. This is similar to |
| the controller in an MVC pattern and described in overview at <a |
| href="http://www-128.ibm.com/developerworks/opensource/library/os-gef/index.html"> |
| Create an Eclipse based application using GEF.</a> The default behavior |
| for a visual class is a WYSIWYG rendering where a preview of the live |
| runtime widget is drawn. There are times when you may wish to |
| override this for a specific component such as to visually annotate the |
| feedback for the figure such as drawing grid lines, additional handles |
| or other features provided by GEF. As an example of how to alter |
| the edit part used by the visual editor the tutorial shows how to have <span |
| style="font-style: italic;">MyCustomPrompter </span> rendered |
| with an icon <img style="width: 16px; height: 16px;" alt="Custom" |
| src="images/custom.gif"> and the text <span |
| style="color: rgb(255, 0, 0);">VE Rules</span> super imposed over the |
| image of the live visual control. In addition the default |
| behavior of a Composite graphical edit part is to draw a border around |
| it in the editor so that it can be located by the user irrespective of |
| whether it has child controls or not. <span |
| style="font-style: italic;">MyCustomPrompter</span> is an aggregate of |
| three child controls into a custom widget so the graphical edit part |
| will remove the artificial border.</p> |
| <table style="text-align: left; width: 100%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before with default behavior |
| showing the image of the live visual control with a border</td> |
| <td style="vertical-align: top;">With plugin showing custom edit |
| part with an icon and label and no border</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 342px; height: 172px;" |
| alt="originalGEF" src="images/OriginalGraphicalEditPart.png"> </td> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 341px; height: 171px;" |
| alt="GraphicalEditPart" src="images/GraphicalEditPart.png"> </td> |
| </tr> |
| </tbody> |
| </table> |
| <h3><a name="Intro_Code_generation"></a>Code generation</h3> |
| <p>Code generation uses decoder classes to mediate between the visual |
| editor's model and the Java source model. This tutorial shows how |
| to create a custom code generation rule for the <span |
| style="font-style: italic;">text</span> property of <span |
| style="font-style: italic;">MyCustomPrompter</span> so that it has an |
| additional comment placed on the line with the set method. This |
| is the string <span style="color: rgb(0, 102, 0);">// Prompter Text |
| Property</span></p> |
| <table style="text-align: left; width: 100%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before with default code |
| generation behavior</td> |
| <td style="vertical-align: top;">With plugin showing the extra |
| comment line code generated for the setText(String) method</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top; font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">private void</span> |
| createMyCustomPrompter() {<br> |
| myCustomPrompter = <span style="color: rgb(153, 0, 0);">new</span> |
| MyCustomPrompter(sShell, SWT.<span |
| style="font-style: italic; color: rgb(51, 51, 255);">NONE</span>); |
| <br> |
| myCustomPrompter.setText(<span style="color: rgb(51, 51, 255);">"Text |
| Value"</span>);<br> |
| }</td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;"><span style="color: rgb(153, 0, 0);">private |
| void</span> createMyCustomPrompter() {</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> myCustomPrompter = <span |
| style="color: rgb(153, 0, 0);">new</span> MyCustomPrompter(sShell, SWT.<span |
| style="font-style: italic; color: rgb(51, 51, 255);">NONE</span>); |
| </span> <br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| myCustomPrompter.setText(<span style="color: rgb(51, 51, 255);">"Text |
| value"</span>); <span style="color: rgb(0, 153, 0);">// Prompter Text |
| Property</span></span> <br style="font-family: monospace;"> |
| <span style="font-family: monospace;">}</span> </td> |
| </tr> |
| </tbody> |
| </table> |
| <h3><a name="Intro_Preferred_Event"></a>Preferred Event</h3> |
| <p><span style="font-style: italic;">MyCustomPrompter</span> signals an |
| event when its button is pressed. Listeners can register |
| interest in this with the method <span style="font-style: italic;">addButtonSelectionListener(ButtonSelectionListener |
| aListener)</span> and remove interest with the method <span |
| style="font-style: italic;">removeButtonSelectionListener(ButtonSelectionListener |
| aListener). </span> The Visual Editor will automatically detect |
| this event because the naming convention of the methods and the |
| listener class follows the JavaBeans specification. The event |
| will be available from the list of all available events for the custom |
| control, however it is included in the list that has everything from |
| mouse through keyboard and paint events. This tutorial shows how |
| to promote the event to the list of <span style="font-style: italic;">preferred</span> |
| events whereupon it will be shown on the <span |
| style="font-style: italic;">Add Events</span> menu for the class.</p> |
| <table style="text-align: left; width: 100%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">Before where the Events menu has |
| no preferred events</td> |
| <td style="vertical-align: top;">With plugin the Events menu has <span |
| style="font-style: italic;">buttonSelected</span> as a preferred event</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 502px; height: 412px;" |
| alt="OriginalEventsMenu" src="images/OriginalEventsMenu.png"> </td> |
| <td style="vertical-align: top;"><img |
| style="border: 1px solid ; width: 501px; height: 411px;" |
| alt="EventsMenuAfter" src="images/EventsMenuAfter.png"> </td> |
| </tr> |
| </tbody> |
| </table> |
| <h2><a name="Getting_started">Getting started</a></h2> |
| <p>This tutorial goes go through the steps required to build a plugin |
| called<i>org.eclipse.ve.example.customwidget</i><span |
| style="font-style: italic;"><span style="font-weight: bold;">. </span></span> |
| The pre-requisites are an Eclipse 3.1 target environment which has a |
| 3.1 code-base for the Visual Editor, GEF and EMF installed. These |
| can be obtained from the <a |
| href="http://download.eclipse.org/tools/ve/downloads/index.php">Visual |
| Editor's download page</a>. There is an SDK version of the Visual |
| Editor available as well as a runtime, and to develop this tutorial |
| ensure you have the SDK download for the VE. If you obtain the SDK |
| drivers for GEF and EMF it means you will be able to view their source |
| and debug code more easily.</p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> Although the |
| plugin is designed to target 3.1 it can be developed in an earlier |
| environment such as 3.0.1. The target environment is the one that |
| is run when the <span style="font-weight: bold;">Run ... Eclipse |
| Environment</span> is used to launch a runtime workbench. You can |
| use <span style="font-weight: bold;">Windows->Preference->PDE->Target |
| Platform</span> to view and change the target environment and <span |
| style="font-weight: bold;">Help About</span> to see the version of |
| Eclipse.</p> |
| <p>The completed plugin can be obtained separately as described in the |
| section <a href="#A_complete_example">A complete example</a></p> |
| <h2><a name="Creating_the_Plugin">Creating the Plugin</a></h2> |
| <p>This section describes how to build the plugin <span |
| style="font-style: italic;">org.eclipse.ve.example.customwidget. </span> |
| This will be used to package the CustomWidget itself as well as to |
| include the extensions required to override its default behavior. |
| The end result for users is that they will install this plugin onto |
| their Eclipse environment and then configure their Java projects to use |
| the custom widget jar that is included in this plugin <a |
| href="#Using_a_classpath_container">using a class path container</a>.</p> |
| <p>To create the plugin select open the New Project wizard using the |
| menu options <span style="font-weight: bold;">File > New > |
| Project</span> and choose <span style="font-weight: bold;">Plug-in |
| Project</span><br> |
| </p> |
| <p><br> |
| On the first page of the creation wizard name the plugin <i>org.eclipse.ve.example.customwidget</i>, |
| select 3.1 as the target version and select the check box <span |
| style="font-style: italic;">Create an OSGi bundle manifest. </span> |
| Press <span style="font-style: italic;">Next</span> to bring up the <span |
| style="font-style: italic;">Plug-in-Content</span> page and enter a |
| plugin name such as <span style="font-style: italic;">Customwidget VE |
| Example Plugin</span> in the <span style="font-style: italic;">Plugin-In |
| Name</span> text field and set the name of runtime library to <span |
| style="font-style: italic;">customwidgetplugin.jar</span>. </p> |
| <p><img style="border: 1px solid ; width: 499px; height: 253px;" alt="" |
| src="images/CreatePluginWizard.png"></p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> The reason the default suggested |
| runtime library name of <span style="font-style: italic;">customwidget</span><span |
| style="font-style: italic;"><span style="font-style: italic;">.jar</span></span> |
| is renamed to <span style="font-style: italic;">customwidgetplugin.jar</span> |
| is to distinguish the jar file used by the workbench code for the |
| plugin from the name that will be given to the runtime jar containing |
| the custom widget. This is covered in the section <a |
| href="#Different_jars_and_packages">Different jars and packages for |
| workbench and widget code</a></p> |
| <p>Press <span style="font-style: italic;">Finish</span> to have the |
| PDE generate the stub plugin. The workbench might then ask you to |
| switch to the PDE perspective which you can answer <span |
| style="font-style: italic;">Yes</span> to. The plugin manifest |
| editor should be opened by default. This is an editor that allows |
| you to view and edit the contents of the files called <span |
| style="font-style: italic;">plugin.xml and manifest.mf</span> that |
| reside within the plugin. These are both important files as they |
| describe the extension points used and also the list of pre-requisite |
| plugins.</p> |
| <p>A plugin represents a component that can be installed onto an |
| Eclipse environment and contributes code. Every plugin has a set |
| of dependent plugins which is those it requires to function. This |
| list would typically include pre-requisite plugins with classes or |
| interfaces extended or any extension points that have been used. |
| The list of pre-requisite plugins for a plugin extending the visual |
| editor is:</p> |
| <ul> |
| <li>org.eclipse.ui</li> |
| <li>org.eclipse.core.runtime</li> |
| <li>org.eclipse.ve.java.core</li> |
| <li>org.eclipse.jdt.core</li> |
| <li>org.eclipse.jem</li> |
| <li>org.eclipse.jem.proxy</li> |
| <li>org.eclipse.ve.cde</li> |
| <li><img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif">org.eclipse.ve.swt</li> |
| <li>org.eclipse.ve.propertysheet</li> |
| <li>org.eclipse.gef</li> |
| <li>org.eclipse.emf.ecore</li> |
| </ul> |
| <p>The pre-requisite plugin <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_1.gif"> org.eclipse.ve.swt is not necessarily |
| required by everyone extending the visual editor. It contains the |
| code that enables the visual editor to work with the SWT and because <span |
| style="font-style: italic;">MyCustomPrompter</span> is an SWT custom |
| widget the plugin will be extending SWT base behavior. If your |
| plugin was for a JFC toolkit such as AWT or Swing you would not |
| necessarily include <span style="font-style: italic;">org.eclipse.ve.swt</span> |
| in your list of dependencies but instead would use <span |
| style="font-style: italic;">org.eclipse.ve.jfc. </span> If your |
| plugin was for an entirely new widget toolkit you might include neither.</p> |
| <p>To set up the list of required plugins select the <span |
| style="font-style: italic;">Dependencies</span> tab on the plugin |
| editor, select the <span style="font-style: italic;">Add ...</span> |
| button beside the list of Required Plug-ins and enter the list of |
| plugins listed above.</p> |
| <p><img style="border: 1px solid ; width: 353px; height: 166px;" |
| alt="PreReqPlugins" src="images/PreReqPlugins.png"></p> |
| <p>Having created the plugin there are two major steps remaining. |
| The first is to create the actual custom widget class itself and test |
| it, and the second is to extend the visual editor to have the |
| customized behavior described in the <a href="#Introduction">introduction</a>.</p> |
| <h2><a name="Different_jars_and_packages"></a>Different jars and |
| packages for workbench and widget code</h2> |
| <p>There are two jar files being created as part of this |
| tutorial. The reason for this is based on the architecture of the |
| Visual Editor and how it uses a separate JVM for the classes |
| instantiated by the editor rather with re-use or share the JVM used by |
| Eclipse itself.<br> |
| <br> |
| The Visual Editor can be considered as an extension to the Java |
| Development Tooling (JDT) that lets you preview any visual controls |
| that are part of the Java class being edited. The raw Java editor |
| on its own lets you view and modify the source code for a <span |
| style="font-style: italic;">.java</span> file, and edit it using |
| features like Code assist and the Outline viewer. When you use |
| code assist the list of available classes is scoped to be only those |
| that are valid for the current compilation unit, namely those present |
| in the Java build path of the project. The Java build path is |
| specified through the project's properties and can be thought of as the |
| list of <span style="font-style: italic;">-classpath</span> entries |
| that make up the <span style="font-style: italic;">javac</span> |
| command. If you try to use a class that isn't on the build path |
| you will get a compile error. If you try to call a method that |
| doesn't exist on a valid class you will get a compile error, although |
| if you were to change the build path so that it now contained a version |
| of the class that had the method it would compile. The build |
| path's entries determine the environment in which the class you're |
| editing is being created for and the editor responds accordingly.<br> |
| <br> |
| When the Visual Editor is open it uses the JDT's Java editor (as the |
| bottom half of the screen or a separate tab depending on the workbench |
| preferences) and parses the code to recognize visual classes and how |
| they are constructed and associated with each other together with their |
| initial property values. To create a preview of the visuals these |
| classes must be actually instantiated in a live environment following |
| the constructor pattern detected from the source and set methods |
| actually invoked against the live objects for the desired properties |
| and relationships. To do this a JVM environment must exist that |
| contains the list of <span style="font-style: italic;">-classpath</span> |
| entries that match those in the Java build path so that the JVM can |
| load and use the actual instances the user is editing their project |
| with. This can't be the Eclipse's JVM as this is started with the |
| .jar files required for it to behave as an editor, so a separate JVM is |
| created each time the Visual Editor is opened on a class. This is |
| sometimes referred to as the <span style="font-style: italic;">target |
| VM</span> and its purpose is to host prototype Java instances that the |
| Visual Editor instantiates and uses based on the source statements in |
| the <span style="font-style: italic;">.java</span> file being |
| edited. A good analogy to this process is the one used by |
| the <span style="font-style: italic;">Run As>Java Application</span> |
| option in the JDT. If you write a Java class with a public void |
| main(String[] args) method the JDT lets you edit it inside the Eclipse |
| JVM, however to test it a separate JVM is launched by the <span |
| style="font-style: italic;">Java Application</span> launcher. |
| The JDT launcher's separate JVM can be viewed from the <span |
| style="font-style: italic;">Debug</span> viewer allowing you to set |
| breakpoints and step through code, while the Visual Editor's <span |
| style="font-style: italic;">target VM</span> is deliberately hidden |
| from the <span style="font-style: italic;">Debug</span> viewer to stop |
| users from accidentally terminating it.<br> |
| <br> |
| When writing the plugin for this tutorial there are two jar files that |
| will finally be created. The first of these is the <a |
| href="#Plugin_Jar">plugin side jar</a> and contains the Eclipse |
| workbench code that is used within the IDE's VM and contains code such |
| as a JFace property sheet editor, a GEF graphical edit part and a |
| custom source decoder. The second is the <a href="#Runtime_jar">runtime |
| side jar</a> that contains the actual <font face="Courier New">MyCustomPrompter</font> |
| class itself and doesn't run inside the IDE but instead is placed in |
| the Java build path of the user's project and runs in the target |
| VM. The runtime side jar also contains the BeanInfo class for |
| MyCustomPrompter that contains the extensions that conform to the |
| JavaBeans component model which is covered more in the sections on the <a |
| href="#Using_an_ENUM_cell_editor"><span style="font-style: italic;">type</span> |
| property editor</a> and creating the <a href="#Preferred_Event">preferred |
| event</a>.<br> |
| <br> |
| <img style="width: 601px; height: 515px;" alt="" |
| src="images/JARdiagram.png"><br> |
| </p> |
| <h3><a name="Plugin_Jar"></a>Plugin jar</h3> |
| <p>The plugin code for this tutorial is placed in <span |
| style="font-style: italic;">customwidgetplugin.jar</span> that is |
| defined as the runtime jar for the plugin itself. On the New |
| Project wizard we explicitly changed the default prompted jar name to |
| be <i>customwidgetplugin.jar</i> so that is will not be confused with |
| the <a href="#Runtime_jar">run time jar</a>. The <span |
| style="font-style: italic;">customwidgetplugin.jar </span>contains |
| the Eclipse code that will run inside the workbench and its definition |
| can be seen in the in the <span style="font-style: italic;">Runtime</span> |
| tab of the manifest editor for the plugin's plugin.xml file. <br> |
| <br> |
| <img style="border: 1px solid ; width: 357px; height: 155px;" alt="" |
| src="images/RuintimeLibraryPluginName.png"><br> |
| <br> |
| <img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> The name of the plugin code's jar |
| is either held in a <span style="font-family: monospace;"><runtime><library |
| name="customwidgetplugin.jar"></runtime></span> tag in the <span |
| style="font-style: italic;">plugin.xml</span> file for a pre 3.1 |
| plugin, or else for an OSGI 3.1compatible only plugin the jar file name |
| is held in the <span style="font-style: italic;">MANIFEST.MF</span> |
| file in the line <span style="font-family: monospace;">Bundle-ClassPath: |
| customwidgetplugin.jar</span>. <br> |
| <br> |
| The package <span style="font-family: monospace;">org.eclipse.ve.example.customwidget</span> |
| contains the Java code that is used to create the contents of the <span |
| style="font-style: italic;">customwidgetplugin.jar</span>.<br> |
| </p> |
| <h3><a name="Runtime_jar"></a>Runtime jar</h3> |
| <p>The code for the <span style="font-family: monospace;">MyCustomPrompter</span> |
| and its BeanInfo class are placed in the package<span |
| style="font-family: monospace;">org.eclipse.ve.example.customwidget.prompter</span>. |
| When the plugin is deployed these classes are compiled not into the |
| plugin's <span style="font-style: italic;">customwidgetplugin.jar</span> |
| but |
| instead to a file customwidgets.jar. The steps to create |
| the customwidgets.jar are described in the section <a |
| href="#The_Custom_Widget">The Custom Widget</a>.</p> |
| <h2><a name="The_Custom_Widget">The Custom Widget</a></h2> |
| <p>The custom widget used in this tutorial extends SWT composite and |
| has three child controls on it; a label, a text field, and a |
| button. For this tutorial we used the Visual Editor to build the |
| custom widget which, although a good exercise in using the Visual |
| Editor, is outside the scope of what this tutorial is designed to cover |
| - you can download it directly from CVS to begin working. You |
| should download the two classes <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/prompter/MyCustomPrompter.java"> |
| <font face="Courier New">MyCustomPrompter.java</font></a>, and <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/prompter/ButtonSelectionListener.java"> |
| <font face="Courier New">ButtonSelectionListener.java</font></a> and |
| place them into the plugin project in a package <span |
| style="font-style: italic;">org.eclipse.ve.customwidget.prompter. </span> |
| This is illustrated below together with the Visual Editor opened |
| against the <span style="font-style: italic;">MyCustomPrompter</span> |
| class to show the three child controls. The package <span |
| style="font-style: italic;">org.eclipse.ve.example.customwidget</span> |
| is where the visual editor classes (such as the specialized |
| graphical edit part or code generation decoder) will reside, and the |
| package <span style="font-style: italic;">org.eclipse.ve.customwidget.prompter</span> |
| is where the classes reside that the user will use to build their |
| runtime GUIs with. </p> |
| <p><img style="border: 1px solid ; width: 721px; height: 357px;" |
| alt="RuntimeClasses" src="images/CustomWidgetPackage.png"></p> |
| <p>For deployment the classes <span style="font-style: italic;">MyCustomPrompter</span> |
| and <span style="font-style: italic;">ButtonSelectionListener</span> |
| will be packaged in a runtime jar. To do this select the runtime |
| package and use the pop up menu option <span style="font-weight: bold;">Export</span> |
| to bring up the Export wizard. Select the JAR file option and |
| name the JAR file <span style="font-style: italic;">customwidgets.jar. </span> |
| This JAR file will be placed inside the plugin itself and there are two |
| ways to do this. The first is to either export the JAR to a |
| temporary location on your computer and then import it into the |
| project. If you do this you should import the <span |
| style="font-style: italic;">customwidgets.jar</span> not as a JAR file |
| as it contains no code of any interest to the plugin itself, but |
| instead as a raw <span style="font-style: italic;">File</span>. |
| The reason for this is that the inclusion of the runtime code in the |
| plugin is not for the benefit of Eclipse and it will never be loaded by |
| the Visual Editor into the Eclipse JVM. The user of the plugin |
| will configure their Java project to use the custom prompter which is |
| described in the later section <a href="#Using_a_classpath_container">Using |
| a classpath container</a>, and the visual editor will insert the JAR |
| into the -classpath of the VM that it uses to host the Java classes |
| that make up the user's classes.<br> |
| <br> |
| The second way to ensure that the <span style="font-style: italic;">customwidgets.jar</span> |
| is included in the plugin that avoids having to export to the file |
| system and then re-import as a file, is to export straight to the |
| directory used by the plugin itself. To see the location of the |
| plugin you can open its properties and select Info. The figure |
| below shows an example of this where the workbench location is |
| D:\temp\tutorial and the JAR wizard creates customwidgets.jar into the |
| directory used by the <span style="font-style: italic;">org.eclipse.ve.example.customwidget</span> |
| plugin. If you do export directly to the workbench as shown below |
| afterwards you will need to do a manual refresh of the project's |
| contents using F5 (or the pop-up menu option) to ensure that the |
| Eclipse workbench is in sync with the file system contents that have |
| just been altered.<br> |
| </p> |
| <img style="border: 1px solid ; width: 466px; height: 401px;" |
| alt="JarExport" src="images/JARExport.png"><br> |
| <br> |
| <h3><a name="Testing_MyCustomPrompter"></a>Testing MyCustomPrompter</h3> |
| <p>Having created the plugin you can now test it. To do this |
| create an Eclipse launch configuration using the <span |
| style="font-weight: bold;">Run</span> menu to bring up the list of |
| available launch configurations, selecting <span |
| style="font-style: italic;">Eclipse Application</span> and <span |
| style="font-style: italic;">New</span> and then running this using the |
| default application.</p> |
| <p><img alt="" style="border: 1px solid ; width: 261px; height: 311px;" |
| src="images/LaunchConfig.png"></p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> On Eclipse 3.0.x an <i>Eclipse |
| Application</i> launch configuration is called <i>Run-time Workbench.</i></p> |
| <p>This will launch a second Eclipse workbench - the first being your |
| one that you are using to develop the plugin and the second being the |
| one you are going to use to deploy the plugin into. In the |
| deployed workbench create a Java project and add <i>customwidgets.jar</i> |
| to the Java build path. This is done using the pop-up menu option |
| to open the <span style="font-weight: bold;">Properties</span> of the |
| project and selecting <span style="font-weight: bold;">Java Build path |
| ...</span>. On the build path select the <span |
| style="font-style: italic;">Libraries</span> tab and <span |
| style="font-style: italic;">Add External Jar ...</span>. Point |
| to the location of the jar in the plugin itself - for the example |
| figure above this would be <span style="font-style: italic;">D:\temp\tutorial\org.eclipse.ve.example.customwidget.customwidgets.jar.</span> |
| Having added the JAR containing the <span style="font-style: italic;">MyCustomPrompter</span> |
| class you can now use it within a visual editor class. Create a |
| test sample using <span style="font-weight: bold;">File > New > |
| Visual class</span> and selecting <span style="font-weight: bold;">SWT |
| > Shell. </span> This will open the Visual Editor over a class |
| with an SWT shell. Select the <span style="font-style: italic;">Choose |
| Bean</span> palette entry and because <span style="font-style: italic;">customwidgets.jar</span> |
| is in the project's build path (the effective -classpath used by the |
| Eclipse Java compiler and by the Visual Editor) you can choose <span |
| style="font-style: italic;">MyCustomPrompter</span> and drop it onto |
| the Shell.<br> |
| <br> |
| The behavior of <span style="font-style: italic;">MyCustomPrompter</span> |
| is everything picked up by default as the Visual Editor will realize |
| that <span style="font-style: italic;">MyCustomPrompter</span> extends |
| <span style="font-style: italic;">org.eclipse.swt.widgets.Composite</span> |
| so it will be rendered visually and have default property sheet, code |
| generation, graphical edit part and event menu behavior. The |
| remainder of this tutorial shows how to customize this behavior as |
| described in the <a href="#Introduction">introduction</a>.</p> |
| <h2><a name="Creating_a_Classpath_Container">Creating a classpath |
| container</a></h2> |
| <p>For the test described at the end of the preceding section the <span |
| style="font-style: italic;">MyCustomPrompter</span> class was made |
| available to the user's Java project by them adding it as an external |
| JAR. This isn't ideal as it requires the user knowing the |
| location of the plugin directory on their computer and physically |
| pointing to it. A better way is to use a classpath |
| container. This allows one-touch configuration of a Java project |
| to use a named container which handles all the internals of how to |
| locate the correct runtime code. </p> |
| <p>A Java container is a class that implements the JDT interface <span |
| style="font-style: italic;">org.eclipse.jdt.core.IClasspathContainer</span>. |
| It is added to a Java project's build path using the <span |
| style="font-style: italic;">Add Library</span> button on the <span |
| style="font-style: italic;">Libraries</span> tab and an example of one |
| used by the Visual Editor is <span style="font-style: italic;">org.eclipse.ve.internal.swt.SWTContainer</span>. |
| As well as the JDT using the container to locate the runtime classes |
| the Visual Editor uses this as a marker for extension behavior. |
| When the Visual Editor opens over a project all of the containers are |
| scanned and matched against extension points to see if there are any |
| plugins that wish to contribute to the palette or any other custom |
| visual editor behavior based on the classes included within the |
| container.</p> |
| <p>This tutorial doesn't create a new container class because the |
| complexities involved doing this require knowledge of JDT concepts such |
| as IPath and IClassPathEntry[]. It is expected that commercial |
| quality plugins extending the Visual Editor will create their own |
| containers in which case the <span style="font-style: italic;">SWTContainer</span> |
| class is a good example to look at to learn how to do this, however for |
| simplicity the visual editor provides a reference implementation |
| container class <span style="font-style: italic;">org.eclipse.ve.internal.java.core.RegisteredClassPathContainer. </span> |
| The Registered container uses extension points to determine the JAR |
| files it will add to the user's build path.</p> |
| <p>The user experience is that a container called "Custom Prompter" |
| will be available for them to add to a Java project's build path. |
| This is described in the section <a href="#Using_a_classpath_container">Using |
| a classpath container</a>. The JDT extension point <span |
| style="font-style: italic;">org.eclipse.jdt.ui.classpathContainerPage</span> |
| allows contributions to be made for an entry to appear in the list of |
| containers and be available for the user to select, as well as the |
| wizard page that will then appear once <span |
| style="font-style: italic;">Next</span> is pressed. The wizard |
| page is responsible for configuring the project's build path to |
| actually add the container classpath entry.</p> |
| <p>To add the <span style="font-style: italic;">Custom Prompter</span> |
| entry to the list of available containers add the following to the <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/plugin.xml"> |
| plugin.xml</a> of the <span style="font-style: italic;">org.eclipse.ve.examples.customwidget</span> |
| plugin.</p> |
| <pre> <a name="ContainerPageDefinition"></a><extension<br> point="org.eclipse.jdt.ui.classpathContainerPage"><br> <classpathContainerPage<br><img |
| style="width: 24px; height: 13px;" alt="tag1" src="../images/tag_1.gif"> name="Custom Prompter"<br><img |
| style="width: 24px; height: 13px;" alt="tag2" src="../images/tag_2.gif"> class="org.eclipse.ve.internal.java.wizard.RegisteredClasspathContainerWizardPage"<br><img |
| style="width: 24px; height: 13px;" alt="tag3" src="../images/tag_3.gif"> id="org.eclipse.ve.example.PrompterContainer"><br> </classpathContainerPage><br> </extension><br></pre> |
| <p>The name <img style="font-style: italic; width: 24px; height: 13px;" |
| alt="tag1" src="../images/tag_1.gif"><span style="font-style: italic;">"Custom |
| Prompter"</span> is the user visible String shown in the list of |
| available libraries from the <span style="font-style: italic;">Add |
| Library</span> wizard on the <span style="font-style: italic;">Libraries</span> |
| tab on the <span style="font-style: italic;">Java build path. </span> |
| In a commercial quality plugin it is expected this would come from a |
| resource bundle and be externalized for different locales however this |
| tutorial will hard code it to the literal <span |
| style="font-style: italic;">"Custom Prompter"</span>. Once the |
| user selects a container library to be added and presses <span |
| style="font-style: italic;">Next</span> a wizard page is brought up |
| showing configuration details of the particular container. This |
| wizard page <span style="font-style: italic;">implements |
| org.eclipse.jdt.ui.wizards.IClasspathContainerPage</span> and for a |
| commercial quality plugin it is expected that a custom page would be |
| written. The visual editor SWT container page |
| org.eclipse.ve.internal.swt.SWTcontainerWizardPage is a good example to |
| look at if your intention is to create a full wizard page, however the |
| visual editor provides an example <span style="font-style: italic;">org.eclipse.ve.internal.java.wizard.RegisteredClasspathContainerWizardPage</span> |
| that can be used <img style="width: 24px; height: 13px;" alt="tag2" |
| src="../images/tag_2.gif">. <br> |
| <br> |
| The container needs an id that uniquely identifies it within an Eclipse |
| environment and this tutorial uses <img |
| style="width: 24px; height: 13px;" alt="tag3" src="../images/tag_3.gif"> <span |
| style="font-style: italic;">org.eclipse.ve.example.PrompterContainer.</span><br> |
| <br> |
| The RegisteredClasspathContainerWizardPage will add the container |
| RegisteredClasspathContainer to the build path of the user's project |
| once they select it. This is a generic container and to identify |
| it as being an entry that should point to the runtime files required |
| for the <span style="font-style: italic;">MyCustomPrompter</span> and |
| its supporting classes requires two further extension points. If |
| a specific custom container is being used then these are not required.<br> |
| <br> |
| The extension point <span style="font-style: italic;">org.eclipse.jdt.core.classpathContainerInitializer</span> |
| specificies a container initializer that will be used by the JDT to |
| configure containers. The following lines should be added to the |
| plugin.xml for the <span style="font-style: italic;">org.eclipse.ve.examples.customwidget</span> |
| plugin.</p> |
| <pre> <extension<br> point="org.eclipse.jdt.core.classpathContainerInitializer"><br> <classpathContainerInitializer<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> class="org.eclipse.ve.internal.java.core.RegisteredClasspathContainerInitializer"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> id="org.eclipse.ve.example.PrompterContainer"><br> </classpathContainerInitializer><br> </extension><br><br></pre> |
| <p>The class used is a reference implementation provided by the Visual |
| Editor and is <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <span style="font-style: italic;">org.eclipse.ve.internal.java.core.RegisteredClasspathcontainerInitializer. </span> |
| The id used must match the one described earlier as the id of the |
| container wizard page. This tutorial is using <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <span |
| style="font-style: italic;">org.eclipse.ve.example.PrompterContainer.<br> |
| <br> |
| </span> Having configured the wizard page and the container initializer |
| this will now add an instance of the RegisteredClasspathContainer to |
| the user's build path of their Java project. This needs to be |
| told where to locate the jars that contain the runtime code. |
| There is an extension point used by the RegisteredClasspathContainer |
| class named <span style="font-style: italic;">org.eclipse.ve.java.core.registrations. </span> |
| To use it add the following lines to the plugin.xml. Note that if |
| a true container implementation is being done instead then this |
| extension point is not required - it is only used by the |
| RegisteredClasspathContainer. For example, the project |
| org.eclipse.ve.swt that defines the SWT extensions for the visual |
| editor has its own custom behavior and does not require use of this |
| extension point. </p> |
| <pre> <extension<br> point="org.eclipse.ve.java.core.registrations"><br> <registration<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> container="org.eclipse.ve.example.PrompterContainer"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> description="Custom Prompter"><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> <<a |
| name="library_definition"></a>library runtime="customwidgets.jar"/><br> </registration><br> </extension><br></pre> |
| <p>The name of the container must match the id used when the |
| classpath wizard page and container initializer were defined. |
| This tutorial is using <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <span style="font-style: italic;">org.eclipse.ve.example.PrompterContainer. </span> |
| The container needs a description that will appear in the Java build |
| path list of classpath entries and the tutorial uses the hard coded |
| literal <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> <span style="font-style: italic;">"Custom |
| Prompter". </span> The plugin element <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| <library runtime="customwidgets.jar".> describes the actual |
| location of the runtime jars that contain the <span |
| style="font-style: italic;">MyCustomPrompter</span> class. If |
| there are multiple jars then the entry can be repeated. The |
| location of the jar is relative to the plugin itself, so if <span |
| style="font-style: italic;">customwidgets.jar</span> were in a |
| directory called <span style="font-style: italic;">jars</span> within |
| the plugin then the entry would be runtime="jars/.customwidgets.jar".<br> |
| <br> |
| Having updated the plugin.xml file to define the classpath container |
| the next step is to test this.</p> |
| <h2><a name="Using_a_classpath_container"></a>Using a classpath |
| container</h2> |
| <p>Launch the Eclipse Application workbench using the <span |
| style="font-weight: bold;">Run</span> menu to open the runtime |
| environment in which the <span style="font-style: italic;">MyCustomPrompter</span> |
| class can be tested. If you have previously done this and created |
| a Java project with a build path entry pointing to the <span |
| style="font-style: italic;">customwidgets.jar</span> as described |
| earlier remove the jar from the build path. Otherwise create a |
| new Java project.</p> |
| <p>The next steps are the experience that a user of the plugin will |
| take to configure a Java project to work with the <span |
| style="font-style: italic;">MyCustomPrompter</span> custom |
| control. Open the properties for the Java project using the <span |
| style="font-weight: bold;">Properties</span> choice on the pop-up menu |
| and select <span style="font-style: italic;">Java Build Path.</span><span |
| style="font-weight: bold;"><span style="font-style: italic;"> </span></span> |
| Select the <span style="font-style: italic;">Libraries</span> tab and |
| choose the <span style="font-style: italic;">Add Library</span> |
| button. This will bring up a list of all known Java containers |
| which will include the <span style="font-style: italic;">Custom |
| Prompter</span> as defined using the extension point |
| org.eclipse.jdt.ui.classpathcontainerPage <a |
| href="#ContainerPageDefinition">earlier.</a> The figure below shows |
| the Java build path for a project called <span |
| style="font-style: italic;">Test</span> and the Custom Prompter |
| displayed in the list of available libraries opened from the <span |
| style="font-style: italic;">Add Library</span> button</p> |
| <p><img style="border: 1px solid ; width: 641px; height: 471px;" alt="" |
| src="images/CustomPrompterContainer.png"></p> |
| <p>Select the <span style="font-style: italic;">Custom Prompter</span> |
| and press Next to view the wizard page <span |
| style="font-style: italic;">org.eclipse.ve.internal.java.wizard.RegisteredClasspathContainerWizardPage</span> |
| defined <a href="#ContainerPageDefinition">earlier</a>. This is |
| a generic example of a page and shows details of the jar that will be |
| added by the page. For commercial quality plugins it is expected |
| that this page however will be a specific to the particular |
| plugin. </p> |
| <p>Pressing Finish on the wizard page will configure the project (using |
| the RegisteredClasspathcontainerInitializer defined earlier) to include |
| the container <span style="font-style: italic;">RegisteredClasspathContainer</span> |
| together with the id of<span style="font-style: italic;">org.eclipse.ve.examples.PrompterContainer. </span> |
| Expanding the container in the project's build path will show that it |
| points to the correct location for the customwidgets.jar as described |
| in the <span style="font-family: monospace;"><library |
| runtinme="customwidgets.jar"></span> plugin.xml tag described <a |
| href="#library_definition">earlier</a>.<br> |
| <br> |
| <img style="border: 1px solid ; width: 281px; height: 147px;" alt="" |
| src="images/TestProjectBuildPath.png"><br> |
| <br> |
| <img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> The figures above for configuring |
| the project Test's build path to include the <span |
| style="font-style: italic;">Custom Prompter</span> container entry |
| show two other containers, namely the <span style="font-style: italic;">JRE |
| System library</span> and the <span style="font-style: italic;">Standard |
| Widget Toolkit.</span> The JRE container will be present on |
| the Java project by default when it is first created, however the SWT |
| container will not be. This is a container defined by the plugin |
| project <span style="font-style: italic;">org.eclipse.ve.swt</span> |
| that enables the Visual Editor to work with the SWT. If you |
| created the Test project in the step <a |
| href="#Testing_MyCustomPrompter">Testing the custom prompter</a> |
| described earlier when you created the test class using the <span |
| style="font-style: italic;">New Visual Class Wizard</span>and selected |
| SWT application the wizard automatically added the SWT container to the |
| project's build path as required. SWT support for the Visual |
| Editor can be manually added by using the steps described above but |
| selecting <span style="font-style: italic;">Standard Widget Toolkiit</span> |
| instead of <span style="font-style: italic;">Custom Prompter</span> on |
| the <span style="font-style: italic;">Add Library</span> wizard |
| page. Adding dependent containers (CustomPrompter requires SWT) |
| is not something that is supported by the reference implementation of |
| RegisteredClassPathContainer and it is expected that commercial quality |
| plugins will provide their own container class with the required logic |
| to ensure consistency of dependent containers in the user's build path.<br> |
| <br> |
| Having configured the Test project to use the <span |
| style="font-style: italic;">Custom Prompter</span> container you can |
| now test it by creating an SWT Shell from the <span |
| style="font-style: italic;">New Visual Class Wizard</span> and |
| dropping <span style="font-style: italic;">MyCustomPrompter</span> |
| using the <span style="font-style: italic;">Choose Bean ...</span> |
| palette entry. the next step is to configure the palette so that |
| a new category called <span style="font-style: italic;">Custom</span> |
| is added that has an entry for the <span style="font-style: italic;">MyCustomPrompter</span> |
| class.</p> |
| <h2><a name="Adding_a_palette_category_for_our_widget">Adding a palette |
| category for MyCustomPrompter</a></h2> |
| <p>The visual editor's palette is described by an EMF model. EMF |
| serializes to <a |
| href="http://www.omg.org/technology/documents/formal/xmi.htm">XMI</a> |
| which is an XML representation of a graph of EMF objects. Plugins |
| can define their own XMI files that describe the categories to be added |
| to the palette, the groups these belong to, and the actual entries |
| themselves. For the org.eclipse.ve.examples.customwidgets plugin |
| there will be a palette XMI file that describes the single category and |
| class to add.<br> |
| <br> |
| Create a file called customprompter.xmi in the plugin and open it with |
| a text editor. The data for the file is shown below and can be |
| downloaded directly from <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/customprompter.xmi"> |
| CVS</a> to avoid re-entry.<br> |
| <br> |
| </p> |
| <pre> <xmi:XMI xmi:version="2.0"<br> xmlns:xmi="http://www.omg.org/XMI"<br> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" <br> xmlns:palette="http:///org/eclipse/ve/internal/cde/palette.ecore"<br> xmlns:utility="http:///org/eclipse/ve/internal/cde/utility.ecore"><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <palette:CategoryCmp><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <categoryLabel xsi:type="utility:ConstantString" string="Custom"/><br> <cmpGroups xsi:type="palette:GroupCmp"><br><br><img |
| style="width: 23px; height: 13px;" alt="" src="../images/tag_3.gif"> <cmpEntries xsi:type="palette:AnnotatedCreationEntry" xmi:id="entry2" icon16Name="platform:/plugin/org.eclipse.ve.example.customwidget/icons/custom.gif"><br> <objectCreationEntry xsi:type="palette:EMFCreationToolEntry"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> creationClassURI<b>=</b>"java:/org.eclipse.ve.example.customwidget.prompter#MyCustomPrompter"/><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> <entryLabel xsi:type="utility:ConstantString" string="Prompter"/><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> <values xmi:type="ecore:EStringToStringMapEntry" key="org.eclipse.ve.internal.cde.core.nameincomposition" value="customPrompter"/> <br> </cmpEntries><br><br> </cmpGroups><br> </palette:CategoryCmp><br> </xmi:XMI><br></pre> |
| <p>The <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <palette:categoryCmp> tag describes a |
| palette category that has a label and groups, each group containing a |
| number of entries. In the example for the tutorial the label is |
| hard coded to the literal <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_2.gif"> <span style="font-style: italic;">"Custom". </span> |
| <img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> For |
| a plugin that needed to support different language locales there is an |
| EMF class utility:TranslatableString and examples of its usage can be |
| found in the palette files for the plugin org.eclipse.ve.jfc.<br> |
| <br> |
| A single group is defined for the Custom category. If multiple |
| groups are defined the palette demarks these visually with a |
| separator. The group has a single entry that defines the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| graphic, the qualified <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_4.gif"> name of the class and the literal <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> |
| string that is displayed on the palette entry. To ensure that a |
| good default name is used each time the user drops an instance of the |
| CustomPrompter a <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_6.gif"> default <span style="font-style: italic;">nameincomposition |
| </span>is specified to be "customPrompter". The <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| graphic points to the URL of where the image is located, in this case |
| the entry points to a file <span style="font-style: italic;">custom.gif</span> |
| in the <span style="font-style: italic;">icons</span> directory of the |
| plugin called <span style="font-style: italic;">org.eclipse.ve.example.customwidget. </span> |
| The graphic used <img style="width: 16px; height: 16px;" alt="" |
| src="images/custom.gif"> is available in <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/icons/custom.gif">CVS</a> |
| and you will |
| need to create a folder called <span style="font-style: italic;">icons</span> |
| in the plugin and copy it there.<br> |
| <br> |
| <img style="border: 1px solid ; width: 264px; height: 148px;" alt="" |
| src="images/IconsFolder.png"></p> |
| <p><img src="../images/tip.gif" alt="Tip:" |
| style="width: 62px; height: 13px;"> |
| Because XMI files do not have anything to validate them at design time |
| errors made in their syntax can easily be made that cause runtime |
| problems that can be hard to trace and debug. The most |
| straightforward way to write a Visual Editor XMI file is to copy an |
| existing one that is similar to what you desire and then alter just the |
| parts that need changing.</p> |
| <p>Having created the <span style="font-style: italic;">customprompter.xmi</span> |
| file we need to enable the Visual Editor to use it. This is done |
| by associating the palette file with a classpath container, in our case |
| the Custom Prompter. </p> |
| <p>Now that we have our palette xmi file available, we need to |
| contribute it to the Visual Editor. We do so by adding to the |
| following extension in the plugin's <span |
| style="font-style: italic;">plugin.xml</span> manifest |
| file.</p> |
| <pre> <extension<br><img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> point="org.eclipse.ve.java.core.contributors"><br> <palette<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> container="org.eclipse.ve.example.PrompterContainer"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> categories="<b>customprompter.xmi</b>"/><br> </extension> <br></pre> |
| <p>The extension point used is <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <span |
| style="font-style: italic;">org.eclipse.ve.java.core.contributors.</span> |
| This has a <palette> child XML tag that points to the id of |
| the <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> container whose inclusion in a project's |
| build path causes the palette categories defined in the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| categories tag to be included. The palette categories tag is relative |
| to the root of the plugin project, for example If the palette XMI file |
| is in a folder called <span style="font-style: italic;">palette</span> |
| then the entry would be <span style="font-family: monospace;">categories="palette/customprompter.xmi".</span></p> |
| <p>When the Visual Editor starts it scans all of the project's build |
| path entries and for any that are containers it looks to see whether |
| there are any palette files. These are combined together to |
| create the overall palette.</p> |
| <p><img style="width: 63px; height: 13px;" src="../images/note.gif" |
| alt="Note:"> As well as describing palette entries directly it is |
| possible to configure the Visual Editor to have an <font |
| face="Courier New">IConfigurationContribution</font> that has the |
| ability to manipulate both the -classpath of the Visual Editor's VM and |
| the palette with more fine control. An example of where this is |
| done is by SWT that has to add runtime packages such as DLLs or |
| packages to the VM's arguments, or a plugin that might wish to remove |
| some of the existing palette entries (such as the JFC ones) for |
| projects configured with their container present.</p> |
| <p><img style="height: 13px; width: 62px;" alt="Tip:" |
| src="../images/tip.gif"> As |
| well as defining containers to be the trigger point for Visual Editor |
| custom behavior you can also use plugins by direct name using the <span |
| style="font-style: italic;">plugin=</span> tag. An example of where |
| you might do this is if you were extending the Visual Editor to work |
| with a set of classes that were contained in a specific plugin, so the |
| user experience to enable a Java project would be to add a dependent |
| plugin rather than a classpath container. An example of this |
| might be something like a PDE type development environment for the |
| actual end user.</p> |
| <h3><a name="Testing_the_custom_palette"></a>Testing the custom palette</h3> |
| <p>Having modified the manifest of the example plugin to include the |
| plugin the next step is so test it. Do this by launching the |
| Eclipse Application workbench and creating, or re-opening, a class <font |
| face="Courier New">MyShell</font> that was created from the <span |
| style="font-style: italic;">New Visual Class <span |
| style="font-style: italic;">Wizard</span></span> as an SWT |
| application. The Visual Editor should detect that the container |
| with an id of <span style="font-style: italic;">org.eclipse.ve.example.PrompterContainer</span> |
| is in the project's build path and include the palette categories |
| contained in the <span style="font-style: italic;">custompalette.xmi</span> |
| file. This is shown in the figure below where the Prompter |
| palette entry has been selected and dragged out onto the Shell. <br> |
| <br> |
| <img style="border: 1px solid ; width: 758px; height: 396px;" alt="" |
| src="images/CustomPalette.png"><br> |
| <br> |
| <img src="../images/tip.gif" alt="Note:" style="height: 13px; width: 62px;"> |
| When |
| you launch the Eclipse Application workspace use the <span |
| style="font-style: italic;">-clean</span> option, as each time the <span |
| style="font-style: italic;">plugin.xml</span> manifest file has |
| changed we need to be sure the runtime Eclipse environment clears its |
| cached manifest details<br> |
| <br> |
| At this point in the tutorial you should have defined a classpath |
| container that the user can configure a Java project with to include |
| the jar containing the runtime code for the <span |
| style="font-style: italic;"><span style="font-style: italic;"><span |
| style="font-style: italic;">MyCustomPrompter</span></span></span> |
| class. The extension point <span style="font-style: italic;">org.eclipse.ve.java.core.contributors</span> |
| has been used to point to the location of a palette XMI file that |
| contains a category with an entry for the class.<br> |
| <br> |
| The next steps are to configure the Visual Editor so that <span |
| style="font-style: italic;">MyCustomPrompter</span> has custom |
| behavior over and above that it inherits by virtue of extending <span |
| style="font-style: italic;">org.eclipse.swt.widgets.Composite</span>.</p> |
| <h2><a name="Using_an_ENUM_cell_editor">Enumerated values for the <span |
| style="font-style: italic;">type</span> property</a></h2> |
| <p><span style="font-family: monospace;">MyCustomPrompter</span> class |
| has an <i>int</i> property named <i style="font-weight: bold;">type</i>with |
| <i>getType</i>() and <i>setType</i>(int aType) methods. While |
| the signature of <i>setType</i> allows it to accept any int, the class |
| itself only works with one of the three values 0, 1, or 2 The |
| definition of the values is held in three static constants on the <span |
| style="font-family: monospace;">MyPrompterClass</span>.</p> |
| <pre><span style="color: rgb(153, 0, 0);">public final static int</span> <span |
| style="font-style: italic; color: rgb(51, 51, 255);">DOTS</span> = 0;<br><span |
| style="color: rgb(153, 0, 0);">public final static int</span> <span |
| style="color: rgb(51, 51, 255); font-style: italic;">MORE</span> <span |
| style="font-style: italic;">=</span> 1;<br><span |
| style="color: rgb(153, 0, 0);">public final static int</span> <span |
| style="color: rgb(51, 51, 255); font-style: italic;">OPEN</span> = 2;<br></pre> |
| <p>The significance of the three values is that they alter the button |
| text for <span style="font-family: monospace;">MyCustomPrompter to</span> |
| be either "...", "More", or "Open" respectively. The |
| following code shows this for <span style="font-family: monospace;">MyCustomPrompter</span>'s |
| <span style="font-family: monospace;">setType(int type)</span> method.</p> |
| <pre><span style="color: rgb(153, 0, 0);">public void</span> setType (<span |
| style="color: rgb(153, 0, 0);">int</span> type) {<br> <span |
| style="color: rgb(153, 0, 0);">switch</span> (type) {<br> <span |
| style="color: rgb(153, 0, 0);">case</span> <span |
| style="font-style: italic; color: rgb(51, 51, 255);">DOTS</span>: button.setText(<span |
| style="color: rgb(51, 51, 255);">"..."</span>);<br> <span |
| style="color: rgb(153, 0, 0);">break</span>;<br> <span |
| style="color: rgb(153, 0, 0);">case</span> <span |
| style="font-style: italic; color: rgb(51, 51, 255);">MORE</span>: button.setText(<span |
| style="color: rgb(51, 51, 255);">"More"</span>);<br> <span |
| style="color: rgb(153, 0, 0);">break</span>;<br> <span |
| style="color: rgb(153, 0, 0);">case</span> <span |
| style="font-style: italic; color: rgb(51, 51, 255);">OPEN</span>: button.setText(<span |
| style="color: rgb(51, 51, 255);">"Open"</span>);<br> <span |
| style="color: rgb(153, 0, 0);">break</span>;<br> <span |
| style="color: rgb(153, 0, 0);">default</span>:<br> <span |
| style="color: rgb(153, 0, 0);">throw new</span> IllegalArgumentException(<span |
| style="color: rgb(51, 51, 255);">"Value "</span> + type + <span |
| style="color: rgb(51, 51, 255);">" must be one of 0, 1 or 2"</span>);<br> }<br>}<br></pre> |
| <p>Whenever a class is selected in the Visual Editor graphical canvas |
| or Java Beans tree viewer the Properties view will show its properties |
| and their current values. The view can also be used to edit the |
| property values, and the Visual Editor has a number of pre-defined |
| editors associated with specific types. <span |
| style="font-style: italic;">int</span> properties for example have an |
| editor that allows only valid <span style="font-style: italic;">int</span> |
| values to be entered and by default the Visual Editor will use this |
| whenever the <span style="font-style: italic;">type</span> property is |
| selected based on its signature.</p> |
| <p>This step of the tutorial describes how to override the default |
| behavior so that the <span style="font-style: italic;">type</span> |
| property is edited using a drop down list of the three allowable |
| values. Also, instead of the values 0, 1 and 2 being displayed as |
| the current values the literals "Dots", "More" and "Open" will be used |
| instead. This is described as an objective of the tutorial in the |
| <a href="#Introduction">Introduction</a>.</p> |
| <p>To override the behavior of the <span style="font-style: italic;">type</span> |
| property so that it has the desired behavior involves using a BeanInfo |
| class. BeanInfo classes provide a way to describe a classes' |
| design time behavior and art part of the <a |
| href="http://java.sun.com/products/javabeans/reference/api/index.html">JavaBeans |
| specification</a>. The Visual Editor uses the JavaBeans |
| specification wherever possible to define edit time behavior for a |
| JavaBean. </p> |
| <p>The BeanInfo specification allows for a class with the same name as |
| its Java peer to exist that describes the edit time behavior of the |
| class. For example, the tutorial class is named <span |
| style="font-family: monospace;">MyCustomPrompter</span> so there would |
| be a class <span style="font-family: monospace;">MyCustomPrompterBeanInfo</span> |
| that implements the interface <span style="font-family: monospace;">java.beans.BeanInfo</span> |
| associated with it. The simplest way to create this class is to |
| put it in the same package as the class it describes (e.g. <span |
| style="font-family: monospace;">org.eclipse.ve.example.customwidget</span>) |
| . Strictly speaking this isn't good physical separation of |
| behaviors as the BeanInfo classes should be kept apart from the runtime |
| in a separate package and separate jar so they don't become part of the |
| end user's actual deployment configuration. The Visual Editor |
| does support scenarios where the BeanInfo is in separate packages and |
| separate jars, however for the purpose of this tutorial the class <span |
| style="font-family: monospace;">org.eclipse.ve.examples.customwidget.MyCustomPrompterBeanInfo</span> |
| will be created that extends the abstract superclass <span |
| style="font-family: monospace;">java.beans.SimpleBeanInfo</span>.</p> |
| <p>The full source code for the BeanInfo can be downloaded from <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/prompter/MyCustomPrompterBeanInfo.java"> |
| CVS.</a> A BeanInfo class is responsible for describing the list |
| of properties used by a tool such as the Visual Editor, and also their |
| edit time behavior. This is done by specializing the method <span |
| style="font-family: monospace;">PropertyDescriptor[] |
| getPropertyDescriptors()</span>. The method returns an array of <span |
| style="font-family: monospace;">java.beans.PropertyDescriptor</span> |
| objects, each one representing an item that will appear as a row in the |
| Properties view and containing information about its display name, the |
| Java get and set method associated with the property, as well as the |
| rules for how the property shoud be edited. The specification |
| allows support for editing behavior is provided by having a <span |
| style="font-family: monospace;">java.beans.PropertyEditor</span> |
| defined against the <span style="font-family: monospace;">PropertyDescriptor</span>, |
| and while the Visual Editor will work correctly if a <span |
| style="font-family: monospace;">PropertyEditor</span> class has been |
| defined it also supports a shorthand notation for describing a list of |
| enumerated values because this pattern occurs frequently in widget |
| libraries (for example orientation properties on scroll bars, alignment |
| values on layout constraints, etc...) and is the pattern used by the |
| MyCustomPrompter's <span style="font-style: italic;">type</span> |
| property. This shorthand notation involves defining a key value |
| pair on the PropertyDescriptor, the key of which is the string literal <span |
| style="font-style: italic;">enumerationValues</span> and the value of |
| which is an array of tri values. The structure of the array is a |
| repeating set of <span style="font-weight: bold;">displayName, value, |
| initializationString</span>. The displayName is the user visible |
| string shown to the user in the Properties view, the value is the |
| actual object that identifies the trivalue against a live property |
| setting, and the initializationString is the fully qualified code |
| fragment that is generated as argument to the property's set |
| method. This is illustrated below in the method <span |
| style="font-family: monospace;">getPropertyDescriptors()</span> for |
| the class <span style="font-family: monospace;">MyCustomPrompterBeanInfo</span>.</p> |
| <pre> <span style="color: rgb(153, 0, 0);">public</span> PropertyDescriptor[] getPropertyDescriptors() {<br><br> <span |
| style="color: rgb(153, 0, 0);">try</span> {<br> PropertyDescriptor[] result = <span |
| style="color: rgb(153, 0, 0);">new</span> PropertyDescriptor[2];<br><br> result[0] = <span |
| style="color: rgb(153, 0, 0);">new</span> PropertyDescriptor(<span |
| style="color: rgb(51, 51, 255);">"text"</span>,MyCustomPrompter.class);<br> result[1] = <span |
| style="color: rgb(153, 0, 0);">new</span> PropertyDescriptor<span |
| style="font-weight: bold;">(<span style="color: rgb(51, 51, 255);">"type"</span></span>,MyCustomPrompter.class);<br><br> result[1].setValue(<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"><span |
| style="color: rgb(51, 51, 255);">"enumerationValues"</span>, <span |
| style="color: rgb(153, 0, 0);">new</span> Object[] {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <span |
| style="color: rgb(51, 51, 255);">"Dots"</span>, <span |
| style="color: rgb(153, 0, 0);">new</span> Integer(MyCustomPrompter.<span |
| style="color: rgb(51, 51, 255); font-style: italic;">DOTS</span>), <span |
| style="color: rgb(51, 51, 255);">"org.eclipse.ve.example.customwidget.prompter.MyCustomPrompter.DOTS"</span>,<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> <span |
| style="color: rgb(51, 51, 255);">"More"</span>, <span |
| style="color: rgb(153, 0, 0);">new</span> Integer(MyCustomPrompter.<span |
| style="color: rgb(51, 51, 255); font-style: italic;">MORE</span>), <span |
| style="color: rgb(51, 51, 255);">"org.eclipse.ve.example.customwidget.prompter.MyCustomPrompter.MORE"</span>,<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> <span |
| style="color: rgb(51, 51, 255);">"Open"</span>, <span |
| style="color: rgb(153, 0, 0);">new</span> Integer(MyCustomPrompter.<span |
| style="color: rgb(51, 51, 255); font-style: italic;">OPEN</span>), <span |
| style="color: rgb(51, 51, 255);">"org.eclipse.ve.example.customwidget.prompter.MyCustomPrompter.OPEN"</span> <br> });<br> <br> <span |
| style="color: rgb(153, 0, 0);">return</span> result;<br> } <span |
| style="color: rgb(153, 0, 0);">catch</span> (IntrospectionException e) { <br> e.printStackTrace();<br> <span |
| style="color: rgb(153, 0, 0);">return null</span>;<br> }<br>}<br></pre> |
| <p>The getPropertyDescriptors() method returns an array of two |
| properties; <span style="font-style: italic;">text</span> and <span |
| style="font-style: italic;">type. </span> The <span |
| style="font-style: italic;">type</span> property has a key value pair |
| assigned to it with a key of <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_1.gif"> <span style="font-style: italic;">enumerationValues</span> |
| and a value that is an array of nine elements. These nine |
| elements represent the three enumerated values defined as a |
| tri-values. The first of these is for the value 0 and is defined |
| as <span style="font-weight: bold;">displayName,value,initString</span> |
| of <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> "Dots", 0, "0". Instead of hard |
| coding the 0 however they are coded to be the dynamic lookups of the |
| actual value from the static constant, allowing the constant to |
| internally change without requiring BeanInfo modification. The |
| other two values <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_3.gif"> "More" and <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> |
| "Open" are defined as tri-values for the 4th, 5th and 6th elements of |
| the array and the 7th, 8th and 9th respectively.</p> |
| <p>The <span style="font-family: monospace;">getPropertyDescriptors()</span> |
| method returns a fully inclusive set of property descriptors for the |
| JavaBean. For <span style="font-family: monospace;">MyCustomPrompter</span> |
| the user experience the tutorial wants is that the inherited properties |
| such as background, foreground, size, etc.. are present on the |
| class. To achieve this rather than having the <span |
| style="font-family: monospace;">getPropertyDescriptors()</span> method |
| collect the full list of all desired properties, the JavaBeans |
| specification allows for the method <span |
| style="font-family: monospace;">BeanInfo[] getAdditionalBeanInfo()</span> |
| to be specialized. This returns an array of <span |
| style="font-family: monospace;">BeanInfo</span> classes whose |
| properties are merged together with the result of <span |
| style="font-family: monospace;">getPropertyDescriptors()</span> to |
| create the complete list.</p> |
| <pre> <span style="color: rgb(153, 0, 0);">public</span> BeanInfo[] getAdditionalBeanInfo(){<br> <span |
| style="color: rgb(153, 0, 0);">try</span>{<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <span |
| style="color: rgb(153, 0, 0);">return new</span> BeanInfo[]{Introspector.<span |
| style="font-style: italic;">getBeanInfo</span>(Control.<span |
| style="color: rgb(153, 0, 0);">class</span>)};<br> } <span |
| style="color: rgb(153, 0, 0);">catch</span> (IntrospectionException e){<br> <span |
| style="color: rgb(153, 0, 0);">return new</span> BeanInfo[0];<br> }<br></pre> |
| <img src="../images/tip.gif" alt="Note:" style="width: 62px; height: 13px;"> |
| <p>To create the array of BeanInfo classes representing the set of |
| descriptors to merge one technique might be to write the code <span |
| style="font-family: monospace;"><span style="color: rgb(153, 0, 0);">return |
| new</span> BeanInfo[] {CompositeBeanInfo.<span |
| style="color: rgb(153, 0, 0);">class</span>, ControlBeanInfo.<span |
| style="color: rgb(153, 0, 0);">class</span>, WidgetBeanInfo.<span |
| style="color: rgb(153, 0, 0);">class</span>}</span>. However |
| doing so would be an attempt to hard code the names of the BeanInfo |
| classes that may currently be associated with the superclass chain of <span |
| style="font-family: monospace;">MyCustomPrompter</span> but would fail |
| if new BeanInfo classes were introduced or removed. The preferred |
| technique for picking up inherited properties is with the statement <span |
| style="font-family: monospace;"><span style="color: rgb(153, 0, 0);">return |
| new</span> BeanInfo[]{Introspector.<span style="font-style: italic;">getBeanInfo</span>(Composite.<span |
| style="color: rgb(153, 0, 0);">class</span>)}</span> where the |
| argument to the <span |
| style="font-style: italic; font-family: monospace;">getBeanInfo</span><span |
| style="font-family: monospace;">(Class aClass)</span> method is the |
| current bean's superclass. Rather than using <span |
| style="font-family: monospace;">Composite</span> as the starting point |
| for merging inherited properties which is the immediate superclass of <span |
| style="font-family: monospace;">MyCustomPrompter</span>, <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> |
| <span style="font-family: monospace;">Control</span> is used |
| instead. The reason for this is that while <span |
| style="font-family: monospace;">MyCustomPrompter</span> extends <span |
| style="font-family: monospace;">Composite</span> it does this more for |
| physical reasons so it can have its three child controls (the <span |
| style="font-family: monospace;">Label</span>, <span |
| style="font-family: monospace;">Text</span> and <span |
| style="font-family: monospace;">Button</span>), however as a black box |
| custom class it itself doesn't want to inherit the behavior of <span |
| style="font-family: monospace;">Composite</span> such as the ability |
| to have its layout changed. For this reason it is logically a |
| subclass of <span style="font-family: monospace;">Control.</span></p> |
| <h3><a name="Testing_the_enumerated_values_for_type"></a>Testing the |
| enumerated values for <span style="font-style: italic;">type</span></h3> |
| <p>Having updated <span style="font-family: monospace;">MyCustomPrompterBeanInfo.java</span> |
| this must be re-exported to the <span style="font-style: italic;">customwidgets.jar</span> |
| file. The customwidgets.jar in the plugin is the one that the <span |
| style="font-style: italic;">Custom Prompter</span> classpath container |
| uses in its build path, and if the step of re-creating the <span |
| style="font-style: italic;">customwidgets.jar</span> file is not done |
| when you launch the Eclipse Application you will be using the old |
| version of the code. Currently Eclipse 3.1 does not support |
| classpath container entries pointing to folder structures otherwise the |
| RegisteredClassPathContainer could be coded to automatically look back |
| into the directory structure of the development environment that |
| launched it so for now don't forget to keep re-creating the <span |
| style="font-style: italic;">customwidgets.jar</span> file each time |
| any of its contents have changed.</p> |
| <img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| <p>The Visual Editor caches information about a class and under some |
| builds prior to VE 1.1 there are some issues with the cache going stale |
| and not being automatically refreshed. If this occurs you can |
| manually recycle the cache by selecting <span |
| style="font-weight: bold;">Project > Clean</span> and also manually |
| removing the directory <span style="font-style: italic;">org.eclipse.ve.beaninfo/cache</span> |
| from the workbench directory. <br> |
| <br> |
| The changes to the <span style="font-family: monospace;">MyCustomPrompterBeanInfo</span> |
| should mean that the <span style="font-style: italic;">type</span> |
| property is now rendered with its display name rather than just the raw |
| <span style="font-family: monospace;">int</span> value. The |
| Properties view also will create a drop down list of the three |
| allowable values. The figure below shows the list of the three |
| values and when one is selected the argument to the <span |
| style="font-family: monospace;">setType(int)</span> method will be |
| generated with the initializationString as defined in the <span |
| style="font-family: monospace;">BeanInfo</span> array.<br> |
| <br> |
| <br> |
| <img style="border: 1px solid ; width: 808px; height: 527px;" alt="" |
| src="images/TypeCodeGeneration.png"><br> |
| <br> |
| The BeanInfo mechanism provides one technique to override default edit |
| behavior for a Java class. The Visual Editor uses BeanInfo |
| classes internally for many of its customizations and it recognizes |
| externally created BeanInfo classes according to the JavaBeans |
| specification.<br> |
| <br> |
| Some kinds of customization are not possible through the BeanInfo |
| mechanism because while it provides a powerful way to describe edit |
| time behavior and shape for a class the Visual Editor needs to be able |
| to export some of its innermost extension points to the creator of the |
| Java class, and the BeanInfo mechanism is designed to provide a |
| portable way of customizing a Java class that can be transported easily |
| between different IDEs and tools. For example, the next exercise |
| in the tutorial is to override the behavior that occurs when the <span |
| style="font-style: italic;">text</span> property is edited to launch a |
| dialog editor. This dialog editor will be written using the SWT |
| and implement Eclipse specific interfaces, so describing it on the |
| BeanInfo would violate the idea that BeanInfo classes are portable (as |
| Eclipse interfaces and the SWT are not necessarily available to other |
| visual design tools).<br> |
| <br> |
| For this reason the Visual Editor has a separate mechanism to extend a |
| class's edit time behavior that is done through <span |
| style="font-style: italic;">override</span> files<span |
| style="font-style: italic;">.</span> This works in conjunction with |
| the BeanInfo mechanism and provides the ability to leverage any Eclipse |
| IDE or Visual Editor specific behavior for a class.</p> |
| <h2><a name="The_EMF_override_mechanism"></a>The EMF override mechanism</h2> |
| <p>At the heart of the Visual Editor is an EMF model that describes a |
| class being edited. This model describes the instances, their |
| relationships, scope, and property settings. Instances of objects in |
| this model implement <span style="font-family: monospace;">org.eclipse.jem.internal.instantiation.base.IJavaInstance</span>. |
| For example, a visual editor class that has a <span |
| style="font-family: monospace;">Shell</span> whose size is 200,200 |
| will contain two <span style="font-family: monospace;">IJavaInstance</span> |
| objects. The first of these is for the <span |
| style="font-family: monospace;">Shell</span> itself and the second is |
| for a <span style="font-family: monospace;">Point</span> representing |
| the size. An EMF relationship between the <span |
| style="font-family: monospace;">Shell</span> and the <span |
| style="font-family: monospace;">Point</span> instance will exist whose |
| structural feature represents the size property.<br> |
| <br> |
| EMF is a self describing structure, so behind the instance model there |
| is a meta-model that describes the classes themselves - their methods, |
| properties, events and hierarchy. The meta-model is created by the |
| Visual Editor using a combination of reflection and JavaBeans |
| Introspection. Instances in this metamodel consist of <span |
| style="font-family: monospace;">org.eclipse.jem.java.JavaClass</span> |
| for each Java class. The structural features in the model are |
| instances of EReference and represent the properties of the Java class.</p> |
| <p>There are times when it is necessary to provide additional |
| information that should be merged in with the EMF model of a |
| JavaClass. An example of this is a new feature has to be added |
| over and above those that can be determined by reflection.</p> |
| <p>The Visual Editor uses the EMF model of a JavaClass not only to |
| define its shape but also to define a number of helper classes used by |
| the Visual Editor. These are typically mediator classes that are |
| used by the different Visual Editor subsystems. The names of the |
| mediator classes to use for a given JavaClass are held in the EMF |
| model, thereby allowing specific classes to have custom behavior for |
| each subsystem. Rather than hold these directly against the |
| JavaClass (which is a generic model of Java classes that can be used by |
| Eclipse plugins other than the Visual Editor) they are held |
| against decorator classes that annotate the descriptive information of |
| a class. These can be thought of similar to key value pairs that |
| hold information rather than provide functionality. </p> |
| <p>In summary, override files are used as means to modify, add to or |
| delete from an EMF JavaClass whose shape is determined through using |
| standard Java reflection combined with BeanInfo introspection.</p> |
| <p>For a plugin to contribute override files its plugin manifest must |
| implement the extension point <span style="font-style: italic;">org.eclipse.jem.beaninfo.registrations</span>. |
| This specifies the trigger in the build path that will cause the |
| overrides to be applied (either a classpath container or pre-requisite |
| project) as well as the name of a Java package and where override files |
| for its contents are held within the plugin folder structure. The |
| code below shows the extension used for the plugin.xml for the <span |
| style="font-style: italic;">org.eclipse.ve.examples.customwidget</span> |
| example in this tutorial.</p> |
| <pre> <extension<br> point="org.eclipse.jem.beaninfo.registrations"><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <registration container="org.eclipse.ve.example.PrompterContainer"><br> <override<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> package="org.eclipse.ve.example.customwidget.prompter"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> path="overrides/org/eclipse/ve/example/customwidget/prompter"><br> </override><br> </registration><br> </extension><br></pre> |
| <p>The classpath container with an id of <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> is |
| the one used by the <span style="font-style: italic;">Custom Prompter</span> |
| library. The class being overriden is <span |
| style="font-family: monospace;">org.eclipse.ve.example.customwidget.prompter.MyCustomPrompter</span> |
| so its<img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> package is declared together with <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> a |
| folder location for where the override files will be stored. The |
| location of the override folder is up to the creator of the plugin and |
| is any arbitrary folder, however there is a convention that the Visual |
| Editor uses where override files are held in a top level folder called <span |
| style="font-style: italic;">overrides</span> and then sub folders |
| created for the package path. The Figure below shows the |
| directory structure of the <span style="font-style: italic;">org.eclipse.ve.example.customwidget</span> |
| plugin with the folder structure of <span style="font-style: italic;">/overrides/org/ecliose/ve/example/customwidget/prompter</span> |
| (which matches that defined in the registration path=<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| extension point). </p> |
| <p><img style="border: 1px solid ; width: 361px; height: 253px;" alt="" |
| src="images/OverrideFileStructure.png"></p> |
| <p>The Figure also shows a file <font face="Courier New">MyCustomPrompter.override</font> |
| present in the override directory for the package. When the |
| Visual Editor builds up the EMF JavaClass instance representing the |
| shape of the MyCustomPrompter class this file will be read and merged |
| into the definition. The syntax of this file can become complex |
| due to the number of different ways in which different JavaClasses |
| needed to be leveraged to implement custom functionality. |
| The remainder of the three examples in this tutorial are each achieved |
| through settings in the .override file. These are:</p> |
| <ul> |
| <li>Custom cell editing for the text property</li> |
| <li>Overriding a GEF edit part</li> |
| <li>Overriding an expression decoder</li> |
| </ul> |
| <p>Each of these three is done through adding decorator classes. |
| Decorator classes are added to ECore elements in the EMF model |
| representing a class, either the JavaClass itself or an EReference |
| representing one of its structural features Decorators are |
| added through the <annotations> property of an ECore object.</p> |
| <p>The type <span style="font-family: monospace;">org.eclipse.ve.internal.cde.decorators.BasePropertyDecorator</span> |
| is responsible for specifying property sheet information such as the |
| name of the classes for the JFace label provider or cell editor, or |
| whether the entry in the property sheet should override the default |
| behavior for whether it is expandable, whether null values are allowed, |
| etc...</p> |
| <p>The type <span style="font-family: monospace;">org.eclipse.ve.internal.cde.decorators.ClassDescriptorDecorator</span> |
| is responsible for specifying custom GEF behavior such as custom edit |
| parts for the graphical editor or the Java Beans tree view.</p> |
| <h2><a name="Creating_A_SWT_cell_editor">Custom cell editing for the <span |
| style="font-style: italic;">text</span> property</a></h2> |
| <p>Because <span style="font-family: monospace;">MyCustomPrompterBeanInfo</span> |
| returns a <span style="font-style: italic;">text <span |
| style="font-family: monospace;">PropertyDescriptor</span></span> <span |
| style="font-family: monospace;"><span |
| style="font-family: arial,helvetica,geneva;">in</span></span> list of |
| properties from the method <span style="font-family: monospace;">getPropertyDescriptors()[]</span> |
| it will be included as an entry in the Properties view. Even |
| without the explicit BeanInfo the class's signature includes the two |
| methods <span style="font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">public</span> String getText()</span> |
| and <span style="font-family: monospace; color: rgb(153, 0, 0);">public</span> |
| <span style="font-family: monospace;">void setText(String aText)</span> |
| which, because they follow the JavaBeans specification naming |
| convention for a property's get and set methods, would be automatically |
| detected by the Visual Editor through Introspection.</p> |
| <p>The rules for the Properties view is that for a given property a |
| BasePropertyDecorator is first looked for on the EReference |
| representing the property in the EMF model. If one is found and |
| it has an explicit labelProviderClassName or cellEditorClassName then |
| this is used as appropiate. This is the mechanism that will be |
| used for the <span style="font-style: italic;">text</span> |
| property. If no decorator exists in the property defining an |
| editor then if the EReference came originally through introspection the |
| java.beans.PropertyDescriptor is queried to look for a |
| propertyEditorClass or key of <span style="font-style: italic;">enumerationValues. </span> |
| Failing both of these a default editor is used for the type of the |
| property.</p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| To determine the default editor for a property based on its type a <span |
| style="font-family: monospace;">BasePropertyDecorator</span> on the <span |
| style="font-family: monospace;">JavaClass</span> EMF definition is |
| used. If no direct decorator can be found annotating the <span |
| style="font-family: monospace;">JavaClass</span> then the superclass |
| chain is searched to look for a decorator that provides a custom cell |
| editor or label provider. For example, the <span |
| style="font-style: italic;">text</span> property is typed to <span |
| style="font-family: monospace;">java.lang.String</span> and the plugin |
| <span style="font-style: italic;">org.eclipse.ve.java.core</span> |
| provides a <span style="font-style: italic;">String.override</span> |
| file that annotates the <span style="font-family: monospace;">JavaClass</span> |
| with a a <span style="font-family: monospace;">BasePropertyDecorator</span> |
| defining the label provider as <span style="font-family: monospace;">org.eclipse.ve.internal.java.core.StringJavaLabelProvider</span> |
| and the cell editor as <span style="font-family: monospace;">org.eclipse.ve.internal.java.core.StringJavaCellEditor.</span> |
| This is an example of where the Visual Editor's implementations of the |
| JFC and SWT are done thoroughly using its own API.</p> |
| <p>The cell editor that will be written for the <span |
| style="font-style: italic;">text</span> property will be placed in the |
| package <span style="font-family: monospace;">org.eclipse.ve.example.customwidget</span>. |
| This package will form part of the contents of the plugin jar that |
| makes up the code that runs in the workbench and extends the Visual |
| Editor with new Eclipse workbench behavior. The class created is <span |
| style="font-family: monospace;">org.eclipse.ve.example.customwidget.CustomLabelEditor</span> |
| and extends the abstract superclass <span |
| style="font-family: monospace;">org.eclipse.jface.viewers.DialogCellEditor</span>. </p> |
| <p>IDE specific extensions are defined by annotating the EMF JavaClass |
| meta object that the Visual Editor uses. This is done with a |
| .override file, and the contents of <span style="font-style: italic;">MyCustomPrompter.override</span> |
| should be written as follows:</p> |
| <pre> <?xml version="1.0" encoding="UTF-8"?><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <xmi:XMI xmi:version="2.0" <br> xmlns:xmi="http://www.omg.org/XMI" <br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br> xmlns:org.eclipse.ve.internal.cde.decorators="http:///org/eclipse/ve/internal/cde/decorators.ecore"<br> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" <br> xmlns:event="event.xmi"><br><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <event:Add featureName="eStructuralFeatures"><br> <addedEObjects xsi:type="ecore:EReference" <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif">name="text" unsettable="true"><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> <eAnnotations<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> xsi:type="org.eclipse.ve.internal.cde.decorators:BasePropertyDecorator" <br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> cellEditorClassname="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomLabelEditor"/><br> </addedEObjects><br> </event:Add><br><br> </xmi:XMI><br></pre> |
| <p>The header of a .override file declares the namespaces of the EMF |
| packages used. Two packages are required to define the objects |
| required for the CustomLabelEditor, the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> |
| decorators.ecore package and the event model's package.</p> |
| <p>The purpose of the file is to create a BasePropertyDecorator that |
| defines the cell editor and annotate the structural feature for the <span |
| style="font-style: italic;">text</span> property. This is done |
| by <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> adding a structural feature whose name is <span |
| style="font-style: italic;"><img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_3.gif"></span> <span |
| style="font-style: italic;">text. </span> Even through the object |
| used is an <span style="font-style: italic;">Add</span> from the event |
| model, the Visual Editor will pick up the fact that there is a <span |
| style="font-style: italic;">text</span> property defined from |
| introspection (the one explicitly specified in the |
| MyCustomPrompterBeanInfo or in its absence the one determined through |
| get and set method pair matching) and merge in with this |
| property. This way information that has come from introspection |
| such as the get and set method names are combined with the EReference |
| defined in the .override file.</p> |
| <p>The <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_4.gif"> eAnnocations property defines the |
| annotations for the EReference and the class we're creating is an |
| instance of <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_5.gif"> <font face="Courier New">org.eclipse.ve.internal.cde.decorators.BasePropertyDecorator</font>. |
| <img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> The <a name="xsi:type_structure"></a>xsi:type |
| structure does not point to the |
| Java package directly. The first portion of |
| org.eclipse.ve.internal.cde.decorators points to the name of a |
| namespace defined in the <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_1.gif"> xmi:XMI opening tag. This |
| namespace relates to the URL of decorators.ecore EMF package that |
| itself is declared in the plugin org.eclipse.ve.cde with its own use of |
| the extension point <span style="font-style: italic;">org.eclipse.emf.ecore.generated_package</span> |
| to be the EMF package class |
| org.eclipse.ve.internal.cde.decorators.DecoratorsPackage.</p> |
| <p>The class |
| org.eclipse.ve.internal.cde.decorators.BasePropertyDecorator has an EMF |
| feature <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_6.gif"> cellEditorClassname. This will be |
| used by the Visual Editor in the Properties view when the property is |
| edited and points to our custom editor.</p> |
| <p>Having defined the .override file that extends the <span |
| style="font-family: monospace;">MyCustomPrompter</span>'s <span |
| style="font-style: italic;">text</span> feature to have a custom IDE |
| cell editor the next step is to write the code for the custom editor |
| itself. <span style="font-family: monospace;">CustomLabelEditor</span> |
| extends DialogCellEditor that provides the framework support for |
| displaying a button to open the actual dialog. </p> |
| <p><img style="border: 1px solid ; width: 211px; height: 46px;" alt="" |
| src="images/TextPropertyCellEditor.png"></p> |
| <p>The next step is to write the dialog that allows the user to edit |
| the <span style="font-style: italic;">text</span> property and ensure |
| that this is launched from CustomLabelEditor.</p> |
| <p>The dialog is created by extending the JFace helper class <span |
| style="font-family: monospace;">org.eclipse.jface.dialogs.TitleAreaDialog</span> |
| that provides support for the title area and buttons. The content |
| or client area of this will be built using the Visual Editor itself as |
| a visual component class <span style="font-family: monospace;">org.eclipse.ve.example.customwidget.LabelDialogContentArea.</span></p> |
| <p><img style="width: 719px; height: 524px;" alt="" |
| src="images/CustomTextEditorDialog.png"></p> |
| <p> </p> |
| <p>To logic for what occurs when the dialog is requested to be open is |
| done by specializing the method <span style="font-family: monospace;">openDialogBox(Control |
| cellEditorWindow)</span> in <span style="font-family: monospace;">CustomLabelEditor<span |
| style="font-family: arial,helvetica,geneva;">.</span></span> The |
| contents for this method are shown below and perform two important |
| steps. The first of these is to open an actual dialog that lets |
| the user specify their text property, and the second is to get the |
| result of this and create a new <span style="font-family: monospace;">IJavaInstance</span> |
| that represents the next String for the Visual Editor's EMF instance |
| model. The code below shows how to do this for <span |
| style="font-family: monospace;">CustomLabelEditor</span>.</p> |
| <pre><span style="color: rgb(153, 0, 0);">protected</span> Object openDialogBox(Control cellEditorWindow) {<br> Display display = cellEditorWindow.getDisplay();<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> TitleAreaDialog dialog = <span |
| style="color: rgb(153, 0, 0);">new</span> TitleAreaDialog(display.getActiveShell()) {<br> LabelDialogContent content;<br> <span |
| style="color: rgb(153, 0, 0);">protected</span> Control createContents(Composite parent) {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> Control result = super.createContents(parent);<br> setTitleImage(CustomwidgetPlugin.getCustomImage());<br> setTitle(<span |
| style="color: rgb(51, 51, 255);">"Prompter's text property editor"</span>);<br> setMessage(<span |
| style="color: rgb(51, 51, 255);">"Enter the text property, or select a default one by checking the Hello or GoodBye"</span>,IMessageProvider.<span |
| style="font-style: italic;">INFORMATION</span>); <br> <span |
| style="color: rgb(153, 0, 0);">return</span> result;<br> }<br> <span |
| style="color: rgb(153, 0, 0);">protected</span> Control createDialogArea(Composite parent) {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> content = <span |
| style="color: rgb(153, 0, 0);">new</span> LabelDialogContent(parent, SWT.<span |
| style="font-style: italic; color: rgb(51, 51, 255);">NONE</span>);<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> content.setString(stringValue);<br> <span |
| style="color: rgb(153, 0, 0);">return</span> content;<br> }<br> <span |
| style="color: rgb(153, 0, 0);">public</span> String toString() {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> <span |
| style="color: rgb(153, 0, 0);">return</span> content.getString();<br> }<br> }; <br> <span |
| style="color: rgb(153, 0, 0);">if</span> (dialog.open() != Window.<span |
| style="font-style: italic; color: rgb(51, 51, 255);">CANCEL</span>) {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> <span |
| style="color: rgb(153, 0, 0);">return</span> createStringJavaObject(dialog.toString());<br> } <span |
| style="color: rgb(153, 0, 0);">else</span> { <span |
| style="color: rgb(153, 0, 0);"> return</span> getValue();<br> }<br> }<br></pre> |
| <p>The dialog editor used is an <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> |
| inner class that extends the jface abstract class |
| org.eclipse.jface.dialogs.TitleAreaDialog. Three methods are |
| specialized:</p> |
| <p>The createContents(Composite parent) method is used to build the |
| actual SWT content area of the dialog. The TitleAreaDialog |
| supeclass provides a default structure that is invoked through |
| calling <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> <span style="font-family: monospace;">super.createContents(parent)</span>, |
| although details such as the image and title are overridden. The |
| content area of the dialog is the area we're interested in putting out |
| custom editing experience into, and this is done by creating an |
| instance of <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_3.gif"> <span style="font-family: monospace;">LabelDialogContent</span> |
| (that is built below).</p> |
| <p>The content area for the TitleAreaDialog created by the |
| LabelCellEditor is the class |
| org.eclipse.ve.examples.customwidget.LabelDialogContent. This is |
| available in CVS <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/LabelDialogContent.java">LabelDialogContent.java</a> |
| and extends <span style="font-family: monospace;">org.eclipse.swt.Composite</span> |
| and was built using the Visual Editor. This has the methods <span |
| style="font-family: monospace;">public setString(String aString)</span> |
| to set the current value of the String, and <span |
| style="font-family: monospace;">public String getString()</span> to |
| return it. These are both called by the <span |
| style="font-family: monospace;">CustomLabelEditor</span> when it <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> |
| initializes the content area and <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> |
| returns the value. </p> |
| <p>The <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_5.gif"> <span style="font-family: monospace;">toString()</span> |
| method is specialized to return the value of the LableDialogContent, |
| which represents the String entered by the user as the new <span |
| style="font-style: italic;">text</span> property. This is so |
| that the value can be referenced by the CustomLabelEditor itself when |
| it <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_6.gif">has created the actual object that will be |
| set into the Visual Editor model.</p> |
| <p>If the TitleAreaDialog isn't cancelled then the JFace cell editor |
| needs to return the value of the newly created object representing the |
| value of the <span style="font-style: italic;">text</span> |
| property. The LabelDialogContent returns a java.lang.String and |
| this requires conversion into an IJavaInstance representing the EMF |
| JavaClass instance for the Visual Editor's model. This is done |
| with the helper method <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_6.gif"> <span style="font-family: monospace;">IJavaInstance |
| createStringJavaObject(String aString);</span></p> |
| <p>To create an <span style="font-family: monospace;">IJavaInstance</span> |
| requires two steps. First the EMF <span |
| style="font-family: monospace;">JavaClass</span> needs to be located |
| and then an instance of <span style="font-family: monospace;">IJavaInstance</span> |
| needs to be created using this with rules as to how the actual |
| instantion of the live Java object should occur (both in code and by |
| the target VM).</p> |
| <p>To locate a <span style="font-family: monospace;">JavaClass</span> |
| involves looking up for the object on the current resource set. A |
| resource set is a physical grouping of EMF documents and to locate the |
| one being used by the Visual Editor it is held on the editorPart's GEF |
| editDomain. The Visual Editor uses a subclass of default GEF edit |
| domain called <span style="font-family: monospace;">org.eclipse.ve.internal.cde.core.EditDomain</span>. |
| The editDomain provides a way of passing common objects (such as the |
| target VM helper classes, the set of viewers, and the EMF resource set) |
| around between different Visual Editor subsystems. For a cell |
| editor to be given a reference to the edit domain it should implement |
| the interface <span style="font-family: monospace;">org.eclipse.ve.internal.propertysheet.INeedData</span> |
| that has a single method <span style="font-family: monospace;">public |
| void setData(Object data); </span> The argument to this will be |
| set by the Visual Editor to the editDomin object and the cell editor |
| should store this in an instance variable.</p> |
| <pre><span style="font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">public class</span> CustomLabelEditor <span |
| style="color: rgb(153, 0, 0);">extends</span> DialogCellEditor <span |
| style="color: rgb(153, 0, 0);">implements</span> INeedData {<br> private EditDomain fEditDomain;<br></span><span |
| style="font-family: monospace;"><span style="font-family: monospace;"><span |
| style="color: rgb(51, 204, 0);"><span style="color: rgb(0, 153, 0);"> // Remainder of class definition ...</span></span></span><br></span></pre> |
| and<br> |
| <pre> <span style="color: rgb(153, 0, 0);">public void</span> setData(Object data) {<br> fEditDomain = (EditDomain) data;<br> }<br></pre> |
| <p>To lookup the resource set from an EditDomain can be done using the |
| static helper method<span style="font-family: monospace;">JavaEditDomainHelper.getResourceSet(EditDomain |
| anEditDomain);</span></p> |
| <p>Now that the <span style="font-family: monospace;">CustomLabelEditor</span> |
| has a handle to the Visual Editor's model's resource set it can look up |
| <span style="font-family: monospace;">JavaClass</span> objects using |
| the API <span style="font-family: monospace;">org.eclipse.jem.internal.beaninfo.core.Utilities.getJavaClass(String |
| className, ResourceSet resourceSet);</span> In EMF to |
| instantiate actual objects the package's factory should be used, so |
| having obtained the <span style="font-family: monospace;">JavaClass</span> |
| to get the <span style="font-family: monospace;">IJavaInstance</span> |
| requires the method call <span style="font-family: monospace;">javaClass.getEPackage().getEFactoryInstance().create(javaClass);</span> </p> |
| <p>Rather than having to do both steps however there is a helper API |
| method <span style="font-family: monospace;">org.eclipse.ve.internal.java.core.BeanUtilities.createJavaObject(String |
| qualifiedClassName, ResourceSet aResourceSet, String initString)</span>; |
| Examples of its usage are shown below:</p> |
| <pre>BeanUtilities.createJavaObject(<span |
| style="color: rgb(51, 51, 255);">"java.lang.Boolean"</span>, aResourceSet, <span |
| style="color: rgb(51, 51, 255);">"Boolean.TRUE"</span>); <span |
| style="color: rgb(0, 153, 0);">// Create a Boolean.TRUE instance</span><br>BeanUtilities.createJavaObject(<span |
| style="color: rgb(51, 51, 255);">"java.awt.Color"</span>, aResourceSet , <span |
| style="color: rgb(51, 51, 255);">"java.awt.Color.red"</span>); <span |
| style="color: rgb(0, 153, 0);">// Create an instance of the AWT color red</span><br>BeanUtilities.createJavaObject(<span |
| style="color: rgb(51, 51, 255);">"boolean"</span>, aResourceSet, <span |
| style="color: rgb(51, 51, 255);">"true"</span>); <span |
| style="color: rgb(0, 153, 0);">// Create an instance of the primitive boolean true</span><br>BeanUtilities.createJavaObject(<span |
| style="color: rgb(51, 51, 255);">"java.lang.String"</span>, aResourceSet, <span |
| style="color: rgb(51, 51, 255);">"\\"Hello World\\""</span>); <span |
| style="color: rgb(0, 153, 0);">// Create an instance of the String "Hello World"</span> |
| </pre> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| The third argument to the method represents the code fragment that will |
| be used to instantiate the actual live Java instance. This is the |
| actual argument that is used by the Visual Editor when it generates the |
| <span style="font-family: monospace;">setProperty(Object propertyValue)</span> |
| method. For the last example that was itself a String for the |
| quotation marks to be present in the String when the code is generated |
| they must be present in the literal itself which requires escaping them |
| with a <span style="color: rgb(51, 51, 255);">\\.</span></p> |
| <p>The protected helper method on <span style="font-family: monospace;">CustomLabelEditor</span> |
| and called by <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_6.gif"> <span style="font-family: monospace;">openDialogBox(Control |
| cellEditorWindow)</span> can now be written as follows.</p> |
| <pre> <span style="color: rgb(153, 0, 0);">private</span> IJavaInstance createStringJavaObject(String aString) {<br> <span |
| style="color: rgb(153, 0, 0);">return</span> BeanUtilities.createJavaObject(<br> <span |
| style="color: rgb(51, 51, 255);">"java.lang.String"</span>,<br> JavaEditDomainHelper.getResourceSet(fEditDomain),<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> BeanUtilities.createStringInitString(aString)<br> );<br> }<br></pre> |
| <p>Rather than just writing <span style="color: rgb(51, 51, 255);">"\\"</span> |
| + aString + <span style="color: rgb(51, 51, 255);">"\\"</span> a |
| helper method on <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <span style="font-family: monospace;">BeanUtilities</span> |
| is used to quote the user's string. The helper handles cases such |
| as the string containing bona-fide escape characters the user put there |
| that themselves need quoting.</p> |
| <h3><a name="Rendering_the_text_value_in_the"></a>Rendering the <span |
| style="font-style: italic;">text value </span> in the Properties |
| view</h3> |
| <p>When the <span style="font-style: italic;">text</span> property is |
| displayed in the Properties view we wish the user to be able to see the |
| current value. This occurs with nothing extra to be done, because |
| the <span style="font-style: italic;">text</span> property is typed to |
| <span style="font-family: monospace;">java.lang.String</span> and there |
| is a default label provider class for this provided by the <span |
| style="font-style: italic;">org.eclipse.ve.java.core</span> plugin as |
| part of its <span style="font-style: italic;">String.override</span>. |
| For this reason file the Visual Editor already knows how to render |
| String properties as shown below.</p> |
| <p><span style="font-family: monospace;"><img |
| style="border: 1px solid ; width: 266px; height: 63px;" alt="" |
| src="images/TextPropertyDisplayed.png"></span></p> |
| <p>With the CustomLabelEditor however specific code is required to |
| ensure that it displays the current value of the <span |
| style="font-style: italic;">text</span> property</p> |
| <p><img style="border: 1px solid ; width: 265px; height: 66px;" alt="" |
| src="images/TextCurrentValue.png"></p> |
| <p>This is done by specializing the method <span |
| style="font-family: monospace;">doSetValue(Object value); </span> |
| This method is given an argument of an <span |
| style="font-family: monospace;">IJavaInstance</span> which represents |
| the current value of the String object in the Visual Editor's EMF |
| model. To convert from this to this to a <span |
| style="font-family: monospace;">java.lang.String</span> object can be |
| done by accessing the target VM to query the value of the live String |
| object.</p> |
| <p>To write the code for the <span style="font-family: monospace;">doSetValue(Object |
| value)</span> method requires an understanding of the API to work with |
| the Visual Editor target VM objects</p> |
| <h4><a name="Target_VM_and_its_APIs"></a>Target VM and its APIs</h4> |
| <p>Live objects used by the Visual Editor exist only on the target VM |
| and are never loaded by the Visual Editor inside the actual Eclipse |
| workbench's JVM. For every object created on the target VM there |
| is a proxy to it held by the Visual Editor inside the Eclipse |
| JVM. This proxy is an instance of <span |
| style="font-family: monospace;">org.eclipse.jem.internal.proxy.core.IBeanProxy</span> |
| and is able to perform tasks such as remote method invocation on |
| the actual target VM instance.<br> |
| <br> |
| The API for this is modelled on the<span style="font-family: monospace;">java.lang.reflect</span> |
| API however, unlike the reflection API which performs dynamic |
| invocation within a single JVM, the bean proxy mechanism works between |
| the Eclipse workbench's JVM where the proxies are, and Visual Editor's |
| target JVM where the live instances exist.</p> |
| <table style="text-align: left; width: 75%;" border="1" cellspacing="2" |
| cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;">java.lang and java.lang.reflect |
| API</td> |
| <td style="vertical-align: top;">org.eclipse.jem.internal.proxy.core |
| API</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Object</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBeanProxy</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Class</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBeanTypeProxy</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">object.getClass()</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBeanProxy.getTypeProxy()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Method</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IMethodProxy</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Class.getMethod(String methodName)</span> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBeanTypeProxy.getMethodProxy(String |
| methodName)</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Constructor</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IConstructorProxy</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Class.getConstructor(Class[] types)</span> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBeanTypeProxy.getConstructorProxy(IBeanTypeProxy[] |
| types)</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">Constructor.newInstance(Object[] |
| initArgs)</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IConstructorProxy.newInstance(IBeanProxy[] |
| initArgs)</span> </td> |
| </tr> |
| </tbody> |
| </table> |
| <p>To locate instances of <span style="font-family: monospace;">IBeanProxy</span> |
| (from which method and constructor proxies can be retrieved) a factory |
| is used that is held on a proxy factory registry. The registry is |
| used to create and cache instances of <span |
| style="font-family: monospace;">IBeanTypeProxy</span>, and can be |
| located through a helper method which retrieves it from the GEF edit |
| domain. The <span style="font-family: monospace;">IProxyFactoryRegistry</span> |
| can return factories for retrieving instances of IBeanTypeProxy through |
| the method getBeanTypeProxy(String typeName) as well as factories for |
| creating new instances of <span style="font-family: monospace;">IBeanProxy</span> |
| through the overloaded method <span style="font-family: monospace;">getBeanProxy(Object |
| anObject)</span> with arguments representing the nine Java primitives, |
| their <span style="font-family: monospace;">java.lang</span> peers as |
| well as <span style="font-family: monospace;">java.lang.String</span>.</p> |
| <p>The following code samples show how to create an instance of a <span |
| style="font-family: monospace;">java.io.File</span> for the file name <span |
| style="font-style: italic;">"C:\temp\foo.txt"</span> (i.e. the result |
| of evaluating <span style="font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">new</span> java.io.File(<span |
| style="color: rgb(51, 51, 255);">"C:\temp\foo.txt"</span>)</span> on |
| the target VM.</p> |
| <pre>IProxyFactoryRegistry aProxyFactoryRegistry = JavaEditDomainHelper.getBeanProxyDomain(anEditDomain).getProxyFactoryRegistry();<br>IBeanTypeProxy javaIOFileBeanTypeProxy = aProxyFactoryRegistry.getBeanTypeProxy(<span |
| style="color: rgb(51, 51, 255);">"java.io.File"</span>);<br></pre> |
| <p>Having obtained the <span style="font-family: monospace;">IBeanTypeProxy |
| <span style="font-family: arial,helvetica,geneva;">the instance of</span></span> |
| an <span style="font-family: monospace;">IBeanProxy</span> for the |
| java.io.File can be created by locating the correct <span |
| style="font-family: monospace;">IConstructorProxy</span> and calling <span |
| style="font-family: monospace;">newInstance(IBeanProxy[])</span> with |
| the correct arguments.</p> |
| <pre>IBeanProxy fooStringBeanProxy = aProxyFactoryRegistry.getBeanProxyFactory().createBeanProxyWith(<span |
| style="color: rgb(51, 51, 255);">"C:\temp\foo.txt"</span>);<br>IConstructorProxy fileConstructorProxy = javaIOFileBeanTypeProxy.getConstructorProxy(<span |
| style="color: rgb(51, 51, 255);">"java.lang.String"</span>);<br>IBeanProxy fileProxy = fileConstructorProxy.newInstance(fooStringBeanProxy);<br></pre> |
| <p>In addition to locating the IConstructorProxy and invoking as shown |
| above there is a shorthand way of creating a bean proxy with a specific |
| Java initialization string. This is with the method <span |
| style="font-family: monospace;">newInstance(String |
| javaInitializationString)</span> on <span |
| style="font-family: monospace;">IBeanTypeProxy</span>. Using |
| this the above code can be shortened to</p> |
| <pre>IBeanProxy fileProxy = javaIOFileBeanTypeProxy.newInstance(<span |
| style="color: rgb(51, 51, 255);">"C:\temp\foo.txt"</span>);<br></pre> |
| <p>The Visual Editor's model for the Java class being visually is an |
| EMF graph of <span style="font-family: monospace;">IJavaInstance</span> |
| objects. The API method <span style="font-family: monospace;">org.eclipse.jem.internal.proxy.core.BeanProxyUtilities.getBeanProxy(IJavaInstance |
| aJavaInstance)</span> exists to obtain the bean proxy fom a Visual |
| Editor EMF object. These are some more examples of the API for |
| working with bean proxies.</p> |
| <pre><span style="color: rgb(0, 153, 0);">// Retrieve a proxy to the result of calling the method getType() on a target VM for an IJavaInstance of MyCustomPrompter</span><br>IBeanProxy prompterProxy = BeanProxyUtilities.getBeanProxy(prompterJavaInstance); <span |
| style="color: rgb(0, 153, 0);">// Obtain an IBeanProxy from an IJavaInstance</span><br>IMethodProxy getTypeMethodProxy = prompterProxy.getTypeProxy().getMethodProxy(<span |
| style="color: rgb(51, 51, 255);">"getType"</span>);<br>IBeanProxy proxyToGetTypeResult = getTypeMethodProxy.invoke(prompterProxy);<br><br><span |
| style="color: rgb(0, 153, 0);">// Set the value of setType(String) method to the value "Frog"<br></span>IBeanProxy frogProxy = prompterProxy.getProxyFactoryRegistry().getBeanProxyFactory().createBeanProxyWith(<span |
| style="color: rgb(51, 51, 255);">"Frog"</span>);<br>IMethodProxy setTypeMethodProxy = prompterProxy.getTypeProxy().getMethodProxy(<span |
| style="color: rgb(51, 51, 255);">"setType"</span>,<span |
| style="color: rgb(51, 51, 255);">"java.lang.String"</span>);<br>setTypeMethodProxy.invoke(prompterProxy,frogProxy);<br></pre> |
| <p>Working with remote proxies from the Eclipse workbench's JVM that |
| point to instances of real live objects in the Visual Editor's target |
| JVM provides a way of ensuring that the two are totally insultated and |
| no class within the user's build path of a Java project needs to be |
| loaded by the class loader or instantantiated within Eclipse. |
| This provides a true editing sandbox which allows multiple instances of |
| classes to exist across different editors working with different build |
| paths and is the design principle that allows the Visual Editor to be |
| extended to support new target environment and topologies other than |
| just pure Java. However at some point the Visual Editor does need |
| to transport objects back from the target JVM to Eclipse. An |
| example of this is that having got an <span |
| style="font-family: monospace;">IBeanProxy</span> for a rectangle |
| result to the <span style="font-family: monospace;">getBounds()</span> |
| method this must be converted in its four constituient int values so |
| that a draw2D rectangle can be created for the GEF figure. |
| Likewise the Properties view shows the user the values of the target VM |
| objects. The point at which an object on the target VM can be |
| retrieved within the Eclipse workbench is when it is a primitive object |
| or a java.lang peer of a primitive or a String instance. This is |
| done by having four subinterfaces of <span |
| style="font-family: monospace;">IBeanProxy</span> in the package <span |
| style="font-family: monospace;">org.eclipse.jem.internal.proxy.core</span>.</p> |
| <table cellpadding="2" cellspacing="2" border="1" |
| style="text-align: left; width: 50%;"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;">java.lang Object lookup</td> |
| <td style="vertical-align: top;">primitive lookup</td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IStringBeanProxy</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">java.lang.String stringValue()</span> </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">IBooleanBeanProxy</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">java.lang.Boolean getBooleanValue()</span> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">boolean booleanValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">ICharacterBeanProxy</span> </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">java.lang.Character characterValue()</span> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">char charValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">INumberBeanProxy</span> </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">int intValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">long longValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">byte byteValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">short shortValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">float floatValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">double doubleValue()</span> </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"> <br> |
| </td> |
| <td style="vertical-align: top;"><span |
| style="font-family: monospace;">number numberValue()</span> </td> |
| </tr> |
| </tbody> |
| </table> |
| <br> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| It is possible to register custom sub instances of <span |
| style="font-family: monospace;">IBeanProxy</span> for plugin specific |
| objects and this occurs with <span style="font-style: italic;">org.eclipse.ve.jfc</span> |
| plugin that has introduces the types <span |
| style="font-family: monospace;">IPointBeanProxy</span>, <span |
| style="font-family: monospace;">IRectangleBeanProxy</span> and <span |
| style="font-family: monospace;">IDimensionBeanProxy</span>. This |
| can occur safely if you know that the Eclipse workbench's JVM contains |
| the classes in its -classpath and that these are a compatible shape |
| with the target VM's instances. This and other advanced topics |
| such handling arrays, installing helper class on the target VM's |
| -classpath for a classpath container, exceptions and debugging the |
| target VM are covered in a later tutorial specific to the target VM |
| architecture.</p> |
| <h3><a name="Retrieving_the_target_VM_property_value"></a>Retrieving |
| the target VM property value</h3> |
| <p>Having covered some of the background to the target VM API the |
| method <span style="font-family: monospace;">doSetValue(Object value)</span> |
| can now be overriden on CustomLabelEditor. This is so that the |
| Properties view can render correctly the value of the <span |
| style="font-style: italic;">text</span> property<span |
| style="font-style: italic;">. </span></p> |
| <pre><img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <span style="color: rgb(153, 0, 0);">protected</span> String stringValue = <span |
| style="color: rgb(51, 51, 255);">""</span>;<br> <span |
| style="color: rgb(0, 153, 0);"> // ...</span><br> <span |
| style="color: rgb(153, 0, 0);">protected void</span> doSetValue(Object value) {<br> <span |
| style="color: rgb(153, 0, 0);">if</span> (value != <span |
| style="color: rgb(153, 0, 0);">null</span>){<br> IStringBeanProxy stringBeanProxy =<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> (IStringBeanProxy) BeanProxyUtilities.getBeanProxy(<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif">(IJavaInstance) value);<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> stringValue = stringBeanProxy.stringValue();<br> }<br> <span |
| style="color: rgb(153, 0, 0);">super</span>.doSetValue(value);<br> }<br> <span |
| style="color: rgb(0, 153, 0);"> // ...</span> |
| <img style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> <span |
| style="color: rgb(153, 0, 0);">protected void</span> updateContents(Object value) {<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> <span |
| style="color: rgb(153, 0, 0);">super</span>.updateContents(stringValue);<br> }<br></pre> |
| <p>A String instance varialble <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> is |
| created to store the value of the <span style="font-style: italic;">text</span> |
| property result that the CustomLabelEditor is working with. </p> |
| <p>The doSetValue(Object) method will be called when the editor is |
| first created by the Properties view and after each time the dialog |
| editor is closed. The argument to this is an <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> |
| IJavaInstance for the String inside the Visual Editor's EMF model, so |
| the target VM can be used to locate the IBeanProxy which, because the <span |
| style="font-style: italic;">type</span> property is typed to <span |
| style="font-family: monospace;">java.lang.String</span>, will be an |
| instance of <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_3.gif"><span style="font-family: monospace;">IStringBeanProxy</span>. |
| The <span style="font-family: monospace;">java.lang.String</span> |
| value of this inside the workbench's JVM is retrieved using <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> <span |
| style="font-family: monospace;">IStringBeanProxy.stringValue()</span> |
| and this is stored in the instance field <span |
| style="font-family: monospace;">stringValue</span>;</p> |
| <p>To ensure that the contents of the Label used by the cell editor |
| shows the string correctly the method <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> <span |
| style="font-family: monospace;">updateContents(Object value)</span> is |
| overriden to ignore the argument and call <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> <span |
| style="font-family: monospace;">super.updateContents()</span> with the |
| actual String.</p> |
| <h3><a name="Testing_the_text_dialog_cell_editor"></a>Testing the <span |
| style="font-style: italic;">text</span> dialog cell editor</h3> |
| <p>To create the curstom <span style="font-style: italic;">text</span> |
| editor several steps were involved:</p> |
| <ul> |
| <li>Use the extension point <span style="font-style: italic;">org.eclipse.ve.jem.beaninfo.registrations</span> |
| to declare the /override folder structure associated with the |
| PrompterContainer for the Java package org.eclipse.ve.examples.prompter</li> |
| <li>Create a <span style="font-style: italic;">MyCustomPrompter.override</span> |
| file in the /overrides directory that added a BasePropertyDecorator to |
| the EReference for the <span style="font-style: italic;">text</span> |
| structural feature.</li> |
| <li>Set the <span style="font-style: italic;">cellEditorClassname</span> |
| property of the BasePropertyDecorator to be the class |
| org.eclipse.ve.examples.CustomLabelEditor</li> |
| <li>Create the <span style="font-family: monospace;">CustomLabelEditor</span> |
| class extending the JFace abstract <span |
| style="font-family: monospace;">DialogEditorClass</span> (and |
| implementing the interface <span style="font-family: monospace;">INeedData</span> |
| to ensure it is given the Visual Editor's EditDomain)</li> |
| <li>Override the method <span style="font-family: monospace;">openDialogBox(Control |
| aControl)</span> on <span style="font-family: monospace;">CustomLabelEditor</span> |
| to open an inner subclass of <span style="font-family: monospace;">TextDialogEditor</span></li> |
| <li>The <span style="font-family: monospace;">TextDialogEditor</span> |
| contains a content pane which allows the <span |
| style="font-style: italic;">text</span> property to be edited - this |
| is a subclass of <span style="font-family: monospace;">Composite</span> |
| called <span style="font-family: monospace;">LabelDialogContent</span></li> |
| <li>To render the property correctly in CustomLabelEditor the method<span |
| style="font-family: monospace;">doSetValue(Object)</span> and <span |
| style="font-family: monospace;">updateContents(value)</span> is |
| overriden and the target VM string retrieved and displayed</li> |
| </ul> |
| <p>To test the <span style="font-style: italic;">text</span> property |
| start the runtime Eclipse workbench, drop an instance of <span |
| style="font-family: monospace;">MyCustomPrompter</span> onto a <span |
| style="font-family: monospace;">Shell</span> or <span |
| style="font-family: monospace;">Composite</span> and select and edit |
| the <span style="font-style: italic;">text</span> property. If |
| it fails and has the default String label and cell editor look in the <span |
| style="font-style: italic;">.log</span> file in the .metadata |
| directory of the target workbench for any syserr output. These |
| will typically be because some XMI syntax in the .override file was |
| entered incorrectly. If there is no output then it is possible |
| that the definition of the beaninfo.registrations extension point is |
| incorrect, and for this debug the <span style="font-family: monospace;">BeanInfoClassAdapter</span> |
| class to see that the .override file being searched for. <br> |
| <br> |
| The next step of the tutorial will create a special GEF edit part for |
| MyCustomPrompter that instead of just drawing an image of the live |
| custom control, renders some text and icon on top of the graphic.<br> |
| </p> |
| <h2><a name="Overriding_a_GEF_edit_part">Supplying a custom GEF edit |
| part</a></h2> |
| <p>Classes implement the interface <span |
| style="font-family: monospace;">org.eclipse.gef.GraphicalEditPart</span> |
| act as mediators between a model object and the draw2D API that renders |
| the object onto the GEF canvas. The edit part to use for a given <span |
| style="font-family: monospace;">IJavaInstance</span> (the model |
| object) by the Visual Editor is obtained from the <span |
| style="font-family: monospace;">ClassDescriptorDecorator</span> that |
| annotates its JavaClass. If no explicitly defined <span |
| style="font-family: monospace;">ClassDescriptorDecorator</span> can be |
| found, or the one found doesn't have a graphical edit part class |
| defined, then the inheritance chain of the EMF <span |
| style="font-family: monospace;">JavaClass</span> (that shadows the |
| Java type hierarchy) is searched until a graphical edit part class name |
| is found. following this rule, in the absence of any override for |
| <span style="font-family: monospace;">MyCustomPrompter</span> the |
| Visual Editor will pick up the inherited edit part class <span |
| style="font-family: monospace;">CompositeGraphicalEditPart</span> |
| because <span style="font-family: monospace;">MyCustomPrompter</span> |
| extends <span style="font-family: monospace;">Composite</span> and |
| this is what gives <span style="font-family: monospace;">MyCustomPrompter</span> |
| its initial default edit experience.</p> |
| <p>This section of the tutorial will build a custom graphical edit part |
| named <span style="font-family: monospace;">org.eclipse.ve.example.customwidget.CustomWidgetGraphicalEditPart</span>. |
| This will be declared in the <span style="font-style: italic;">MyCustomPrompter.override</span> |
| file as being the graphical edit part class to use, and the class will |
| be specialized to create the draw2D desired effects.</p> |
| <p>MyCustomPrompter.override should be updated as below. (The <span |
| style="color: rgb(153, 153, 153);">grey</span> text fragments of XMI |
| represents elements in the original file written for the <span |
| style="font-style: italic;">text</span> property custom editor and the |
| black the new lines to add)</p> |
| <pre><span style="color: rgb(153, 153, 153);"><br><?xml version="1.0" encoding="UTF-8"?><br> <xmi:XMI xmi:version="2.0" <br> xmlns:xmi="http://www.omg.org/XMI" <br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><br></span><span |
| style="color: rgb(153, 153, 153);"><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"></span> <span |
| style="color: rgb(153, 153, 153);">xmlns:org.eclipse.ve.internal.cde.decorators="http:///org/eclipse/ve/internal/cde/decorators.ecore"</span><br><span |
| style="color: rgb(153, 153, 153);"> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" <br> xmlns:event="event.xmi"><br><br></span><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <event:Add featureName="eAnnotations"><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> <addedEObjects xsi:type="org.eclipse.ve.internal.cde.decorators:ClassDescriptorDecorator"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> graphViewClassname="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomWidgetGraphicalEditPart"><br> </addedEObjects><br> </event:Add><br><br><span |
| style="color: rgb(153, 153, 153);"><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> <event:Add featureName="eStructuralFeatures"></span> <span |
| style="color: rgb(153, 153, 153);"> <br> <addedEObjects xsi:type="ecore:EReference" name="text" unsettable="true"></span> <span |
| style="color: rgb(153, 153, 153);"> <br> <eAnnotations xsi:type="org.eclipse.ve.internal.cde.decorators:BasePropertyDecorator"<br></span> <span |
| style="color: rgb(153, 153, 153);">cellEditorClassname="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomLabelEditor"/></span> <span |
| style="color: rgb(153, 153, 153);"> <br> </addedEObjects></span> <span |
| style="color: rgb(153, 153, 153);"> <br> </event:Add><br></span> <span |
| style="color: rgb(153, 153, 153);"></xmi:XMI> </xmi:XMI></span> |
| </pre> |
| <p>To specify that <span style="font-family: monospace;">BasePropertyDecorator</span> |
| as annotating the <span style="font-style: italic;">type</span> |
| structural feature (as was done for the CustomLabelEditor earlier) |
| an <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_5.gif"> event:Add was created for the EMF feature <span |
| style="font-style: italic;">eStructuralFeature</span><span |
| style="font-style: italic;">s</span>. This represents the |
| features or properties on the JavaClass, and the decorator was then |
| defined as annotating the feature. To annotate the actual |
| JavaClass (as opposed to one of its specific features) an <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <span |
| style="font-family: monospace;">event:Add</span> is created directly |
| on the <span style="font-style: italic;">eAnnotations</span> feature |
| as a top level element in the XMI. Because the file name is <span |
| style="font-style: italic;">MyCustomPrompter.override</span> the |
| Visual Editor will process this as an addition to the annotations of |
| the EMF definition of the <span style="font-family: monospace;">MyCustomPrompter</span> |
| class.</p> |
| <p>The class being added as an annotation to MyCustomPrompter is an |
| instance of <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_3.gif"> |
| org.eclipse.ve.internal.cde.decorators.ClassDescriptorDecorator. |
| As described <a href="#xsi:type_structure">earlier</a> the XMI |
| describes this as <span style="font-style: italic;">EMFPackageName:EMFClassName</span> |
| which corresponds to the EMF registered package <span |
| style="font-family: monospace;">org.eclipse.ve.internal.cde.decorators.DecoratorsPackage</span>. |
| A common coding error with XMI is to declare the element for an |
| annotation assuming that it is the <span style="font-style: italic;">packageName:classNam</span>e |
| without having the namespace definition <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> at |
| the top of the XMI file.<br> |
| <br> |
| <span style="font-family: monospace;">ClassDescriptorDecorator</span> |
| stores the name of the graphical edit part to use by GEF with the |
| syntax of <span style="font-style: italic;">pluginName/qualifiedClassName</span>. |
| For this tutorial the edit part created is called <span |
| style="font-family: monospace;">org.eclipse.ve.example.CustomWidgetGraphicalEditPart</span> |
| and in the plugin name <span style="font-style: italic;">org.eclipse.ve.example.,customwidget</span>.</p> |
| <p>The method responsible for creating the draw2D figure shown on the |
| GEF canvas is <span style="font-family: monospace;">createFigure()</span> |
| and this is overriden to place a draw2L label on top of the inherited |
| behavior (an image of the live visual). The method is shown below |
| and the full class list is available at <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/CustomWidgetGraphicalEditPart.java"> |
| CustomWidgetGraphicalEditPart.java</a>.</p> |
| <pre><span style="color: rgb(153, 0, 0);">public class</span> CustomWidgetGraphicalEditPart <span |
| style="color: rgb(153, 0, 0);">extends</span> <span |
| style="color: rgb(153, 0, 0);"><img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_1.gif"></span> ControlGraphicalEditPart {<br><br> <span |
| style="color: rgb(153, 0, 0);">protected</span> IFigure createFigure() {<br><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> IFigure figure = super.createFigure();<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> Label customFigure = <span |
| style="color: rgb(153, 0, 0);">new</span> Label(<span |
| style="color: rgb(51, 51, 255);">"VE Rules"</span>,CustomwidgetPlugin.getCustomImage());<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> customFigure.setForegroundColor(ColorConstants.red);<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> customFigure.setTextPlacement(PositionConstants.SOUTH);<br> <span |
| style="color: rgb(0, 153, 0);">// ImageFigure has no layout, so we will have to explicitly set the size().</span><br |
| style="color: rgb(0, 153, 0);"><br> <span |
| style="color: rgb(0, 153, 0);"> // To get a prefered size (before we look up the hierarchy), Label will need a Font</span> |
| <img style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> customFigure.setFont(((GraphicalEditPart)getParent()).getFigure().getFont());<br> customFigure.setSize(customFigure.getPreferredSize());<br><br> figure.add(customFigure);<br><br> <span |
| style="color: rgb(153, 0, 0);">return</span> figure;<br> }<br> }<br></pre> |
| <p>Although <span style="font-family: monospace;">MyCustomPrompter</span> |
| extends <span style="font-family: monospace;">Composite</span> and the |
| Visual Editor uses the class <span style="font-family: monospace;">CompositeGraphicalEditPart</span> |
| for visually edited composites, the <span |
| style="font-family: monospace;">CustomWidgetGraphicalEditPart</span> |
| is defined as extending <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> <span style="font-family: monospace;">ControlGraphicalEditPart</span>. |
| This is because <span style="font-family: monospace;">CompositeGraphicalEditPart</span> |
| contains all of the GEF behavior to allow dropping of child controls |
| and dealing with layout management, and while <span |
| style="font-family: monospace;">MyCustomPrompter</span> physically |
| extends <span style="font-family: monospace;">Composite</span> to |
| enable it to have child controls our usage of it is as a closed black |
| box that can't accept more child controls and logically extends <span |
| style="font-family: monospace;">Control</span>'s behavior. </p> |
| <p>The inherited implementation from <span |
| style="font-family: monospace;">ControlGraphicalEditPart</span> |
| returns the class<img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_2.gif"> <span style="font-family: monospace;">ImageFigure</span>. |
| This has the logic required to render a picture of the live |
| control. To this figure we add a draw2D Label that has an icon <img |
| style="width: 16px; height: 16px;" alt="" src="images/custom.gif"> |
| and the text <span style="color: rgb(255, 0, 0);">VE Rules</span> |
| drawn in red. The Label is <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| created with the text and image and its <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif"> |
| foreground color and details about how to <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> |
| place the text (below the icon) are specified. The size of the |
| figure is set to its preferred size, and because this involves |
| calculating using the fontMetrics to determine the width of the label's |
| text the font must be <img style="width: 24px; height: 13px;" |
| alt="" src="../images/tag_6.gif"> explicitly set to the value it will |
| acquire when it is added to the parent. Having completed the |
| creation of the Label it is added as a child of the <span |
| style="font-family: monospace;">ImageFigure</span>.</p> |
| <p>To test the CustomWidgetGraphicalEditPart launch the Eclipse |
| workbench target and verify that the image of a MyCustomPrompter class |
| now renders itself with an image of the live visual covered with the <span |
| style="color: rgb(255, 0, 0);">VE R</span><span |
| style="color: rgb(255, 0, 0);">ules</span> text and icon <img |
| style="width: 16px; height: 16px;" alt="" src="images/custom.gif">. </p> |
| <img style="border: 1px solid ; width: 341px; height: 171px;" alt="" |
| src="images/GraphicalEditPart.png"><br> |
| <br> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| The original default behavior for MyCustomPrompter in the absence of |
| its specific graphical edit part was to render the live visual with a |
| border drawn around it. however the figure above shows that there is no |
| border drawn. The border is not part of the natural behavior of |
| an SWT composite (although one can be specified with the style bit of |
| SWT.BORDER) and it drawn by the Visual Editor around a |
| CompositeGraphicalEditPart so that an empty Composite with no children |
| isn't otherwise invisible (as if it were the same color as its |
| background it'd blend in and be hard to see on the design |
| canvas). The behavior to render a design time border around a GEF |
| figure is done by ConttrolGraphicalEditPart (which |
| CustomWidgetGraphicalEditPart extends) by having initializationData |
| supplied as part of its definition. InitializationData is used by |
| the Visual Editor as a way of supplying parameters to a class so that |
| different usages can supply custom implementations. It occurs by |
| having the class defined in the .override file implement the interface <span |
| style="font-family: monospace;">org.eclipse.core.runtime.IExecutableExtension</span>. |
| This has a single method <span style="font-family: monospace;">setInitializationData(IConfigurationElement |
| config, String propertyName, Object data). </span><br> |
| <br> |
| When the Visual Editor parses a class name defined in a .override file |
| if there is a colon symbol <span style="font-weight: bold;">:</span> |
| after the class name then anything following this is parsed and passed |
| into the setInitializationDataMethod(....). An example of this is |
| the class ControlGraphicalEditPart implements the IExecutableExtension |
| interface and uses the initData to determine whether a border should be |
| drawn around the figure or not as follows:</p> |
| <pre><span style="color: rgb(153, 0, 0);">public void</span> setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {<br> <span |
| style="color: rgb(153, 0, 0);">if</span> (data <span |
| style="color: rgb(153, 0, 0);">instanceof</span> String)<br> border = Boolean.<span |
| style="font-style: italic;">valueOf</span>((String) data).booleanValue();<br>}<br></pre> |
| <p>and in the <span style="font-style: italic;">Composite.override</span> |
| file in <span style="font-style: italic;">org.eclipse.ve.swt/overrides/org/eclipse/swt/widgets</span></p> |
| <pre> <addedEObjects xsi:type="org.eclipse.ve.internal.cde.decorators:ClassDescriptorDecorator"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> graphViewClassname="org.eclipse.ve.swt/org.eclipse.ve.internal.swt.CompositeGraphicalEditPart:<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif">true" <br> </addedEObjects><br></pre> |
| <p>The <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_1.gif"> graphViewClassname is defined as |
| pluginName/qualifiedClassNane:initData and the value of <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <span |
| style="font-style: italic;">true</span> specifies that an SWT |
| composite is drawn by the Visual Editor with the border. Because <span |
| style="font-style: italic;">MyCustomPrompter.override</span> does not |
| specify the initData of <span style="font-style: italic;">true</span> |
| it is drawn with the live widget as is.<br> |
| <br> |
| The next step in the tutorial is to look at how to affect the code |
| generation subsystem of the Visual Editor.</p> |
| <h2><a name="Overriding_an_Expression_Decoder">Custom code generation |
| for the <span style="font-style: italic;">text</span> property</a></h2> |
| <p>The code generation subsystem is responsible for parsing a .java |
| file when it is opened by the Visual Editor and building up the graph |
| of IJavaInstance objects that represent the model of the visual |
| class. It does this by working with the JDT's Abstract Syntax |
| Tree (AST) that represents a set of fine grained nodes for every |
| compilable fragment of Java source. For every AST expression that |
| is modeled by the Visual Editor (not all source represents code |
| constructs that the Visual Editor is interested in showing to the user |
| or collecting in its model) there is an expression decoder. |
| The decoder has two helper classes; a feature mapper and a decoder |
| helper.</p> |
| <p>The feature mapper is responsible for tying together a source code |
| expression in the actual Java source to a modeled feature in the Visual |
| Editor's EMF model and vice-versa.</p> |
| <p>The decoder helper has the knowledge of how to parse AST expressions |
| and build up the Visual Editor model portion related to a specific |
| expression type, as well as how to generate specific expression source |
| code from the model. </p> |
| <p>The task of the decoder class is largely a delegate to determine |
| which feature mapper and decoder helper to use for a given source code |
| expression</p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| Decoders do not generate AST nodes directly because in many cases the Java |
| source is created instead by using JavaJet templates. These |
| templates can be modified by users and recognized by the Visual |
| Editor and will be covered in more detail in a specific tutorial |
| covering the code generation subsystem.</p> |
| <p>This tutorial will create a decoder helper that adds a comment <span |
| style="font-family: monospace; color: rgb(0, 153, 0);">// Prompter |
| Text Property</span> to the line of Java code generated for the |
| setText(String aString) method of the <span style="font-style: italic;">text</span> |
| property.</p> |
| <pre><span style="font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">private void</span> createMyCustomPrompter() {</span><br |
| style="font-family: monospace;"> <span style="font-family: monospace;">myCustomPrompter = <span |
| style="color: rgb(153, 0, 0);">new</span> MyCustomPrompter(sShell, SWT.<span |
| style="font-style: italic; color: rgb(51, 51, 255);">NONE</span>);</span> <br> <span |
| style="font-family: monospace;">myCustomPrompter.setText(<span |
| style="color: rgb(51, 51, 255);">"Text value"</span>); <span |
| style="color: rgb(0, 153, 0);">// Prompter Text Property</span></span><br><span |
| style="font-family: monospace;">}<br></span><br>The class created to do this is <span |
| style="font-family: monospace;">org.eclipse.ve.examples.customwidget.CustomPrompterDecoderHelper</span>. This is declared in the <span |
| style="font-style: italic;">MyCustomPrompter.override</span> file as annotating the <span |
| style="font-family: monospace;">JavaClass</span> definition for <span |
| style="font-family: monospace;">MyCustomPrompter</span> so the Visual Editor uses it.</pre> |
| <pre><span style="color: rgb(192, 192, 192);"><span |
| style="color: rgb(153, 153, 153);"> <?xml version="1.0" encoding="UTF-8"?></span></span><br> <span |
| style="color: rgb(153, 153, 153);"><xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span><br> <span |
| style="color: rgb(153, 153, 153);">xmlns:org.eclipse.ve.internal.cde.decorators="http:///org/eclipse/ve/internal/cde/decorators.ecore"<br></span><span |
| style="color: rgb(153, 153, 153);"><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"></span> xmlns:codeGenHelpers="platform:/plugin/org.eclipse.ve.java.core/overrides/codegenHelpers.ecore"<br> <span |
| style="color: rgb(153, 153, 153);">xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"<br> xmlns:event="event.xmi"></span><br><br><span |
| style="color: rgb(153, 153, 153);"><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"></span> <event:AddMany featureName="eAnnotations"><br> <span |
| style="color: rgb(153, 153, 153);"><addedEObjects xsi:type="org.eclipse.ve.internal.cde.decorators:ClassDescriptorDecorator"</span><br> <span |
| style="color: rgb(153, 153, 153);">graphViewClassname="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomWidgetGraphicalEditPart"></span><br> <span |
| style="color: rgb(153, 153, 153);"></addedEObjects></span> |
| <img style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> <addedEObjects xsi:type="codeGenHelpers:CodeGenHelperClass"<img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_4.gif">source="codegen.CodeGenHelperClass"<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> expDecoder="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomPrompterDecoder"/><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"> </event:AddMany><br><br> <span |
| style="color: rgb(153, 153, 153);"><event:Add featureName="eStructuralFeatures"></span><br> <span |
| style="color: rgb(153, 153, 153);"><addedEObjects xsi:type="ecore:EReference" name="text" unsettable="true"></span><br> <span |
| style="color: rgb(153, 153, 153);"><eAnnotations xsi:type="org.eclipse.ve.internal.cde.decorators:BasePropertyDecorator"<br></span> <span |
| style="color: rgb(153, 153, 153);">cellEditorClassname="org.eclipse.ve.example.customwidget/org.eclipse.ve.example.customwidget.CustomLabelEditor"/></span><br> <span |
| style="color: rgb(153, 153, 153);"></addedEObjects></span><br> <span |
| style="color: rgb(153, 153, 153);"></event:Add><br></span><span |
| style="color: rgb(153, 153, 153);"> </xmi:XMI></span> |
| </pre> |
| <p>Earlier when just the single ClassDecriptorDecorator was added as an |
| annotation to MyCustomPrompter the XMI tag used in the .override file |
| was <span style="font-style: italic;"><event:Add></span>. |
| This is the syntax to add a single object, however because a second |
| annotation now needs to be added the file is changed to use the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <span |
| style="font-style: italic;"><span style="font-style: italic;"><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_6.gif"></span></span><span |
| style="font-style: italic;"><event:AddMany></span> element for |
| the two decorators. The decorator added is a CodeGenHelperClass |
| and this is done through adding <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_3.gif"> |
| the namespace for codeGenHelper in the XMI package declarations and an |
| xsi:type of <span style="font-style: italic;">namespace:CodeGenHelperClass</span> |
| with syntax <img style="width: 24px; height: 13px;" alt="" |
| src="../images/tag_4.gif"> <span style="font-style: italic;">source="codegen.CodeGenHelperClass</span>". |
| The expression decoder is stored in the expDecoder feature of the |
| CodeGenHelperClass and defined with the syntax of <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_5.gif"> |
| pluginName/qualifiedClassName.</p> |
| <p><font face="Arial">The <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/CustomPrompterDecoder.java">CustomPrompterDecoder.java</a>. |
| is responsible for determining which decoder helper is associated with |
| which property. The superclass |
| ~org.eclipse.ve.internal.swt.codegen.SWTControlDecoder is used as this |
| contains behavior such as dealing with the SWT code patterns required |
| for constructor style bits, and the method initialDecoderHelper() is |
| specialized to associate a decoder helper with the <span |
| style="font-style: italic;">text</span> property</font></p> |
| <pre> <span style="color: rgb(153, 0, 0);">public class</span> CustomPrompterDecoder <span |
| style="color: rgb(153, 0, 0);">extends</span> SWTControlDecoder {<br><br> <span |
| style="color: rgb(153, 0, 0);">protected void</span> initialDecoderHelper() {<br> <span |
| style="color: rgb(0, 153, 0);"> // if it is the text property that this decoder is decoding, use a custom helper</span><br> <span |
| style="color: rgb(153, 0, 0);">if</span> (fFeatureMapper.getFeature(<span |
| style="color: rgb(153, 0, 0);">null</span>).getName().equals(<font |
| color="#0000ff">"text"</font>)) {<br> fhelper = <span |
| style="color: rgb(153, 0, 0);">new</span> CustomPrompterDecoderHelper(fbeanPart, fExpr, fFeatureMapper, this);<br> } <span |
| style="color: rgb(153, 0, 0);">else</span> {<br> <span |
| style="color: rgb(153, 0, 0);">super</span>.initialDecoderHelper();<br> }<br> }<br> }<br></pre> |
| <p>The CustomPrompterDecoderHelper will extend the Visual Editor class |
| org.eclipse.ve.internal.java.codegen.java.SimpleAttributeDecoderHelper. |
| The method responsible for generating the code is generate(Object[]) |
| and this is specialized as below. The full source file can be |
| viewed in CVS <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/CustomPrompterDecoderHelper.java"> |
| CustomPrompterDecoderHelper.java</a>.</p> |
| <pre> <span style="color: rgb(153, 0, 0);">public class</span> CustomPrompterDecoderHelper <span |
| style="color: rgb(153, 0, 0);">extends</span> SimpleAttributeDecoderHelper {<br><br> <span |
| style="color: rgb(153, 0, 0);">public</span> String generate(Object[] noArgs) <span |
| style="color: rgb(153, 0, 0);">throws</span> CodeGenException {<br> String result = <span |
| style="color: rgb(153, 0, 0);">super</span>.generate(noArgs);<br> <span |
| style="color: rgb(0, 153, 0);"> // Add a comment at the end of the expression</span><br> <span |
| style="color: rgb(153, 0, 0);">int</span> idx = result.lastIndexOf(<span |
| style="color: rgb(51, 51, 255);">';'</span>) + 1;<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> <span |
| style="color: rgb(153, 0, 0);">return</span> result.substring(0, idx) + <span |
| style="color: rgb(51, 51, 255);">" // Prompter Text Property "</span> + result.substring(idx, result.length());<br> }<br><br> }<br></pre> |
| <p>The <span style="font-family: monospace;">generate(Object[])</span> |
| method returns the String that is used for the code fragment generated |
| and the <span style="font-family: monospace;">CustomPrompterDecoderHelper</span> |
| adds a hard coded literal to the end of the inherited behavior (that |
| creates the full expression for the setType(...) method invocation).</p> |
| <p><img src="../images/note.gif" alt="Note:" |
| style="width: 62px; height: 13px;"> |
| Instead of having CustomPrompterDecoderHelper and CustomPrompterDecoder |
| as two separate classes it would have been possible to have the decoder |
| helper as an anonymous inner class of the decoder itself. By |
| separating the decoder and the decoder helper into separate classes |
| however enables for re-use, as other properties that wished to share |
| the same rules as the <span style="font-style: italic;">text</span> |
| property can have their own decoders that use the same decoder helper.</p> |
| <p>You can test the decoder and decoder helper for the <span |
| style="font-style: italic;">text</span> property by launching the |
| Eclipse target workbench. Use the Properties view to set the <span |
| style="font-style: italic;">text</span> property and ensure that the |
| line is generated with the new comment. If it fails follow the |
| same steps as for the custom property editor which |
| involves looking in the .log file for any XMI syntax errors, using the |
| BeanInfoClassAdapter to ensure the .override is being detected, and |
| then finally debugging the decoder helper itself. </p> |
| <p>The final step of the tutorial is to promote the <span |
| style="font-style: italic;">buttonSelection</span> event to the list |
| of preferred events used by the Visual Editor when a list of events to |
| be added is displayed to the user.</p> |
| <h2><a name="Preferred_Event">Specifying a preferred event</a></h2> |
| <p><span style="font-family: monospace;">MyCustomPrompter class</span> |
| has the methods <span style="font-family: monospace;">addButtonSelectionEvent(ButtonSelectionEvent |
| anEvent)</span> and <span style="font-family: monospace;">removeButtonSelectionEvent(ButtonSelectionEvent |
| anEvent).</span> This allows anyone developing a class that uses |
| the custom prompter to be able to get called back anytime the user |
| presses its button. This is the button on the right hand side of |
| the prompter that is labelled ..., <span style="font-style: italic;">Open |
| or More </span>based on the <span style="font-style: italic;">type </span>property |
| setting. If a button listener is added to the custom prompter the |
| code generated is as below, and can be used for example to launch an |
| additional dialog or perform user logic.<br> |
| </p> |
| <p><span style="font-family: monospace;"><span |
| style="color: rgb(153, 0, 0);">private void </span>createCustomPrompter() |
| {</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> customPrompter |
| = <span style="color: rgb(153, 0, 0);">new </span>MyCustomPrompter(sShell, |
| SWT.NONE); </span><span |
| style="font-family: monospace;"></span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| customPrompter.addButtonSelectionListener(<span |
| style="color: rgb(153, 0, 0);">new </span>ButtonSelectionListener() { |
| </span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| <span style="color: rgb(153, 0, 0);">public void</span> |
| buttonSelected(org.eclipse.swt.events.SelectionEvent e) |
| { </span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| System.out.println(<span |
| style="color: rgb(51, 51, 255);">"buttonSelected()"</span>); <span |
| style="color: rgb(0, 153, 0);">// TODO Auto-generated Event stub |
| buttonSelected()</span></span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| }</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> });</span><span |
| style="font-family: monospace;"></span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;">}</span><br> |
| </p> |
| <p>The purpose of this section is to show how to make it such that the <span |
| style="font-style: italic;">buttonSelected </span>event is the |
| preferred event offered to the user because it is the one that will be |
| most commonly used.<br> |
| </p> |
| <p>In the absence of any specific customization |
| rules the Visual Editor will by default use JavaBeans reflection and |
| associate these together with an event named <span |
| style="font-style: italic;">buttonSelection</span>. This will be |
| available for the user to add events to from the <span |
| style="font-style: italic;">Add Event</span> wizard that is launched |
| from the <span style="font-weight: bold;">Events > Add Event ..</span>. |
| pop-up menu option.</p> |
| <p>The desired effect though is to override the behavior of the Visual |
| Editor |
| such as the buttonSelected event appears on the first level of the <span |
| style="font-weight: bold;">Events</span> cascaded menu, as shown in |
| the figure below. The result of this would be that the usability |
| of the MyCustomPrompter class has been improved because the user is |
| more aware of its preferred API usage.</p> |
| <p><img style="border: 1px solid ; width: 501px; height: 411px;" alt="" |
| src="images/EventsMenuAfter.png"></p> |
| <p>Preferred events are defined according to the JavaBeans |
| specification with a custom BeanInfo class. Earlier the tutorial |
| created a specialized <a |
| href="http://dev.eclipse.org/viewcvs/indextools.cgi/%7Echeckout%7E/org.eclipse.ve.examples/org.eclipse.ve.example.customwidget/src/org/eclipse/ve/example/customwidget/prompter/MyCustomPrompterBeanInfo.java"> |
| MyCustomPrompterBeanInfo.java</a> to define the <span |
| style="font-style: italic;">enumerationValues</span> for the <span |
| style="font-style: italic;">type</span> property. This was done |
| by specializing the <span style="font-family: monospace;">getPropertyDescriptors()</span> |
| method. As well as defining the list of available properties and |
| how they should be edited, a BeanInfo class defines the list of |
| available events in the method <span style="font-family: monospace;">getEventSetDescriptors()</span>. |
| This returns an array of <span style="font-family: monospace;">java.beans.EventSetDescriptor</span> |
| objects and for <span style="font-family: monospace;">MyCustomPrompterBeanInfo</span> |
| is written as below</p> |
| <pre> <span style="color: rgb(153, 0, 0);">public</span> EventSetDescriptor[] getEventSetDescriptors() {<br><br> <span |
| style="color: rgb(153, 0, 0);">try</span> {<br> MethodDescriptor addButtonSelectionMD = <span |
| style="color: rgb(153, 0, 0);">new</span> MethodDescriptor(<br> ButtonSelectionListener.class.getMethod(<span |
| style="color: rgb(51, 51, 255);">"buttonSelected"</span>,<br> <span |
| style="color: rgb(153, 0, 0);">new</span> Class[]{SelectionEvent.<span |
| style="color: rgb(153, 0, 0);">class</span>})<br> );<br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> addButtonSelectionMD.setPreferred(<span |
| style="color: rgb(153, 0, 0);">true</span>);<br> <br> EventSetDescriptor addButtonSelectionED = new EventSetDescriptor(<br> <span |
| style="color: rgb(51, 51, 255);">"buttonSelection"</span>,<br> ButtonSelectionListener.<span |
| style="color: rgb(153, 0, 0);">class</span>,<br> <span |
| style="color: rgb(153, 0, 0);">new</span> MethodDescriptor[] {addButtonSelectionMD},<br> MyCustomPrompter.<span |
| style="color: rgb(153, 0, 0);">class</span>.getMethod(<span |
| style="color: rgb(51, 51, 255);">"addButtonSelectionListener"</span>,<span |
| style="color: rgb(153, 0, 0);">new</span> Class[]{ButtonSelectionListener.class}),<br> MyCustomPrompter.<span |
| style="color: rgb(153, 0, 0);">class</span>.getMethod(<span |
| style="color: rgb(51, 51, 255);">"removeButtonSelectionListener"</span>,<span |
| style="color: rgb(153, 0, 0);">new</span> Class[]{ButtonSelectionListener.<span |
| style="color: rgb(153, 0, 0);">class</span>})<br> );<br><br><img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> addButtonSelectionED.setPreferred(<span |
| style="color: rgb(153, 0, 0);">true</span>);<br> <br> return <span |
| style="color: rgb(153, 0, 0);">new</span> EventSetDescriptor[] {addButtonSelectionED};<br><br> } <span |
| style="color: rgb(153, 0, 0);">catch</span> (Exception e){<br> e.printStackTrace();<br> } <br> <span |
| style="color: rgb(153, 0, 0);">return null</span>;<br> }<br></pre> |
| <p>To prompt a method to be preferred requies both the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_1.gif"> |
| MethodDescriptor being set to preferred and also the <img |
| style="width: 24px; height: 13px;" alt="" src="../images/tag_2.gif"> |
| EventSetDescriptor.</p> |
| <p>To test the preferred event launch the Eclipse workbench target |
| environment and verify that the <span style="font-weight: bold;">Events</span> |
| pop-up menu displays an item for <span style="font-style: italic;">buttonSelected</span>.</p> |
| <h1><a name="A_complete_example"></a>A complete example</h1> |
| <p>This tutorial has gone through the steps required to create the |
| plugin <span style="font-style: italic;">org.eclipse.ve.example.customwidget</span>. |
| The completed plugin is available <a href="customwidgetexample.zip"> |
| here</a> or can be obtained directly from CVS.<br> |
| <br> |
| To install the plugin from CVS into an Eclipse development environment |
| attach to the host <span style="font-style: italic;">dev.eclipse.org</span> |
| and repository path <span style="font-style: italic;">/cvsroot/tools</span> |
| using a user id of <span style="font-style: italic;">anonymous</span> |
| with no password required. The figure below illustrates the CVS |
| perspective in Eclipse with the CVS Repositories view showing the |
| repository correctly attached to. To create the new repository |
| open the pop-up menu on the CVS Repositories view and select <span |
| style="font-style: italic; font-weight: bold;">New > Repository |
| Location.<br> |
| <br> |
| </span> Attach to the repository name<span style="font-style: italic;">/cvsroot/tools</span> |
| on the host name<span style="font-style: italic;">dev.eclipse.org</span>. |
| Specify a user name of anonymous which allows the code to be checked |
| out.<span style="font-style: italic; font-weight: bold;"><br> |
| </span> <span style="font-style: italic; font-weight: bold;"><br> |
| <br> |
| </span> <span style="font-weight: bold;"><img |
| src="images/RepositoriesView.png" alt="CVSRepositoriesView" |
| style="border: 1px solid ; width: 399px; height: 144px;"><br> |
| <br> |
| </span> The CVS Repositories view showing the correct |
| repository for the tutorial's finished pugin<br> |
| <br> |
| Having attached to the repository expand the <span |
| style="font-style: italic;">Head</span> tree item and search for the |
| plugin <span style="font-style: italic;">org.eclipse.ve.examples. </span> |
| Expand this and select <span style="font-style: italic;">org.eclipse.ve.example.customwidget.</span> |
| This is the complete plugin and to install it onto your workbench use |
| the pop-up menu option <span style="font-weight: bold;">Check Out</span> |
| as shown below<br> |
| <br> |
| <img style="border: 1px solid ; width: 395px; height: 272px;" alt="" |
| src="images/CheckOutAsProject.png"> </p> |
| <h2><a name="Conclusion">Conclusion</a></h2> |
| <p>In this tutorial, we looked at a high level where to start and |
| extend the Visual Editor and use specialized property cell editors, |
| BeanInfo, GEF edit parts, palette, and CodeGen decoders. To do |
| this required understanding how to use Java build path containers as |
| the trigger point for Visual Editor custom behavior, and how to inject |
| specialized code through the user of BeanInfo classes (for cross IDE |
| extensions) and .override files (for Visual Editor only specific |
| logic). An XMI file for a new palette category was created, and |
| also the concept of the target VM was discussed. </p> |
| <p>The software supplied with this article is for illustrative purposes |
| only and should be used accordingly. The software is provided as is and |
| with all faults, and hereby disclaims all other warranties and |
| conditions, either expressed, implied or statutory, including, but not |
| limited to, any (if any) implied warranties, duties or conditions of |
| merchantability, of fitness for a particular purpose, of accuracy or |
| completeness of responses, of results, of workmanlike effort, of lack |
| of viruses, and of lack of negligence, all with regard to the software.</p> |
| <p>Further tutorials will cover some of the topics introduced in more |
| depth and we welcome all feedback.</p> |
| |
| <p><small>ref: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=88801">bug |
| 88801</a></small></p> |
| |
| <p><small>IBM is trademark of International Business Machines |
| Corporation in the United States, other countries, or both. 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. Microsoft and Windows are trademarks of Microsoft |
| Corporation in the United States, other countries, or both. Other |
| company, product, and service names may be trademarks or service marks |
| of others.</small></p> |
| </body> |
| </html> |