| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="description" content="The website of Eclipse EMF Parsley, an open-source framework for development User Interfaces upon EMF models"> |
| <meta name="author" content="Francesco Guidieri, Paolo Bachini"> |
| <link rel="icon" href="/favicon.ico"> |
| |
| <title>EMF Parsley - Play with your UI and EMF!</title> |
| <link rel="SHORTCUT ICON" href="img/logo_nw.gif" /> |
| <!-- styles --> |
| <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements --> |
| <!--[if lt IE 9]> |
| <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> |
| <![endif]--> |
| |
| <!-- Bootstrap core CSS --> |
| <link href="css/bootstrap.min.css" rel="stylesheet"> |
| <link href="css/main.css" rel="stylesheet"> |
| <!-- Animate CSS --> |
| <link href="css/animate.css" rel="stylesheet"> |
| |
| <!--[if lt IE 9]> |
| <link href="css/iebugs.css" rel="stylesheet" type='text/css'> |
| <![endif]--> |
| |
| <!-- Custom styles for this template --> |
| <link href="carousel.css" rel="stylesheet"> |
| |
| <!-- Bootstrap Lightbox --> |
| <link href="bootstrap-lightbox/bootstrap-lightbox.min.css" rel="stylesheet"> |
| <!--<script src="js/twitter.js" type="text/javascript"></script>--> |
| <!-- Just for debugging purposes. Don't actually copy these 2 lines! --> |
| <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> |
| <script src="assets/js/ie-emulation-modes-warning.js"></script> |
| |
| <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> |
| <script src="assets/js/ie10-viewport-bug-workaround.js"></script> |
| |
| <!-- Run Prettify --> |
| <script src="prettify/run_prettify.js"></script> |
| |
| <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> |
| <!--[if lt IE 9]> |
| <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> |
| <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> |
| <![endif]--> |
| <script> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| |
| ga('create', 'UA-58549052-1', 'auto'); |
| ga('send', 'pageview'); |
| |
| </script> |
| </head> |
| <body> |
| <!-- ====== NAVBAR ====== --> |
| <body style="overflow-y: scroll; padding-top:185px;"> |
| <div class="navbar-fixed-top" style="background:url(img/bg-100x100.jpg)"> |
| <div class="container" style="width:1150px;"> |
| <div class="navbar-header"> |
| <a href="Index.htm"><img class="featurette-image img-responsive" alt="" src="img/logo.gif"/></a> |
| </div> |
| </div> |
| <nav class="navbar navbar-default" role="navigation" style="background-color:transparent; border:0 none; margin:-31px 0px 3px 0px;min-height: 36px;"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" style="margin-bottom:2px;"> |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| </div> |
| <!-- Collect the nav links, forms, and other content for toggling --> |
| <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> |
| <ul class="nav navbar-nav pull-right mioli"> |
| <li><a href="support.html">Contact Us</a></li> |
| <li><a href="http://www.eclipse.org">Eclipse.org</a></li> |
| <li style="border-right: 0 none;"><a target="_blank" href="https://twitter.com/EmfParsley" id="twitterli"><img style="width:25px;float:left;margin-top: 5px; margin-right:1px;" alt="" src="img/twitter.png"/>@EmfParsley</a></li> |
| </ul> |
| </div><!-- /.navbar-collapse --> |
| </div> |
| </nav> |
| <div style="background:url(img/bg1-100x100.jpg);"> |
| <nav class="navbar navbar-default miomenubar" role="navigation" style="border-radius:0px; background: url('img/menu.jpg') no-repeat; border: 0 none; -webkit-box-shadow: 0px 3px 8px 0px rgba(171,209,173,1);-moz-box-shadow: 0px 3px 8px 0px rgba(171,209,173,1);box-shadow: 0px 3px 8px 0px rgba(171,209,173,1);margin-bottom:0;"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-2"> |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| </div> |
| <!-- Collect the nav links, forms, and other content for toggling --> |
| <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-2"> |
| <ul class="nav navbar-nav pull-left miomenu"> |
| <li><a href="index.html">Home</a></li> |
| <li><a href="download.html">Download</a></li> |
| <li><a href="documentation.html">Documentation</a></li> |
| <li><a href="sources.html">Sources</a></li> |
| <li><a href="support.html">Support</a></li> |
| </ul> |
| </div><!-- /.navbar-collapse --> |
| </div> |
| </nav> |
| </div> |
| </div> |
| <!-- NAVBAR End --> |
| <!-- Marketing messaging and featurettes |
| ================================================== --> |
| <!-- Wrap the rest of the page in another container to center all the content. --> |
| <style> |
| .row { |
| -webkit-animation: fadeInRightBig 1.5s; |
| -moz-animation: fadeInRightBig 1.5s; |
| -ms-animation: fadeInRightBig 1.5s; |
| -o-animation: fadeInRightBig 1.5s; |
| animation: fadeInRightBig 1.5s; |
| } |
| |
| .dropdown-menu { |
| -webkit-animation: fadeInDownBig 1.5s; |
| -moz-animation: fadeInDownBig 1.5s; |
| -ms-animation: fadeInDownBig 1.5s; |
| -o-animation: fadeInDownBig 1.5s; |
| animation: fadeInDownBig 1.5s; |
| } |
| </style> |
| <div class="containerdoc marketing"> |
| <!-- SIDEBAR --> |
| <div style="position: fixed;" class="col-md-2"> |
| <ul class="dropdown-menu" style="margin: 0px; max-width: 250px; display: block;box-shadow: 0 0px 7px rgba(0,0,0,.175);"> |
| <li class="activemenu" ><a tabindex="-1" href="#par">Overview</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Parsley Components</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Customize</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">First Example</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">Components</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Form Component</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Tree Component</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Tree Form Component</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Table Component</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">Customizations</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Providers</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Contextual Menu</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Factories</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">Eclipse 4.x</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">First Example Setup</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Preparing for a pure e4</br> Application</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Create an e4 Application</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Using a TreeComposite</br> into an e4 Part</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Adding the dirty state</br> and Save command</a></li> |
| <li class="divider"></li> |
| </ul> |
| </div> |
| |
| <!-- START THE FEATURETTES --> |
| </br> |
| <div class="row featurette"> |
| <div class="col-md-8 col-md-offset-3"> |
| <h1 id="par" class="featurette-heading text-parsley">Overview</h1> |
| <p> |
| <strong>Emf Parsley</strong> is a lightweight framework that allows easy and quick UI development |
| upon EMF. <strong>EMF Parsley</strong> is built from EMF Edit framework features like Tree, Form and Table builders with |
| standard JFace databinding, providing a complete component-based toolset. Moreover a DSL allows to customize several behaviors in each component and can be configured to use all kinds of EMF persistence implementations (XMI, Teneo, CDO). |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Parsley Components</h2> |
| <p> |
| <strong>EMF Parsley</strong> aims to provide a complete set of block components to visualize your model with the introspective EMF capabilities and can be used to easily build forms, viewers or editors. |
| </p> |
| <p> |
| There are some components that can be used out-of-the-box and can be considered as a reference implementation |
| of the mechanisms that are the bases of <strong>Emf Parsley</strong> itslef. |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><strong>Tree</strong></li> |
| <li><strong>Form</strong></li> |
| <li><strong>Table</strong></li> |
| <li><strong>Search</strong> coming soon</li> |
| </ul> |
| <p> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Customize</h2> |
| <p> |
| The main feature of <strong>EMF Parsley</strong> is that you can customize all basic UI behaviours of the components with Injection mechanism (based on <a href="http://code.google.com/p/google-guice">Google Guice</a>). |
| You can get more info in the <a href="#addref" rel="Customizations">Customizations Section</a>, but you don't have to know all details about the internal implementation to inject your own customization because |
| <strong>Emf Parsley</strong> provides a DSL to easy customize your UI, as explained in the next section. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Customize with the DSL<a id="Customizations_DSL"></a></h3> |
| <p> |
| You can use the DSL by creating a new project with the wizard "Create a new project" -> "EMF Parsley DSL Based project" |
| </p> |
| <p> |
| </p> |
| <img src="images/01-new-project-dsl-wizard.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Clicking the "Finish" button the wizard will open directly the dsl editor. You can use the content assistant |
| to discover all features. |
| </p> |
| <p> |
| </p> |
| <img src="images/01-dsl-content-assistant.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| The DSL allows to customize the most relevant behaviors, currently the following are permitted: |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><strong>parts</strong> let you define your View Parts: a file plugin.xml_emfparsley_gen will be generated |
| to synchronize with your own plugin.xml</li> |
| <li><strong>bindings</strong> section let you define which implementation will be used wiht Injection</li> |
| <li><strong>menu</strong> section let you define the contextual menu for all viewers (<strong>Tree</strong> and <strong>tables</strong>)</li> |
| <li><strong>features provider</strong> is used to retrieve list of feature for a given EClass to build <strong>Tables</strong> |
| and <strong>Forms</strong></li> |
| <li><strong>viewer content provider</strong> mediates between the viewer's model and the viewer, to provide the |
| contents to be shown</li> |
| <li><strong>Label Provider</strong> is used to retrieve the image and text rapresentation of the EStructuredFeature of a given EClass</li> |
| <li><strong>Caption Provider</strong> provides captions for each feature. Different implementations can be defined for <strong>Dialogs</strong> and <strong>Forms</strong></li> |
| <li><strong>Control Factory</strong> provides a custom implementation of Controls for each feature. Different implementations can be defined forfor <strong>Dialogs</strong> and <strong>Forms</strong></li> |
| </ul> |
| <p> |
| </p> |
| </div> |
| </div> |
| </div> |
| <hr style="width:64.6%;margin-bottom:28px;margin-top:30px;" class="col-md-8 col-md-offset-3"> |
| <div class="row featurette"> |
| <div class="col-md-8 col-md-offset-3"> |
| <h1 id="par" class="featurette-heading text-parsley">First Example</h1> |
| <p> |
| The purpose of this first example is to make use of the classical EMF Library Model example and |
| create a view for editing such models using an EMF Parsley enabled plug-in. |
| </p> |
| <p> |
| So let's start by creating the model plug-in with |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Eclipse Modeling Framework", select "Extended Library Model Example"</li> |
| <li>press Next and Finish</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| You will end up with three plug-ins: |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li>org.eclipse.emf.examples.library (the model plug-in)</li> |
| <li>org.eclipse.emf.examples.library.edit (the edit plug-in)</li> |
| <li>org.eclipse.emf.examples.library.editor (the editor plug-in)</li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| Please consider that here we are starting from this well known EMF model taken out-of-the-box from Eclipse, |
| but you can start from your EMF model (in that case you may probably omit the ".edit" and ".editor" plugins, depending on your model). |
| </p> |
| <p> |
| Now you can create your first example with the appropriate wizard. |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>select "File" -> "New" -> "Project..."</li> |
| <li>from the "Emf Parsley" category select "Emf Parsley Dsl based Project"</li> |
| <li>click "Next"</li> |
| <li>give a name to the project (e.g. "org.eclipse.emf.parsley.examples.firstexample")</li> |
| <li>click "Finish"</li> |
| </ol> |
| <p> |
| |
| |
| The generated project has some classes and a <strong>module.parlsey</strong> file, which opens automatically. |
| Just type the following content into the {} block (note that context assist is available) |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| parts { |
| viewpart org.eclipse.emf.parsley.examples.firstexample.view.library.treeform { |
| viewname "My Library Tree Form" |
| viewclass |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Here above we have just declared a view part with |
| |
| </p> |
| <ol> |
| <li>id <strong>"org.eclipse.emf.parsley.examples.firstexample.view.library.treeform"</strong></li> |
| <li>name <strong>"Library Tree Form"</strong></li> |
| <li>class: not yet set, we are going to create |
| <strong>"org.eclipse.emf.parsley.examples.firstexample.views.LibraryTreeFormView"</strong></li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| So there is still an error, in fact we need to create the declared class. |
| <strong>Suggestion:</strong> Just copy the above qualified class name (<strong>"org.eclipse.emf.parsley.examples.firstexample.views.LibraryTreeFormView"</strong>), |
| select the project, right-click and select File -> New -> Class. Now paste the clipboard content into <strong>"Name:"</strong> field: the |
| package and class name will be automatically splitted into right fields. Then click <strong>"Finish"</strong>. |
| </p> |
| <p> |
| Now modify the view class code with this content: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| import org.eclipse.emf.parsley.views.AbstractSaveableTreeFormView; |
| import org.eclipse.emf.common.util.URI; |
| |
| public class LibraryTreeFormView extends AbstractSaveableTreeFormView { |
| |
| protected URI createResourceURI() { |
| return URI.createFileURI( System.getProperty("user.home") + "/MyLibrary.library" ); |
| } |
| |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Now get back to <strong>module.parlsey</strong> file, go just after <strong>"viewclass"</strong> keyword, type <strong>"LibraryTreeFormView"</strong> |
| and <strong>Ctrl-Space</strong>: the content assist will set automatically the correct qualified name |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| viewclass org.eclipse.emf.parsley.examples.firstexample.views.LibraryTreeFormView |
| </pre> |
| <p> |
| </p> |
| <p> |
| when you save the above file you will notice that a new file (<strong>"plugin.xml_emfparsley_gen"</strong>) |
| is generated into the root folder of your project. Just copy this file into <strong>"plugin.xml"</strong>. |
| </p> |
| <p> |
| Let's focus briefly on the above <strong>createResourceURI()</strong> method: our goal is allowing to manage |
| a library model instance which persists on a EMF Resource. |
| In this example we choose to use the EMF default persistence (XMI), but you can provide any URI |
| (e.g. using Teneo, CDO or any other EMF Resource Persistence implementation) |
| In particular here we choose to persist the Resource in a XMI file named <strong>"MyLibrary.library"</strong> into the user home |
| folder (you might want to change it with any other path). |
| </p> |
| <p> |
| We need a <strong>Dependency</strong> from the model plug-in: so open <strong>MANIFEST.MF</strong> file, go to <strong>Dependencies</strong> |
| tab, press <strong>"Add..."</strong> button in <strong>"Required Plug-ins"</strong> section and insert <strong>"org.eclipse.emf.examples.library"</strong> |
| among dependencies. |
| </p> |
| <p> |
| Before executing this code we need to do some little more work in order to initialize the Resource. |
| </p> |
| <p> |
| An easy way to overcome this issue can be the following: |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>open the class *GuiceModule (FirstexampleGuiceModule in this example) that the wizard created for you. |
| Note that this is a key class for all customizations; it allows to override several methods in order to provide custom behaviors |
| and implementations.</li> |
| <li>override method <strong>bindEmptyResourceInitializer()</strong> providing a class for Resource initialization |
| |
| <pre class="prettyprint" skin="desert"> |
| public Class<? extends EmptyResourceInitializer> bindEmptyResourceInitializer() { |
| return LibraryEmptyResourceInitializer.class; |
| } |
| </pre></li> |
| <li>create a new class <strong>LibraryEmptyResourceInitializer</strong> extending from <strong>EmptyResourceInitializer</strong> for Resource initialization |
| <pre class="prettyprint" skin="desert"> |
| import org.eclipse.emf.parsley.resource.EmptyResourceInitializer; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.examples.extlibrary.EXTLibraryFactory; |
| import org.eclipse.emf.examples.extlibrary.Library; |
| |
| public class LibraryEmptyResourceInitializer extends EmptyResourceInitializer { |
| |
| public void initialize(Resource resource) { |
| super.initialize(resource); |
| Library library = EXTLibraryFactory.eINSTANCE.createLibrary(); |
| resource.getContents().add(library); |
| } |
| |
| } |
| </pre> |
| The method <strong>initialize()</strong> will be executed only when the Resource is empty |
| (i.e., it has no contents).</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| now get back to the <strong>MANIFEST.MF</strong> and run the example |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-launch.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| As an Eclipse RCP developer you know, of course, that this will start another Eclipse instance (unless |
| you add an Application plug-in to the launch or define an Application in the current plug-in). |
| </p> |
| <p> |
| In this second Eclipse instance you can show the View in this way: |
| </p> |
| <ol> |
| <li><strong>Window -> Show View -> Other...</strong></li> |
| <li>from Category "Other", select "My Library Tree Form"</li> |
| <li>press <strong>OK</strong></li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-run.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| With this simple view you can start editing the model instance. For example you can set the <strong>"name"</strong> |
| field; as soon as you start typing characters into this field you will notice that: |
| </p> |
| <ol> |
| <li>the View turns to a <strong>"dirty"</strong> state (an asterisk symbol appears on the view tab)</li> |
| <li>the <strong>"Save"</strong> toolbar button is enabled</li> |
| <li>the typed characters are reflected into the label correspondent to the Library icon</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| if you now perform a <strong>"Save"</strong> action the persistence mechanism will trigger and you will see that file |
| </p> |
| <user.home>/MyLibrary.library |
| <p> |
| |
| is being created on the file system. From now on, this file will keep the state of the model object whenever |
| you change and save it. |
| </p> |
| <p> |
| To create a Writer into the Library just right-click on the Library object and select <strong>New Child -> Writer</strong> |
| </p> |
| <p> |
| </p> |
| <img src="images/createWriter.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Please note that you might see a slightly different content in the above context-menu in case you deleted |
| the .edit plugin when creating the model (e.g. <strong>"Writers Writer"</strong> instead of <strong>"Writer"</strong>, <strong>"Stock Book"</strong> instead of <strong>"Book"</strong> and |
| similar (this is because with EMF it is possible to customize labels also via .edit plugin). |
| </p> |
| <p> |
| Now set for instance the writer <strong>"name"</strong> field and save. |
| Now just play around creating Books, associating them to Writers and so on. |
| As you can see you can entirely manage the EMF model instance: creating, modifying and deleting elements. |
| </p> |
| <p> |
| Whenever the current selection on the upper side of the view changes, then the lower side shows the detail |
| of this selection. |
| </p> |
| <p> |
| However, up to this point, you have no control over the field to be shown and its order; for example |
| you may want just the <strong>"name"</strong> attribute for the Library and <strong>"name", "address" and "books"</strong> attributes |
| for Writers and maybe <strong>"title", "authors" and "category"</strong> for Books. |
| </p> |
| <p> |
| Well, it's indeed very easy to obtain this: just edit the <strong>module.parsley</strong> file, |
| adding the following import (without ending line with ";") |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| import org.eclipse.emf.examples.extlibrary.* |
| </pre> |
| <p> |
| </p> |
| <p> |
| and then defining the features to show |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| module ... { |
| |
| parts { |
| ... |
| } |
| |
| featuresProvider { |
| features { |
| Library -> name |
| Writer -> name, address, books |
| Book -> author, title, category |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Remeber that code completion is available, just exploit it since it helps a lot. |
| </p> |
| <p> |
| If you restart now the application you will see that, when selecting an object, only the declared attributes |
| will be shown. Furthermore, they are shown in the specified order. |
| </p> |
| <p> |
| Did you run the application in Debug mode? Well, then you can change fields and order, save and see the |
| changes without even restarting the application. |
| </p> |
| <p> |
| Do you want to change text used for attribute labels in the detail? Just add the following: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| propertyDescriptionProvider { |
| text { |
| Book : author -> 'Wrote by:' |
| Writer : name -> 'Name:' |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| Or do you want to change the label shown on the tree nodes on the upper side and as detail title? |
| Maybe want to format the book label like this? |
| |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| labelProvider { |
| text { |
| Book b -> '"' + b.title + '"' +' (by '+ b.author.name + ')' |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| </p> |
| <img src="images/labelCustomization.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| </div> |
| </div> |
| <hr style="width:64.6%;margin-bottom:28px;margin-top:30px;" class="col-md-8 col-md-offset-3"> |
| <div class="row featurette"> |
| <div class="col-md-8 col-md-offset-3"> |
| <h1 id="par" class="featurette-heading text-parsley">Components</h1> |
| <p> |
| This section describes the components that are provided to be used out-of-the-box, that are the foundations for all parts built upon <strong>Emf Parsley</strong>. |
| Afetr a brief description, for each component we present a set of customizations, just to get an idea of how it works. You can refer |
| to <a href="#addref" rel="Customizations">Customizations Section</a> for a complete list. |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Form Component</h2> |
| <p> |
| The <strong>Form Component</strong> can be used to rapresent an <abbr title="org.eclipse.emf.ecore.EObject">EObject</abbr> |
| in a row-oriented form, |
| like in the image above. |
| </p> |
| <p> |
| </p> |
| <img src="images/03-components-form.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| <strong>EMF Parsley</strong> provides a factory that can be used to create such a component, like in the code below. |
| Here you can see that can be configured only in 2 lines, the constructor phase and the build&fill phase. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject FormFactory formFactory; |
| |
| (...) |
| |
| formComposite = formFactory.createFormDetailComposite(parent, SWT.NONE); |
| formComposite.init(eObject); |
| </pre> |
| <p> |
| </p> |
| <p> |
| Most of the job is done by the second line of code, that get the list of <abbr title="org.eclipse.emf.ecore.EStructuralFeature">EStructuralFeature</abbr> |
| defined for the <abbr title="org.eclipse.emf.ecore.EClass">EClass</abbr> |
| |
| (that is the type of the object to rapresent) and builds a row for each of them. Each row is composed |
| by a <strong>label</strong> with the name of the feature and a <strong>control</strong> to access the data. |
| </p> |
| <p> |
| All these aspect can be customized in many way, for example feature list, the labels and the controls. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Feature List Customization<a id="FormComponent_features"></a></h3> |
| <p> |
| The <strong>list fo feature</strong> displayed on the form can be customized via the <a href="#FeaturesProvider">Feature Provider</a> to select the features or the order. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Caption Customization<a id="FormComponent_captions"></a></h3> |
| <p> |
| The description on the left side of the form can be customizzed via the <a href="#FormFeatureCaptionProvider">Form Feature Caption Provider</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Control Customization<a id="FormComponent_controls"></a></h3> |
| <p> |
| Otherwise to customize the controls on the right, you can use the <a href="#FormControlFactory">Form Control Factory</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Proposal Provider<a id="FormComponent_proposals"></a></h3> |
| <p> |
| Depending on the feature types, can be some fields that use predefined values (e.g. combo). You can provide the exact proposal list via the <a href="#ProposalProvider">Proposal Provider</a> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Tree Component</h2> |
| <p> |
| The <strong>Tree Component</strong> provides a tree rapresentation of data that can be feeded with an EResource, a |
| Resource URI, and a simple EObject. This component use the EMF Meta-Model information to display objects in the tree. |
| </p> |
| <p> |
| </p> |
| <img src="images/03-components-tree.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| <strong>EMF Parsley</strong> provides an initializer that can be used to create such a component, like in the code below. |
| Here you can see that can be configured only in 2 lines, the constructor phase and the build&fill phase. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject ViewerInitializer viewerInitializer; |
| |
| (...) |
| |
| treeViewer = new TreeViewer(parent); |
| viewerInitializer.initialize(treeViewer, element); |
| </pre> |
| <p> |
| </p> |
| <p> |
| The <strong>Tree Component</strong>can be customized in several way via the standard EMF Edit facilities or with the EMF Parsley |
| codeinjection based mechanism. If you are familiar with Jface APIs, you can easily use the basic class with some facilties to define the specific implementation. |
| See the corrisponding sections for more details. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Content Provider<a id="Tree_ContentProvider"></a></h3> |
| <p> |
| An IContentProvider is used in Jface to retrieve the list of <strong>elements</strong> and <strong>children</strong> to be showed |
| in the tree viewer. The <a href="#ViewerContentProvider">Viewer Content Provider</a> is the <strong>EMF Parsley</strong> implementation of that interface, |
| and by default uses the containment mechanisms to provide children as in EMF Edit framework, but it can |
| be customized as weel. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">LabelProvider<a id="Tree_LabelProvider"></a></h3> |
| <p> |
| The <a href="#ViewerLabelProvider">Viewer Label Provider</a> is the implementation ov a ILabelProvider interface |
| and is responsible to provide the text and image rapresentation for each EObject visualized. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Adding Menu<a id="Tree_MenuBuilder"></a></h3> |
| <p> |
| The contextual menu can be added to the viewer via the ViewerInitializer, as explained in the <a href="#addref" rel="Contextual Menu">Menu section</a> |
| The <a href="#MenuBuilder">Menu Builder</a> allow to fully customize the contextual menu. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Tree Form Component</h2> |
| <p> |
| The <strong>Tree Form Component</strong> contains a <a href="#addref" rel="Tree Component"></a> that provides a tree rapresentation of data that can be feeded with |
| an EResource, a Resource URI, and a simple EObject. This component use the EMF Meta-Model information to display objects in |
| the tree. The component also combines a <a href="#addref" rel="Form Component"></a> detail that display the current selected object. |
| </p> |
| <p> |
| </p> |
| <img src="images/03-components-treeform.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| <strong>EMF Parsley</strong> provides a factory to create such a component. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject TreeFormFactory treeFormFactory; |
| |
| (...) |
| |
| treeFormComposite = treeFormFactory.createTreeFormComposite(parent, SWT.BORDER); |
| treeFormComposite.update(application); |
| </pre> |
| <p> |
| </p> |
| <p> |
| Since <strong>Tree Form Component</strong> is a combination of <strong>Tree Component</strong> and <strong>Form Component</strong>, all their customizations |
| are avaible for it. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Table Component</h2> |
| <p> |
| The <strong>Table Component</strong> can rapresent data in a grid, once you have specified what kind of object need to be rapresented. |
| It uses metamodel infos to build column as needed. |
| </p> |
| <p> |
| </p> |
| <img src="images/03-components-table.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject ViewerFactory viewerFactory; |
| |
| (...) |
| |
| tableViewer = viewerFactory.createTableViewer(composite,SWT.BORDER | SWT.FULL_SELECTION, object, eClass); |
| </pre> |
| <p> |
| </p> |
| <p> |
| The class <abbr title="org.eclipse.emf.parsley.builders.TableViewerColumnBuilder">TableViewerColumnBuilder</abbr> |
| has the responsability to |
| build the columns of the Table, by using the <a href="#FeaturesProvider">Features Provider</a> to get the list |
| of features and the <a href="#FeatureCaptionProvider">Feature Caption Provider</a> for the captions. |
| The class <abbr title="org.eclipse.emf.parsley.ui.provider.TableColumnLabelProvider">TableColumnLabelProvider</abbr> |
| can be used to specify |
| an implementation of ILabelProvider for each column. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Feature List Customization<a id="Table_features"></a></h3> |
| <p> |
| The <strong>list fo feature</strong> displayed on the form can be customized via the <a href="#TableFeaturesProvider">Table Feature Provider</a> to select the features or the order. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Caption Customization<a id="Table_captions"></a></h3> |
| <p> |
| The description on the left side of the form can be customizzed via the <a href="#FeatureCaptionProvider">Caption Provider</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Adding Menu<a id="Table_MenuBuilder"></a></h3> |
| <p> |
| The contextual menu can be added to the viewer via the ViewerInitializer, as explained in the <a href="#addref" rel="Contextual Menu">Menu section</a> |
| The <a href="#MenuBuilder">Menu Builder</a> allow to fully customize the contextual menu. |
| </p> |
| </div> |
| </div> |
| </div> |
| <hr style="width:64.6%;margin-bottom:28px;margin-top:30px;" class="col-md-8 col-md-offset-3"> |
| <div class="row featurette"> |
| <div class="col-md-8 col-md-offset-3"> |
| <h1 id="par" class="featurette-heading text-parsley">Customizations</h1> |
| <p> |
| In this chapter we will describe how <strong>EMF Parsley</strong> let you customize the standard behaviours. |
| A DSL is provided to easily customize most common feature, but you can customize all aspect by doing |
| manually. As a matter of fact each customization is explained in a single section, with the details on the DSL (if available) and the |
| class for overriding by Java. |
| </p> |
| <p> |
| As we hinted in the <a href="#addref" rel="Overview">Overview</a>, if you want to provide a specific implementation via |
| Java, you can use the Google Guice injection mechanism, but overriding the specific class with your own |
| implementation. Note that an explicit contructor is needed, with the <strong>@Inject</strong> annotation to make Guice |
| correctly works. |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Providers</h2> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Viewer Label Provider<a id="ViewerLabelProvider"></a></h3> |
| <p> |
| The Label Prorvider as in JFace allows to specify the representation of a given Object. <strong>EMF Parsley</strong> |
| provides an implementation that uses the information provided via the DSL, as you can see in the snippet |
| below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| labelProvider{ |
| text{ |
| Book -> "Book:"+title |
| Borrower -> "Borrower: "+firstName |
| } |
| image{ |
| Book -> "book.png" |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| However if you wnat to use your own implementation, you can do that by providing a specific implementation of <abbr title="org.eclipse.jface.viewers.ILabelProvider">ILabelProvider</abbr> |
| |
| and injecting it in the spefic module <strong>(TODO)</strong>. |
| <strong>EMF Parsley</strong> provides such an implementation with the class <abbr title="org.eclipse.emf.parsley.ui.provider.ViewerLabelProvider">ViewerLabelProvider</abbr> |
| |
| that is inteded to be surclassed by the programmer to provides specific implementations like in the example below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public class CustomLibraryLabelProvider extends ViewerLabelProvider { |
| |
| @Inject |
| public CustomLibraryLabelProvider(AdapterFactoryLabelProvider delegate) { |
| super(delegate); |
| } |
| |
| public String text(Book book) { |
| return "Book: " + book.getTitle(); |
| } |
| |
| public String image(Book book) { |
| return "book.png"; |
| } |
| |
| public String text(Borrower b) { |
| return "Borrower: " + b.getFirstName(); |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Viewer Content Provider<a id="ViewerContentProvider"></a></h3> |
| <p> |
| As in Jface, the Content Provider is used to get the elements to represent and for tree their children. |
| <strong>EMF Parsley</strong> provides an implementation that uses the DSL as in the code below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| viewerContentProvider{ |
| elements{ |
| Library -> books |
| } |
| children{ |
| Library -> books |
| Book b-> { |
| new ArrayList()=>[ |
| add(b.author) |
| addAll(b.borrowers) |
| ] |
| } |
| } |
| }</pre> |
| <p> |
| </p> |
| <p> |
| The developer can also provide a specific implementation of <abbr title="org.eclipse.jface.viewers.IContentProvider">IContentProvider</abbr> |
| |
| by injecting it in the spefic module <strong>(TODO)</strong>. EMF Parsley provides an implementation with the class |
| <abbr title="org.eclipse.emf.parsley.edit.ui.provider.ViewerContentProvider">ViewerContentProvider</abbr> |
| that can be easily used to |
| specify the children of all object on the tree, like in the example below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public class CustomLibraryViewerContentProvider extends ViewerContentProvider { |
| |
| @Inject |
| public CustomLibraryViewerContentProvider(AdapterFactory adapterFactory) { |
| super(adapterFactory); |
| } |
| |
| public Object elements(Library library) { |
| return library.getBooks(); |
| } |
| |
| public Object children(Library library) { |
| return library.getBooks(); |
| } |
| |
| public Object children(Book book) { |
| ArrayList<Object> children = new ArrayList<Object>(); |
| Writer author = book.getAuthor(); |
| if (author != null) { |
| children.add(author); |
| } |
| children.addAll(book.getBorrowers()); |
| return children; |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Features Provider<a id="FeaturesProvider"></a></h3> |
| <p> |
| <strong>EMF Parsley</strong> uses thi kinf of provider wherever a list of feature is requested for a certain EClass. |
| The default is to return the list of all the features in the EClass, but the programmer can customize it (for instance, |
| by returning only a superset, or using a different order) on an EClass-based strategy. |
| Thus you can use the DSL to specify that list, as in the snipped below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| featuresProvider{ |
| features{ |
| Book -> title, author, category, pages |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| If we look at Java, there are more chances to customize this behaviour, but we need to go deep in some |
| details of the <strong>Feature Provider</strong> implementation. |
| </p> |
| <p> |
| When the framework builds components according to the |
| <abbr title="org.eclipse.emf.ecore.EStructuralFeature">EStructuralFeature</abbr> |
| s of a given |
| <abbr title="org.eclipse.emf.ecore.EClass">EClass</abbr> |
| it relies on an injected |
| <abbr title="org.eclipse.emf.parsley.ui.provider.FeaturesProvider">FeaturesProvider</abbr> |
| . |
| The default behavior is to simply return all the features of the a given EClass, |
| in the order they are defined in the EClass, as implemented by the method <strong>defaultFeatures</strong> in <abbr title="org.eclipse.emf.parsley.ui.provider.FeaturesProvider">FeaturesProvider</abbr> |
| . |
| </p> |
| <p> |
| You can set the mappings, i.e., specify the structural |
| features you want to be used given an EClass, by implementing |
| the method <strong>buildMap</strong>, which receives the |
| <abbr title="org.eclipse.emf.parsley.ui.provider.FeaturesProvider$EClassToEStructuralFeatureMap">FeaturesProvider.EClassToEStructuralFeatureMap</abbr> |
| |
| that can be filled with the method <strong>mapTo</strong>; |
| for instance, using the EMF extended library |
| example, this customization will return only the <strong>name</strong> and <strong>address</strong> features |
| for <strong>Library</strong>, the <strong>firstName</strong>, <strong>lastName</strong> and <strong>address</strong> for |
| <strong>Person</strong>, and the <strong>firstName</strong>, <strong>lastName</strong> and <strong>books</strong> (but |
| not <strong>address</strong>) for <strong>Writer</strong> (which inherits from <strong>Person</strong>). |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| import static org.eclipse.emf.examples.extlibrary.EXTLibraryPackage.Literals.*; |
| import org.eclipse.emf.parsley.ui.provider.EStructuralFeaturesProvider; |
| |
| public class LibraryEStructuralFeaturesProvider extends |
| FeaturesProvider { |
| |
| @Override |
| protected void buildMap(EClassToEStructuralFeatureMap map) { |
| super.buildMap(map); |
| map.mapTo(LIBRARY, |
| LIBRARY__NAME, ADDRESSABLE__ADDRESS); |
| map.mapTo(PERSON, PERSON__FIRST_NAME, PERSON__LAST_NAME, ADDRESSABLE__ADDRESS); |
| map.mapTo(WRITER, PERSON__FIRST_NAME, PERSON__LAST_NAME, WRITER__BOOKS); |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Another possibility is to build a map which relies on Strings |
| both for the <abbr title="org.eclipse.emf.ecore.EClass">EClass</abbr> |
| and for |
| the list of <abbr title="org.eclipse.emf.ecore.EStructuralFeature">EStructuralFeature</abbr> |
| ; |
| note that the name of the <abbr title="org.eclipse.emf.ecore.EClass">EClass</abbr> |
| should |
| be obtained by using <strong>getInstanceClassName()</strong>; you can also |
| combine the two approaches. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Table Features Provider<a id="TableFeaturesProvider"></a></h3> |
| <p> |
| As an extension, you can use the <abbr title="org.eclipse.emf.parsley.ui.provider.TableFeaturesProvider">TableFeaturesProvider</abbr> |
| : |
| the customizations will be applied only to <a href="#addref" rel="Table Component">Tables</a>, not to <a href="#addref" rel="Form Component">Forms</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Feature Caption Provider<a id="FeatureCaptionProvider"></a></h3> |
| <p> |
| The <abbr title="org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider">FeatureCaptionProvider</abbr> |
| provides captions for |
| the features in <a href="#addref" rel="Table Component">Tables</a> and <a href="#addref" rel="Form Component">Forms</a>. |
| Here you can see an example of the DSL. |
| |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| featureCaptionProvider{ |
| text{ |
| Book:author -> "Wrote by:" |
| Writer:name -> "Name:" |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| The <abbr title="org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider">FeatureCaptionProvider</abbr> |
| provides captions for |
| the features. It can be customized, with injection (see Injection paragraph), to customize the caption label on the |
| left of each control in a form and the headers in a table's columns. |
| The framework use a polimorphic mechanism to find customizations, so that It can |
| be written a method with a specific signature build by the keyword <strong>'text'</strong> followed by the EClass and the EStructuralFeature. |
| All parts of the name are separated by an underscore character and the method must accept a parameter of type EStructuralFeature. |
| </p> |
| <p> |
| In the following example we specify the caption text for the feature 'Author' of Book and the feature 'Name' for |
| Writer. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public String text_Book_author(final EStructuralFeature feature) { |
| return "Wrote by:"; |
| } |
| |
| public String text_Writer_name(final EStructuralFeature feature) { |
| return "Name:"; |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Form Feature Caption Provider<a id="FormFeatureCaptionProvider"></a></h3> |
| <p> |
| The <abbr title="org.eclipse.emf.parsley.ui.provider.FormFeatureCaptionProvider">FormFeatureCaptionProvider</abbr> |
| can be used if you want |
| to define the description only for the form. For example using the <a href="#addref" rel="Tree Form Component">Tree |
| Form</a> your definition will not be used in the tree. |
| </p> |
| <p> |
| In this case you can also define a method the returns directly the control, like in the example |
| below. In such methods there is another parameter that is the parent composite. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public Label label_Writer_name(Composite parent, EStructuralFeature feature) { |
| Label label = defaultLabel(parent, feature); |
| label.setBackground(getFormToolkit().getColors().getColor(IFormColors.TITLE)); |
| return label; |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Proposal Provider<a id="ProposalProvider"></a></h3> |
| <p> |
| Some controls use a list of proposal to help the end user experince: for example the combo box has a |
| list of proposal, but also the simple text can use the proposal to assist and correct the hand-writed |
| values. For each feature it can be specified a list of proposals via the DSl. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| proposals{ |
| Book:author -> { |
| defaultProposals(feature). |
| filter(Writer). |
| filter[name.startsWith("F")].toList |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| This customization can be done also in Java, by extending the class <abbr title="org.eclipse.emf.parsley.binding.ProposalCreator">ProposalCreator</abbr> |
| |
| and implementing the method </p> |
| <pre class="prettyprint" skin="desert">public List<?> proposals_Book_author(Book book) {...}</pre> |
| <p> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Contextual Menu</h2> |
| <p> |
| Contextual menu can be added to any viewer by usinf the <abbr title="org.eclipse.emf.parsley.viewers.ViewerInitializer">ViewerInitializer</abbr> |
| . |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject ViewerInitializer viewerInitializer; |
| (...) |
| |
| treeActionBarContributor.initialize(editingDomain); |
| viewerInitializer.addContextMenu(treeFormComposite.getViewer(), |
| treeActionBarContributor, editingDomain, this); |
| treeFormComposite.getViewer().addSelectionChangedListener(treeActionBarContributor); |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Menu Builder<a id="MenuBuilder"></a></h3> |
| <p> |
| <strong>EMF Parsley</strong> logically separate the menu into 2 parts. The first section contains all common edit commands |
| such as <strong>copy</strong> and <strong>paste</strong>. The second section regards EMF specific commands, such as for example <strong>new child</strong>. |
| You can use the DSL to fully customize the menu, as in the example below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| menuBuilder{ |
| menus{ |
| Library-> #[ |
| submenu("Edit",#[ |
| actionCopy, |
| actionCut, |
| separator, |
| actionPaste |
| ]) |
| ] |
| } |
| emfMenus{ |
| Library -> #[ |
| actionAdd("Add a new book", books, |
| EXTLibraryFactory.eINSTANCE.createBook => [ |
| title="new book" |
| ] |
| ) |
| ] |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| You can customize menu also via Java, by extending the <abbr title="org.eclipse.emf.parsley.edit.action.EditingMenuBuilder">EditingMenuBuilder</abbr> |
| . |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Factories</h2> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Form Control Factory<a id="FormControlFactory"></a></h3> |
| <p> |
| <strong>EMF Parsley</strong> let you customize the <strong>form controls</strong> via the DSL as in the following example. |
| |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| formControlFactory { |
| control { |
| Library : name -> { } |
| Writer : books -> |
| createLabel( |
| books.map[title].join(", ")) |
| Writer : name -> { createLabel(parent, "") } |
| target { observeText } |
| Writer : firstName -> |
| toolkit.createLabel(parent, "") |
| target observeText(SWT::Modify) |
| Borrower : firstName -> { |
| createText(firstName, SWT::MULTI, SWT::BORDER, |
| SWT::WRAP, SWT::V_SCROLL) |
| } |
| } |
| } |
| </pre> |
| <p> |
| |
| |
| If you want to customize the controls on the detail via Java, you can extend the class <abbr title="org.eclipse.emf.parsley.binding.FormControlFactory">FormControlFactory</abbr> |
| . |
| Using the same polimorphic mechanism of the labels, the programmer can write a method with the keyword <strong>'control'</strong> |
| followed by the EClass and EStructuralFeature undescore-character-separated. In the signature of the |
| method must be both the <strong>DataBinding Context</strong> and the <strong>Feature Observable</strong> that can be used for databinding. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public Control control_Writer_name(DataBindingContext dbc,IObservableValue featureObservable) { |
| //Creating the control |
| Text text = getToolkit().createText(getParent(), ""); |
| text.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER); |
| text.setBackground(getToolkit().getColors().getColor(IFormColors.TITLE)); |
| //Binding the control to the feature observable |
| dbc.bindValue(SWTObservables.observeText(text, SWT.Modify), featureObservable); |
| return text; |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Dialog Control Factory<a id="DialogControFactory"></a></h3> |
| <p> |
| If you want to customize controls in Dialog, you can use the specific DSL section <strong>dialogControlFactory</strong>: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| dialogControlFactory { |
| control { |
| ... |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| </div> |
| <hr style="width:64.6%;margin-bottom:28px;margin-top:30px;" class="col-md-8 col-md-offset-3"> |
| <div class="row featurette"> |
| <div class="col-md-8 col-md-offset-3"> |
| <h1 id="par" class="featurette-heading text-parsley">Eclipse 4.x</h1> |
| <p> |
| Instead of using the Extension Point mechanism, EMF Parsley leverages from DSL and Google Guice Injection. |
| </p> |
| <p> |
| Because of this, it is very easy to use it with Eclipse 4.x (e4). |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">First Example Setup</h2> |
| <p> |
| If you followed the steps described in section <a href="#addref" rel="First Example">First Example</a> you will have already |
| what we need to begin. Otherwise the following wizard will bring you to that point. |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Emf Parsley Examples", select "Emf Parsley First Example"</li> |
| <li>press Next and Finish</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| You will end up with three plug-ins: |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li>org.eclipse.emf.parsley.examples.firstexample (the EMF Parsley example plug-in)</li> |
| <li>org.eclipse.emf.examples.library (the model plug-in)</li> |
| <li>org.eclipse.emf.examples.library.edit (the model.edit plug-in)</li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| As a reminder, in section <a href="#addref" rel="First Example">First Example</a> we reached the point where we launched a second Eclipse |
| instance (but, of course, just defining a product you could have a standalone 3.x application) with a |
| view (called "My Library Tree Form") that allowed to manage the model. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Preparing for a pure e4 Application</h2> |
| <p> |
| What we will do now is starting from the previous step and create an e4 Application (on top of |
| the previous plug-ins) that gets to the same result, but now with a pure e4 Part. |
| </p> |
| <p> |
| In order to do this we need to export the <strong>"org.eclipse.emf.parsley.examples.firstexample"</strong> package from the first plug-in. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Create an e4 Application</h2> |
| <p> |
| Now let's create a new, empty, e4 application, e.g. <strong>"org.eclipse.emf.parsley.examples.firstexample.application"</strong> |
| (you can find details on how to create e4 applications in <a href="http://www.rcp-vision.com/?p=4694&lang=en">our |
| tutorials</a>). |
| </p> |
| <p> |
| Create a Part and ensure that the application starts. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Using a TreeComposite into an e4 Part</h2> |
| <p> |
| In the just created plug-in we need dependencies from the previous plug-ins: so open the <strong>org.eclipse.emf.parsley.examples.firstexample.application/MANIFEST.MF</strong> file, go to <strong>Dependencies</strong> |
| tab and add the three previous plug-ins. Add also <strong>"org.eclipse.emf.parsley"</strong> plug-in. |
| Don't forget to add the previous, and the required plug-ins, also to the Product. |
| </p> |
| <p> |
| Open the Part java class and make the following changes: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| // Use these imports during Organizing Imports operation |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.swt.widgets.Composite; |
| |
| // The part implements IMenuListener for context menu handling |
| public class MyEclipse4Part implements IMenuListener |
| |
| //the parent composite |
| private Composite parent; |
| //the EMF Parley composite for showing a tree and a detail form |
| private TreeFormComposite treeFormComposite; |
| //the EMF Resource |
| private Resource resource; |
| |
| //Guice injected EMF Parsley component for contributing to the tree context menu |
| private TreeActionBarContributor treeActionBarContributor = FirstexampleActivator.getDefault().getInjector() |
| .getInstance(TreeActionBarContributor.class); |
| |
| |
| //Guice injected EMF Parsley factory for the tree detail form |
| private TreeFormFactory treeFormFactory = FirstexampleActivator.getDefault().getInjector() |
| .getInstance(TreeFormFactory.class); |
| |
| //Guice injected EMF Parsley Resource loader |
| private ResourceLoader resourceLoader = FirstexampleActivator.getDefault().getInjector() |
| .getInstance(ResourceLoader.class); |
| |
| //Guice injected EMF Parsley editing domain |
| private AdapterFactoryEditingDomain editingDomain = FirstexampleActivator.getDefault().getInjector() |
| .getInstance(AdapterFactoryEditingDomain.class); |
| |
| //Guice injected viewer initializer |
| private ViewerInitializer viewerInitializer = (ViewerInitializer) FirstexampleActivator.getDefault().getInjector() |
| .getInstance(ViewerInitializer.class); |
| |
| //Guice injected save manager |
| private ResourceSaveManager resourceSaveManager = FirstexampleActivator.getDefault().getInjector() |
| .getInstance(ResourceSaveManager.class); |
| |
| //URI for EMF Resource |
| private URI uri = URI.createFileURI(System.getProperty("user.home") |
| + "/MyLibrary.library"); |
| </pre> |
| <p> |
| </p> |
| <p> |
| Modify the <strong>@PostConstruct</strong> method with this code: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @PostConstruct |
| public void postConstruct(Composite parent) { |
| this.parent = parent; |
| |
| // Initialize TreeFormFactory & ResourceLoader |
| init(treeFormFactory, resourceLoader); |
| |
| // Prepare the menu action bar contributor upon the selection |
| treeFormComposite.getViewer().addSelectionChangedListener(treeActionBarContributor); |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| and add the following methods: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public void init(TreeFormFactory treeFormFactory, ResourceLoader resourceLoader) { |
| //create the tree-form composite |
| treeFormComposite = treeFormFactory.createTreeFormMasterDetailComposite(parent, SWT.BORDER); |
| //load the resource |
| resource = resourceLoader.getResource(editingDomain, uri).getResource(); |
| //update the composite |
| treeFormComposite.update(resource); |
| //initialize and bind the context menu to the tree-form composite |
| treeActionBarContributor.initialize(editingDomain); |
| viewerInitializer.addContextMenu( |
| treeFormComposite.getViewer(), treeActionBarContributor, editingDomain, this); |
| } |
| |
| @Override |
| public void menuAboutToShow(IMenuManager manager) { |
| treeActionBarContributor.menuAboutToShow(manager); |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| If you now run the application you will be able to manage the model: |
| </p> |
| <p> |
| </p> |
| <img src="images/07-eclipse4-part.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| but you will notice that it is not possible to persist the changes to the model. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Adding the dirty state and Save command</h2> |
| <p> |
| In order to allow persisting the model changes we have to add the dirty state handling to the part and |
| the Save command to the application. |
| Let's start with adding the following attribute to the part |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Inject |
| MDirtyable dirtyable; |
| </pre> |
| <p> |
| </p> |
| <p> |
| initialize it in the <strong>@PostConstruct</strong> method |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @PostConstruct |
| public void postConstruct(Composite parent, MDirtyable dirtyable) { |
| |
| this.dirtyable = dirtyable; |
| |
| this.dirtyable.setDirty(false); |
| </pre> |
| <p> |
| </p> |
| <p> |
| add to <strong>init</strong> method the following code in order to update the dirty state |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| editingDomain.getCommandStack().addCommandStackListener( |
| new CommandStackListener() { |
| public void commandStackChanged(EventObject event) { |
| if (dirtyable != null) |
| dirtyable.setDirty(true); |
| } |
| }); |
| </pre> |
| <p> |
| </p> |
| <p> |
| and add the <strong>@Persist</strong> method, which will be called when the part is saved |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| @Persist |
| public void save(MDirtyable dirty) throws IOException { |
| if (resourceSaveManager.save(resource)) { |
| if (dirty != null) { |
| dirty.setDirty(false); |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| and, in the end, add the <strong>Save</strong> handler along with the correspondent <strong>Command</strong> and <strong>Menu</strong> |
| (you can find how to create handlers, commands and menus in an e4 applications in <a href="http://www.rcp-vision.com/?p=4972&lang=en">our |
| tutorials</a>) |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public class SaveHandler { |
| |
| @Execute |
| void execute(EPartService partService, @Named(IServiceConstants.ACTIVE_PART) MPart part) { |
| partService.savePart(part, false); |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| </div> |
| </br></br></br></br></br></br></br> |
| <!-- /END THE FEATURETTES --> |
| </div> |
| <!-- FOOTER --> |
| <footer style="z-index: 1001;position:relative;background-color:#35414C;-webkit-box-shadow: 0px -3px 8px 0px rgba(171,209,173,1);-moz-box-shadow: 0px -3px 8px 0px rgba(171,209,173,1);box-shadow: 0px -3px 8px 0px rgba(30,51,72,1);margin-top:1%;"> |
| <img width="100%" alt="" src="img/footer.jpg" /> |
| <nav class="navbar navbar-default" role="navigation" style="background-color:transparent; border:0 none; margin:-97px 0px 31px 0px;min-height: 36px;"> |
| <div class="container" style="width:37.6%;"> |
| |
| </div> |
| </nav> |
| <nav class="navbar navbar-default" role="navigation" style="background-color:transparent; border:0 none; margin:-18px 0px 0px 0px;min-height: 36px;"> |
| <div class="container" style="width:57%;"> |
| <!-- Collect the nav links, forms, and other content for toggling --> |
| <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-4"> |
| <ul class="nav navbar-nav miolifooter"> |
| <li><a href="index.html">Home</a></li> |
| <li><a href="download.html">Download</a></li> |
| <li><a href="documentation.html">Documentation</a></li> |
| <li><a href="sources.html">Sources</a></li> |
| <li style="border-right: 0 none;"><a href="support.html">Support</a></li> |
| </ul> |
| </div><!-- /.navbar-collapse --> |
| </div> |
| </nav> |
| <p class="terms" style="margin:0px;padding:21px 0px 6px 20px;"><a target="_blank" href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a> · <a target="_blank" href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a> · <a target="_blank" href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a> · <a target="_blank" href="http://www.eclipse.org/legal/">Legal</a><a class="pull-right" style="z-index: 1001;position:relative;margin:-38px 15px 0px 0px;" href="#top" id="topbutton"><img alt="Back to top" src="img/arrow_up.png"/></a></p> |
| </footer> |
| <!-- Bootstrap core JavaScript |
| ================================================== --> |
| <!-- Placed at the end of the document so the pages load faster --> |
| <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>--> |
| <script src="js/vendor/jquery.min.js"></script> |
| <script src="js/vendor/jquery.scrollstop.js"></script> |
| <script src="js/vendor/bootstrap.min.js"></script> |
| |
| <!-- Open lightbox-content image --> |
| <script type="text/javascript"> |
| $('.featurette-image').click(function(){ |
| $('.lightbox-content').empty(); |
| $($(this).parents('div').html()).appendTo('.lightbox-content'); |
| $('#myModal').modal({show:true});}); |
| </script> |
| |
| <script type="text/javascript"> |
| $('#twitterli').mouseover(function() { |
| $('a#twitterli > img').attr('src','img/twitter_h1.png'); |
| }); |
| $('#twitterli').mouseout(function() { |
| $('a#twitterli > img').attr('src','img/twitter.png'); |
| }); |
| |
| $('#twitterfooter').mouseover(function() { |
| $('a#twitterfooter > img').attr('src','img/twitter_h2.png'); |
| }); |
| $('#twitterfooter').mouseout(function() { |
| $('a#twitterfooter > img').attr('src','img/twitter.png'); |
| }); |
| |
| $('#topbutton').mouseover(function() { |
| $('a#topbutton > img').attr('src','img/arrow_up_h.png'); |
| }); |
| $('#topbutton').mouseout(function() { |
| $('a#topbutton > img').attr('src','img/arrow_up.png'); |
| }); |
| |
| //gestione scroll verticale |
| $(function() { |
| $('a[href*=#]').click(function() { |
| if(this.hash=="#top"){ |
| $('html,body').animate({scrollTop:0}, 800); |
| return false; |
| } else { |
| var arrivo = $(this.hash); |
| if (arrivo.length) { |
| arrivo=arrivo.offset().top; |
| $('html,body').animate({scrollTop:arrivo-205}, 500); |
| return false; |
| } |
| } |
| }); |
| }); |
| |
| $(window).on("scrollstop", function() { |
| var scrollposition = $('html,body').scrollTop()+210; |
| if(/chrome/.test(navigator.userAgent.toLowerCase())) |
| scrollposition = $("body").scrollTop()+210; |
| var mieipar = $("[id^='par']"); |
| mieipar.each(function(idx) { |
| if(idx==mieipar.length-1 && scrollposition>=$(this).offset().top){ |
| var parid = $(this).attr('id').match(/\d+/); |
| $('.activemenu').removeClass("activemenu"); |
| $("a[href='#par"+parid+"']").parent().addClass("activemenu"); |
| } else if(scrollposition>=$(this).offset().top && scrollposition<mieipar.eq(idx + 1).offset().top){ |
| var parid = $(this).attr('id').match(/\d+/); |
| $('.activemenu').removeClass("activemenu"); |
| $("a[href='#par"+parid+"']").parent().addClass("activemenu"); |
| } |
| }); |
| }) |
| |
| $(document).ready(function() { |
| //Setto link attivo nel menu |
| var mieili = $('.miomenu li'); |
| mieili.each(function(idx) { |
| var indirizzo = $(this).children().attr('href'); |
| if(indirizzo.length>0 && window.location.href.indexOf(indirizzo)>0){ |
| $(this).addClass('mioactive'); |
| } |
| }); |
| //Setto link attivo nel footer |
| mieili = $('.miolifooter li'); |
| mieili.each(function(idx) { |
| var indirizzo = $(this).children().attr('href'); |
| if(indirizzo.length>0 && window.location.href.indexOf(indirizzo)>0){ |
| $(this).children().addClass('mioactivefooter'); |
| } |
| }); |
| |
| //Setto gli indici per l'effertto hover del dropdown-menu |
| var mieiidx = $(".dropdown-menu a[href='#par']"); |
| var mieipar = $("[id^='par']"); |
| mieiidx.each(function(idx) { |
| $(this).attr('href','#par'+idx); |
| if(idx<mieipar.length) |
| mieipar.eq(idx).attr('id','par'+idx); |
| }); |
| |
| //Setto le references #addref |
| var mieiaddref = $("a[href='#addref']"); |
| mieiaddref.each(function(idx) { |
| var ref = $(".dropdown-menu a:contains("+$(this).attr('rel')+")").attr('href'); |
| if(ref!=null && ref.length>0) |
| $(this).attr('href',ref); |
| }); |
| }); |
| |
| //Levo il blur da tutti i link |
| $("a").focus( |
| function () { |
| if ($(this).blur) $(this).blur(); |
| } |
| ); |
| |
| $('#questiondiv').mouseover(function() { |
| $('#questiondiv').css('background-color','#D7EFDA'); |
| }); |
| $('#questiondiv').mouseout(function() { |
| $('#questiondiv').css('background-color','#e8f9ea'); |
| }); |
| |
| $('#bugdiv').mouseover(function() { |
| $('#bugdiv').css('background-color','#F0F2C6'); |
| }); |
| $('#bugdiv').mouseout(function() { |
| $('#bugdiv').css('background-color','rgb(246, 247, 227)'); |
| }); |
| |
| $('#suppdiv').mouseover(function() { |
| $('#suppdiv').css('background-color','#E8E8E8'); |
| }); |
| $('#suppdiv').mouseout(function() { |
| $('#suppdiv').css('background-color','rgb(242, 242, 242)'); |
| }); |
| |
| $('#twdiv').mouseover(function() { |
| $('#twdiv').css('background-color','#CFE5F7'); |
| }); |
| $('#twdiv').mouseout(function() { |
| $('#twdiv').css('background-color','#e8f3fc'); |
| }); |
| </script> |
| <script type="text/javascript" src="google-code-prettify/lang-common.js"></script><script type="text/javascript"> |
| registerLanguage('import|module|parts|labelProvider|text|image|elements|propertyDescriptionProvider|featuresProvider|features|formControlFactory|control|target|viewerContentProvider|children|viewpart|viewname|viewclass|viewcategory|for|new|switch|default|boolean|do|if|this|double|throw|byte|else|case|enum|instanceof|return|featureCaptionProvider|catch|extends|int|short|try|char|void|finally|long|float|super|while|proposals|dialogControlFactory|menuBuilder|menus|emfMenus', 'emfparsley'); |
| </script> |
| </body> |
| </html> |