| <!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> |