| <!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.html"><img class="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; |
| } |
| |
| .scrollup { |
| background: url(img/up.png) no-repeat scroll 0 0 rgba(0, 0, 0, 0); |
| bottom: 6%; |
| display: none; |
| opacity: 0.35; /* modifica anche in mouseout */ |
| position: fixed; |
| right: 4%; |
| z-index: 900; |
| width: 45px; |
| height: 45px; |
| } |
| </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">Dependency Injection With</br> Google Guice</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><a class="submenu" tabindex="-1" href="#par">Resources</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Configurator</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Validation</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">Advanced Features</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Testing Framework</a></li> |
| <li class="divider"></li> |
| <li><a tabindex="-1" href="#par">RAP</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Introduction</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Setup</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">Examples</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> |
| <li><a tabindex="-1" href="#par">Migration Guide</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">From 0.4 to 0.5</a></li> |
| <li><a class="submenu" tabindex="-1" href="#par">From 0.3 to 0.4</a></li> |
| <li class="divider"></li> |
| </ul> |
| </div> |
| |
| <!-- START THE FEATURETTES --> |
| </br> |
| <!-- scrollup ICON --> |
| <a class="scrollup" href="#top"></a> |
| <!-- scrollup ICON --> |
| <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 based |
| upon EMF. <strong>EMF Parsley</strong> is built on top of the EMF Edit framework and it implements features like Trees, Forms and Table builders with |
| standard JFace databinding, providing a complete component-based toolset. |
| EMF Parsley can be configured to use all kinds of EMF persistence |
| implementations (XMI, Teneo, CDO) |
| Moreover a DSL allows to easily customize several behaviors in each component. |
| </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 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 basis of <strong>EMF Parsley</strong> itslef. |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><strong>Trees</strong></li> |
| <li><strong>Forms</strong></li> |
| <li><strong>Tables</strong></li> |
| <li><strong>Editors</strong></li> |
| <li><strong>Search boxes</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 <strong>Dependency Injection</strong> |
| mechanisms (based on <a href="https://github.com/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> lets you define your View Parts: a file <strong>plugin.xml_emfparsley_gen</strong> will be generated |
| that is meant to be synchronized with your own <strong>plugin.xml</strong></li> |
| <li><strong>bindings</strong> section lets you define which implementation will be used with Injection</li> |
| <li><strong>menu</strong> section lets you define the contextual menu for all viewers (<strong>trees</strong> and <strong>tables</strong>)</li> |
| <li><strong>features provider</strong> is used to retrieve the 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 objects of a |
| tree viewer</li> |
| <li><strong>Caption Provider</strong> provides captions for each feature (namely, EStructuredFeature) of the object shown in a form, |
| in a dialog or in a table row. |
| Different implementations can be defined for <strong>dialogs</strong>, <strong>forms</strong> and <strong>tables</strong>.</li> |
| <li><strong>Control Factory</strong> provides a custom implementation of the Controls for each feature shown in a form or a dialog. |
| 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. We will use |
| one of the saveable views shipped with Parsley: a Tree Form View. |
| </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> |
| The editor plug-in project can be removed. |
| </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" |
| |
| <img src="images/01-new-project-dsl-wizard.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"></li> |
| <li>click "Next"</li> |
| <li>give a name to the project (e.g. "org.eclipse.emf.parsley.examples.firstexample") |
| and make sure the checkbox about using one of the templates is checked |
| |
| <img src="images/01-new-project-dsl-wizard2.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"></li> |
| <li>click "Next"</li> |
| <li>Select "Saveable Tree Form View" |
| |
| <img src="images/01-new-project-dsl-wizard3.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"></li> |
| <li>click "Finish"</li> |
| </ol> |
| <p> |
| |
| |
| The generated project has some classes and a <strong>module.parlsey</strong> file, which opens automatically: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| import org.eclipse.emf.parsley.examples.firstexample.FirstexampleSaveableTreeFormView |
| |
| /* org.eclipse.emf.parsley.examples.firstexample Emf Parsley Dsl Module file */ |
| module org.eclipse.emf.parsley.examples.firstexample { |
| |
| parts { |
| viewpart org.eclipse.emf.parsley.examples.firstexample { |
| viewname "Firstexample" |
| viewclass FirstexampleSaveableTreeFormView |
| } |
| } |
| |
| configurator { |
| resourceURI { |
| FirstexampleSaveableTreeFormView -> { |
| // TODO create and return a org.eclipse.emf.common.util.URI |
| return null; |
| } |
| } |
| } |
| |
| resourceManager { |
| initializeResource { |
| // Optional: initialize an empty Resource |
| // 'it' is of type Resource |
| // e.g., it.getContents += myFactory.createMyClass |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The <strong>viewpart</strong> corresponds to the standard Eclipse view part extension point; the Parsley |
| DSL will generate a <strong>plugin.xml_emfparsley_gen</strong> |
| into the root folder of your project. Just copy this file into <strong>"plugin.xml"</strong>. Parsley |
| will never override your <strong>plugin.xml</strong> file; each time you modify the module file, the |
| <strong>plugin.xml_emfparsley_gen</strong> will be generated: it is up to you to keep the generated file |
| synchronized with your <strong>"plugin.xml"</strong>. The easiest way is to select to the files, |
| and use the context menu "Compare With" => "Each Other". |
| </p> |
| <p> |
| The wizard will also generate a view part class into the project |
| (in this example, <strong>FirstexampleSaveableTreeFormView</strong>); you can add other controls |
| into that view, or customize other behaviors. Note that the Parsley DSL will never |
| touch the files into the <strong>src</strong> source folder. On the contrary, files generated into |
| <strong>emfparsley-gen</strong> source folder must never be manually modified, since its contents will |
| be regenerated each time you modify the <strong>module.parsley</strong> file. |
| </p> |
| <p> |
| For example, let's change the view name into "My Library Tree Form": |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| module org.eclipse.emf.parsley.examples.firstexample { |
| |
| parts { |
| viewpart org.eclipse.emf.parsley.examples.firstexample { |
| viewname "My Library Tree Form" |
| ... |
| </pre> |
| <p> |
| </p> |
| <p> |
| Let's save the file, wait for Eclipse to rebuild, and update the |
| <strong>plugin.xml</strong> with the new <strong>plugin.xml_emfparsley_gen</strong>. |
| </p> |
| <p> |
| (Other <strong>viewpart</strong> sections can be created; content assist is available for that). |
| </p> |
| <p> |
| In the generated <strong>module.parsley</strong>, there is a <strong>configurator</strong> section, with |
| a <strong>TODO</strong> comment (The <strong>Configurator</strong> is detailed in the section <a href="#addref" rel="Configurator">Configurator</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| configurator { |
| resourceURI { |
| FirstexampleSaveableTreeFormView -> { |
| // TODO create and return a org.eclipse.emf.common.util.URI |
| return null; |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Let's focus on the above <strong>resourceURI</strong>: our goal is allowing to manage |
| a library model instance which persists on a EMF <abbr title="org.eclipse.emf.ecore.resource.Resource">Resource</abbr> |
| . |
| So we must specify the <abbr title="org.eclipse.emf.common.util.URI">URI</abbr> |
| of the resource |
| that will be edited by our tree form view. |
| 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). |
| To achieve this, we just need to create such a URI (recall that content assist is available |
| when typing Xbase expressions): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| configurator { |
| resourceURI { |
| FirstexampleSaveableTreeFormView -> { |
| return URI.createFileURI( System.getProperty("user.home") + "/MyLibrary.library" ); |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| If you simply copy and paste the above return statement, you'll get an error about |
| unresolvable Java type URI; "Organize Imports" context menu (or its shortcut "Ctrl+Shift+O") |
| can be used to automatically add the missing import (make sure you select |
| <abbr title="org.eclipse.emf.common.util.URI">URI</abbr> |
| ). |
| </p> |
| <p> |
| Note that the specified URI, will be used for loading the resource only for our specific |
| view (the resource will be automatically created if it does not exist). |
| </p> |
| <p> |
| In the <strong>module.parsley</strong> there is another section that has been generated by the wizard: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| resourceManager { |
| initializeResource { |
| // Optional: initialize an empty Resource |
| // 'it' is of type Resource |
| // e.g., it.getContents += myFactory.createMyClass |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| We can use this section to initialize our resource when it is empty |
| (i.e., the first time the resource is created); (The <strong>resourceManager</strong> |
| is detailed in section <a href="#ResourceManager">Resource Manager</a>). |
| </p> |
| <p> |
| In this example, we want to initialize an empty resource with a |
| <strong>Library</strong> object; so |
| we first 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> |
| Now we can implement the <strong>initializeResource</strong> method |
| (as described in the comment, the <abbr title="org.eclipse.emf.ecore.resource.Resource">Resource</abbr> |
| |
| to initialized is available through the parameter <strong>it</strong>); the Library object |
| is created using the standard EMF API: we need the factory of the library model: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| resourceManager { |
| initializeResource { |
| it.getContents += EXTLibraryFactory.eINSTANCE.createLibrary |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Again, use the content assist while typing, e.g., for automatically importing the |
| type <strong>EXTLibraryFactory</strong>, or use the "Organize Imports" functionality. |
| </p> |
| <p> |
| Now, we are ready to execute this example: |
| let's 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> |
| </p> |
| <img src="images/first-example-default.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </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 (the <strong>featuresProvider</strong> is detailed |
| in section <a href="#FeaturesProvider">Features Provider</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| module ... { |
| |
| ... |
| 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 features |
| specified in the above section will be shown for each specified classes. |
| Furthermore, they are shown in the specified order. |
| </p> |
| <p> |
| NOTE: 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 captions in the form for a specific |
| class? Just add the following |
| (<strong>featureCaptionProvider</strong> is detailed in section <a href="#FeatureCaptionProvider">Feature Caption Provider</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| featureCaptionProvider { |
| 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? |
| (<strong>labelProvider</strong> is detailed in section <a href="#ViewerLabelProvider">Viewer Label Provider</a>): |
| |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| labelProvider { |
| text { |
| Book b -> { '"' + b.title + '"' } |
| Writer w -> { w.name } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The result of all the above customizations is shown in the following screenshot |
| (compare it with the previous screenshot): |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-customized.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Now, let's customize the context menus; by default, |
| Parsley will generate context menus using EMF.Edit: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-default-menus.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| We will now customize the context menu for books and writers, using |
| the <strong>menuBuilder</strong> in the DSL (context menu customization is detailed |
| in section <a href="#addref" rel="Contextual Menu">Contextual Menu</a>). |
| What we want to achieve is to have a context menu for a <strong>Writer</strong> |
| to add a new book in the library, and set its author to the |
| selected writer (similarly, we want a context menu for a <strong>Book</strong> |
| to add a new writer in the library, and set the selected book as |
| one of the new writer's books): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| menuBuilder { |
| val factory = EXTLibraryFactory.eINSTANCE |
| |
| emfMenus { |
| Writer w -> #[ |
| actionAdd( |
| "New book", |
| (w.eContainer as Library).books, |
| factory.createBook, |
| [ book | |
| book.title = "A new book" |
| book.author = w |
| ] |
| ) |
| ] |
| Book b -> #[ |
| actionAdd( |
| "New writer", |
| (b.eContainer as Library).writers, |
| factory.createWriter, |
| [ writer | |
| writer.name = "A new writer" |
| writer.books += b |
| ] |
| ) |
| ] |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| In this code we use Xbase features like list literals (<strong>#[...]</strong>) and |
| lambda expressions. |
| </p> |
| <p> |
| If you now restart the application, you see that the new |
| context menu appears on writer elements: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-menus1.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| And selecting such a menu on a writer will add a new book, with |
| a title, and whose author is the selected writer: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-menus2.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| You may want to try the new context menu on a book as well. |
| </p> |
| <p> |
| Now, let's customize the contents shown in the tree view: by default, |
| as you can see from the previous screenshots, the tree will show all |
| the contents of the library. If we want to show only the writers and |
| the books we can specify this section in the DSL |
| (the customization of the content provider is detailed in |
| section <a href="#ViewerContentProvider">Viewer Content Provider</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| viewerContentProvider { |
| children { |
| Library -> { |
| writers + books |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| and the result can be seen in the following screenshot: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-contents1.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| By default, double-clicking on a tree viewer of a saveable view will |
| show a dialog to edit that object (if you customized the |
| <strong>featuresProvider</strong>, the dialog will use your customized version); |
| by default, if you edit a field in such dialog, the modifications will |
| be applied immediately to the resource: this can be seen in the |
| labels of the tree which are automatically updated and in the dirty state of |
| the view: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-default-dialog.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Such a strategy for editing is delegated to an injected |
| <abbr title="org.eclipse.emf.parsley.edit.IEditingStrategy">IEditingStrategy</abbr> |
| , which is |
| implemented by default by <abbr title="org.eclipse.emf.parsley.edit.OnTheFlyEditingStrategy">OnTheFlyEditingStrategy</abbr> |
| . |
| </p> |
| <p> |
| One may want to avoid this automatic update of the resource, and |
| have the changes applied only when the "OK" dialog button is pressed |
| (if "Cancel" is pressed, no changes should be applied at all). |
| To achieve this behavior, it is enough to bind the alternative implementation |
| <abbr title="org.eclipse.emf.parsley.edit.UndoableEditingStrategy">UndoableEditingStrategy</abbr> |
| , in the Guice module. |
| This can be achieved in the DSL using the <strong>binding</strong> section |
| (Guice bindings are detailed in section <a href="#addref" rel="Dependency Injection With</br> Google Guice">Guice Bindings</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| bindings { |
| type IEditingStrategy -> UndoableEditingStrategy |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| We strongly suggest you use the content assist to discover default |
| bindings, since they also show Javadoc for each default binding: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-binding1.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Besides types, you can also bind (i.e., inject) specific values |
| that are used in the framework; for example, you can change the |
| orientation of the tree form sash as follows |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| ... |
| bindings { |
| type IEditingStrategy -> UndoableEditingStrategy |
| value int TreeFormSashStyle -> SWT.HORIZONTAL |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| and see the result: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-orientation.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| This ends the first tutorial. |
| </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 give 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 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 a form can be configured 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, which gets 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 represent) and builds a row for each of them. Each row is composed |
| by a <strong>caption</strong> which defaults to the name of the feature and a <strong>control</strong> to access the data. |
| </p> |
| <p> |
| All these aspects can be customized in many ways, for example you can customize the feature list, the captions and the controls. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Feature List Customization<a id="FormComponent_features"></a></h3> |
| <p> |
| The <strong>list of features</strong> displayed on the form can be customized via the <a href="#FeaturesProvider">Feature Provider</a> |
| that returns the list of the features (in a given order). |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Caption Customization<a id="FormComponent_captions"></a></h3> |
| <p> |
| The captions of the features shown in 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> |
| The Controls in the form can be customized via 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, some fields can have 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 fed with an EResource, a |
| Resource URI, and a simple EObject. This component uses 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 of an 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> allows to fully customize the menus. |
| </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 fed with |
| an EResource, a Resource URI, and a simple EObject. This component uses 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 the type of objects to represent. |
| It uses metamodel information to build columns 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.viewers.TableViewerColumnBuilder">TableViewerColumnBuilder</abbr> |
| has the responsibility 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 column headers. |
| The class <abbr title="org.eclipse.emf.parsley.ui.provider.TableColumnLabelProvider">TableColumnLabelProvider</abbr> |
| can be used to specify |
| an implementation of ILabelProvider for each cell in the table. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Feature List Customization<a id="Table_features"></a></h3> |
| <p> |
| The <strong>list fo features</strong> displayed on the table can be customized via the <a href="#TableFeaturesProvider">Table Feature Provider</a>. |
| This list of features will be used for building the columns of the table. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Caption Customization<a id="Table_captions"></a></h3> |
| <p> |
| The headers of the table can be customizzed via the <a href="#FeatureCaptionProvider">Caption Provider</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Column width Customization<a id="Table_columns_width"></a></h3> |
| <p> |
| All columns have the same size by default, but they can be customizzed via the <a href="#addref" rel="Configurator">Configurator</a> |
| for instance in the DSL, like in the example below. |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| |
| bindings{ |
| value List<Integer> TableColumnWeights -> #[10,20,30,40] |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Adding Menu<a id="Table_MenuBuilder"></a></h3> |
| <p> |
| The context 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> allows to fully customize the menus. |
| </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> lets you customize the standard behaviours. |
| A DSL is provided to easily customize most common features, but you can also customize all aspects |
| manually (i.e., in directly Java). |
| As a matter of fact each customization is explained in a single section, with the details on how to do |
| that with the DSL (if available) and in Java. |
| </p> |
| <p> |
| If you want to provide a specific implementation in |
| Java, you can use the Google Guice injection mechanism, by overriding the specific class with your own |
| implementation. Note that in some cases an explicit constructor is needed, with the <strong>@Inject</strong> annotation to make Guice |
| correctly works; when this is the case, the base class will already have such a constructor and you will only |
| need to override it, but you will also need to add the <strong>@Inject</strong> annotation explicitly. |
| </p> |
| <p> |
| Although one can specify any Guice <abbr title="com.google.inject.Module">Module</abbr> |
| , <strong>EMF Parsley</strong> ships with |
| some default base class modules that should be used for specifying custom |
| Guice bindings. The default base class is |
| <abbr title="org.eclipse.emf.parsley.EmfParsleyGuiceModule">EmfParsleyGuiceModule</abbr> |
| that is suitable to be used |
| in an OSGI environment, like Eclipse itself or RAP (see also <a href="#addref" rel="RAP">EMF Parsley RAP support</a>). |
| Our project wizards will automatically use such module as the base class. |
| For CDO we have a specialized base module. |
| </p> |
| <p> |
| We also have a module to be used in a non OSGI environment, e.g., a pure Java environment: |
| <abbr title="org.eclipse.emf.parsley.EmfParsleyJavaGuiceModule">EmfParsleyJavaGuiceModule</abbr> |
| (this is the base class of |
| <abbr title="org.eclipse.emf.parsley.EmfParsleyGuiceModule">EmfParsleyGuiceModule</abbr> |
| ). This is useful also for |
| testing purposes, for writing plain Junit tests (i.e., not Plug-in Junit tests). |
| This is also used in our testing framework (see <a href="#addref" rel="Testing Framework">EMF Parsley Testing Framework</a>). |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Dependency Injection With Google Guice</h2> |
| <p> |
| All Parsley components are assembled by means of <strong>Dependency Injection (DI)</strong>. |
| This means that whenever some code is in need for functionality (or state) |
| from another component, one just declares the dependency rather then stating |
| how to resolve it, i.e. obtaining that component. |
| </p> |
| <p> |
| For example, when some code wants to use a label provider, |
| it just declares a field (or method or constructor) and adds the |
| <abbr title="com.google.inject.Inject">@Inject</abbr> |
| annotation: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| class MyView extends ViewPart { |
| |
| @Inject |
| private ILabelProvider labelProvider; |
| |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| It is not the duty of the client code to care about where the |
| actual <abbr title="org.eclipse.jface.viewers.ILabelProvider">ILabelProvider</abbr> |
| comes from or |
| how it is created. |
| When the above class is instantiated, Guice sees that it requires an instance |
| of ILabelProvider and assigns it to the specified field or method parameter. |
| This of course only works, if the object itself is created by Guice. |
| In Parsley almost every instance is created that way and therefore the whole |
| dependency net is controlled and configured by the means of Google Guice. |
| </p> |
| <p> |
| Guice of course needs to know how to instantiate real objects for declared dependencies. |
| This is done in so called Modules. A <abbr title="com.google.inject.Module">Module</abbr> |
| |
| defines a set of mappings from types to either existing instances, |
| instance providers or concrete classes. |
| Modules are implemented in Java. Here's an example: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public class MyGuiceModule extends AbstractGenericModule { |
| |
| @Override |
| public void configure(Binder binder) { |
| super.configure(binder); |
| binder.bind(ILabelProvider.class).to(MyLabelProvider.class); |
| binder.bind(... |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| With plain Guice modules one implements a method called configure and gets a |
| <abbr title="com.google.inject.Binder">Binder</abbr> |
| passed in. |
| That binder provides a fluent API to define the mentioned mappings. |
| This was just a very brief and simplified description. |
| We highly recommend to have a look at the <a href="https://github.com/google/guice">Google Guice</a> |
| website to learn more. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Module API<a id="ModuleAPI"></a></h3> |
| <p> |
| Parsley comes with a slightly enhanced module API |
| (this was inspired by Xtext, so, if you are already familiar with the |
| enhnaced Guice module API of Xtext, you can use Parsley API right away). |
| </p> |
| <p> |
| The enhancement we added to Guice's Module API is that we provide an abstract base class, |
| which reflectively looks for certain methods in order to find declared bindings. |
| The standard base class is <abbr title="org.eclipse.emf.parsley.EmfParsleyGuiceModule">EmfParsleyGuiceModule</abbr> |
| , |
| which can be used in a standard Eclipse OSGI environment. If you are using |
| CDO, it is better to use as base class <strong>CDOEmfParsleyModule</strong>, which has defaults |
| that better fit a CDO environment. If you do not need OSGI, you can use |
| <abbr title="org.eclipse.emf.parsley.EmfParsleyJavaGuiceModule">EmfParsleyJavaGuiceModule</abbr> |
| (e.g., to run tests |
| with plain Junit, see also <a href="#addref" rel="Testing Framework">Testing Framework</a>). |
| </p> |
| <p> |
| The most common kind of method is |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public Class<? extends ILabelProvider> bindILabelProvider() { |
| return MyLabelProvider.class; |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| which would do the same as the code snippet above. |
| It simply declares a binding from ILabelProvider to MyLabelProvider. |
| That binding will make Guice instantiate and inject a new instance of |
| MyLabelProviderProvider whenever a dependency to ILabelProvider is declared. |
| </p> |
| <p> |
| There are two additional kinds of binding-methods supported. |
| The first one allows to configure a provider. |
| A <abbr title="com.google.inject.Provider">Provider</abbr> |
| is an interface with just one method: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public interface Provider<T> extends javax.inject.Provider<T> { |
| |
| /** |
| * Provides an instance of {@code T}. Must never return {@code null}. |
| */ |
| T get(); |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| This one can be used if you need a hook whenever an instance of a certain type |
| is created. For instance if you want to provide lazy access to a singleton |
| or you need to do some computation each time an instance is created (i.e. factory). |
| If you want to point to a provider rather than to a concrete class you can |
| use the following binding method: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public Class<? extends Provider<ILabelProvider>> provideILabelProvider() { |
| return MyLabelProviderFactory.class; |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The last kind of binding allows to inject values in Parsley components; |
| here are some examples of such bindings implemented in the base class of |
| Parsley Guice module: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| /** |
| * The String constant for Content Assist Shortcut |
| */ |
| public String valueContentAssistShortcut() { |
| return "Ctrl+Space"; |
| } |
| |
| /** |
| * The String constant used as a ellipses for Iterable string representation |
| * when it is too long |
| */ |
| public String valueIterableStringEllipses() { |
| return "..."; |
| } |
| |
| /** |
| * The list of Integer weights for a table's columns |
| */ |
| public List<Integer> valueTableColumnWeights() { |
| return Collections.<Integer>emptyList(); |
| } |
| |
| /** |
| * The int constant defining the Sash style in a TreeFormComposite |
| */ |
| public int valueTreeFormSashStyle() { |
| return SWT.VERTICAL; |
| } |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Specify Guice Bindings in the DSL<a id="BindingsInTheDSL"></a></h3> |
| <p> |
| Guice bindings can be specified directly in the DSL, in the |
| <strong>bindings</strong> section. |
| </p> |
| <p> |
| In this section you can specify bindings of all the three above kinds with |
| <strong>type</strong>, <strong>provide</strong> and <strong>value</strong> respectively, e.g., |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| bindings { |
| type ILabelProvider -> MyLabelProvider |
| type ... -> ... |
| provide ProposalCreator -> MyProposalCreatorProvider |
| ... |
| value int TreeFormSashStyle -> SWT.HORIZONTAL |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| We strongly suggest you use the content assist to discover default |
| bindings, since they also show Javadoc for each default binding: |
| </p> |
| <p> |
| </p> |
| <img src="images/first-example-custom-binding1.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| </div> |
| </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 Jface Label Prorvider 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 want to customize the label provider in Java, you need to provide an 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 a base implementation with the class <abbr title="org.eclipse.emf.parsley.ui.provider.ViewerLabelProvider">ViewerLabelProvider</abbr> |
| |
| that is meant to be subclassed by the programmer to provide specific implementations like in the example below. |
| </p> |
| <p> |
| This class, like many others in our framework, relies on the <strong>polymorphic dispatcher</strong> idiom to declaratively |
| specify text and image representations for objects. It boils down to the fact that the only thing you need to do is |
| to implement a method that matches a specific signature: <strong>text</strong> and <strong>image</strong> for the String representation and |
| the image, respectively. These methods will need to specify as parameter the type of the object to represent. |
| For the image, you can either specify an image filename or an Image object. File names for images are |
| assumed to refer to files in the <strong>icons</strong> folder of the containing plug-in. |
| </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 in a tree and 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 a base 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 (again, this uses the polymorphic dispatch idiom). |
| </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 this kind of provider wherever a list of features 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 in 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 you want to customize it in Java, there are more ways 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> |
| <p> |
| If there are no specific customization in the <abbr title="org.eclipse.emf.parsley.ui.provider.TableFeaturesProvider">TableFeaturesProvider</abbr> |
| , |
| we fall back to <abbr title="org.eclipse.emf.parsley.ui.provider.FeaturesProvider">FeaturesProvider</abbr> |
| . |
| </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> |
| </p> |
| <p> |
| If you want to customize it in Java, you need to derive from |
| <abbr title="org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider">FeatureCaptionProvider</abbr> |
| . |
| It can be customized, with injection <strong>TODO (see Injection paragraph)</strong>, to customize the caption label on the |
| left of each control in a form and the headers in a table's column. |
| The framework uses a polimorphic mechanism to find customizations: it searches for |
| methods with a specific signature: the name is built by the string <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 (that is automatically |
| passed by the framework). |
| </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> |
| <p> |
| If there is no customization in the <abbr title="org.eclipse.emf.parsley.ui.provider.FormFeatureCaptionProvider">FormFeatureCaptionProvider</abbr> |
| |
| we fall back to <abbr title="org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider">FeatureCaptionProvider</abbr> |
| . |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Proposal Provider<a id="ProposalProvider"></a></h3> |
| <p> |
| Some controls use a list of proposals to help the end user experince: for example a single value reference feature |
| will be rendered by default with a combo box, automatically filled with all the possible targets for |
| that reference; similarly for Enum features. You can customize the proposals, and you can specify proposals also |
| for simple text fields (a content assist dialog will show up for text fields). |
| </p> |
| <p> |
| For each feature you can specify a list of proposals via the DSL. In the example below, we first |
| compute the default proposals for that feature and then we filter the proposals. |
| </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.composite.ProposalCreator">ProposalCreator</abbr> |
| |
| and implementing the method </p> |
| <pre class="prettyprint" skin="desert">public List<?> proposals_Book_author(Book book) {...}</pre> |
| <p> |
| . This |
| method follows the same convention on the signature name as explained in <a href="#FeatureCaptionProvider">Feature |
| Provider</a>. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Contextual Menu</h2> |
| <p> |
| A context menu can be added to any viewer by using the <abbr title="org.eclipse.emf.parsley.menus.ViewerContextMenuHelper">ViewerContextMenuHelper</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> |
| <p> |
| The contents of such menu are built automatically by the framework or customized by the programmer, |
| as shown in the next section. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Menu Builder<a id="MenuBuilder"></a></h3> |
| <p> |
| <strong>EMF Parsley</strong> uses the standard EMF.Edit features to build the contextual menus of |
| viewers (thus you will get by default the standard "New Child" and "New Sibling" |
| sections in the context menu). |
| </p> |
| <p> |
| You can customize context menus on a per class basis |
| by extending the <abbr title="org.eclipse.emf.parsley.edit.action.EditingMenuBuilder">EditingMenuBuilder</abbr> |
| |
| (and injecting it in the Guice module). However, we suggest to use the |
| DSL for this task, as detailed in the following. |
| </p> |
| <p> |
| <strong>EMF Parsley</strong> logically separates 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 contains 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 lib -> #[ |
| actionAdd("Add a new book", lib.books, |
| EXTLibraryFactory.eINSTANCE.createBook) |
| ] |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| For each EClass of your meta-model you can specify a list of menu items |
| (the #[] is the Xbase syntax for a list literal) |
| Content assist is available to select the editing actions, the separator and |
| also methods for EMF menu part. In the <strong>emfMenus</strong> section, you can use |
| the method <strong>actionAdd</strong>, specifying the label for the menu, |
| the containment list in the model, and the object to add in such list |
| when the menu is selected (Note that it is up to you to specify a |
| containment list); the DSL will issue an error if the object cannot be |
| added to the list (because it is not of the right type). |
| The object should be created using the standard EMF API (i.e., using |
| the EMF factory for your model). |
| </p> |
| <p> |
| IMPORTANT: do not initialize any reference feature of the created EObject |
| upon object creation; i.e., do not do something like the following |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| emfMenus{ |
| Writer w -> #[ |
| actionAdd("Add a new book for the writer", |
| (w.eContainer as Library).books, |
| // WRONG: don't do that |
| EXTLibraryFactory.eINSTANCE.createBook => [ |
| author = w |
| ] |
| ) |
| ] |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Since the object is created when the contextual menu is created, NOT |
| when the menu is selected; if you do something like in the code above, |
| you will end up with a resource with dangling references (which cannot be |
| saved). |
| </p> |
| <p> |
| If you want to specify further initialization instructions for the |
| created object you can pass a lambda expression as another argument |
| to <strong>actionAdd</strong>: that lambda will be executed ONLY after the menu |
| has been selected, i.e., ONLY after the created |
| object is part of the resource: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| emfMenus{ |
| Writer w -> #[ |
| actionAdd("Add a new book for the writer", |
| (w.eContainer as Library).books, |
| EXTLibraryFactory.eINSTANCE.createBook, |
| // CORRECT: the lambda will be executed when the menu |
| // is selected and the object has been added to |
| // the resource |
| [ book | book.author = w ] |
| ) |
| ] |
| } |
| </pre> |
| <p> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Factories</h2> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Widget Factory<a id="WidgetFactory"></a></h3> |
| <p> |
| The actual creation of text field, buttons, labels, etc. is delegated to an |
| implementation of <abbr title="org.eclipse.emf.parsley.widgets.IWidgetFactory">IWidgetFactory</abbr> |
| , which has several methods |
| like <strong>createText</strong>, <strong>createLabel</strong>, etc. We provide two implementations of such interface |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><abbr title="org.eclipse.emf.parsley.widgets.DialogWidgetFactory">DialogWidgetFactory</abbr></li> |
| <li><abbr title="org.eclipse.emf.parsley.widgets.FormWidgetFactory">FormWidgetFactory</abbr> |
| which is a specialization of the above, |
| specific for forms.</li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| Usually, you do not need to customize such factories, which are used internally by the framework, |
| like in <a href="#FormControlFactory"></a> and <a href="#DialogControFactory"></a>. |
| </p> |
| <p> |
| You may want to customize such factories in case all your controls must have a specific style; |
| in such case, just inherit from our base classes |
| (there is no DSL section for such customizations, since they can be made in plain Java easily) |
| and bind such custom implementations in the Guice module. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Form Control Factory<a id="FormControlFactory"></a></h3> |
| <p> |
| <strong>EMF Parsley</strong> lets 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> |
| </p> |
| <p> |
| For each pair EClass, EStructuralFeature you can either simply return a Control or specify also the target |
| for the databinding (see some examples above). |
| |
| If you want to customize the controls in Java, you can extend the class <abbr title="org.eclipse.emf.parsley.composite.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. The method |
| must accept as parameters 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> |
| <p> |
| This customization is exactly as in the case of the form of the previous section. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Resources</h2> |
| <p> |
| </p> |
| <ul> |
| <li>If you need a machanism to fill some data for the first time you use a model, you can provide |
| a specific implementation of <a href="#ResourceManager">Resource Manager</a>.</li> |
| <li>If you want to interact with Resource Loading, you can provide a specific <a href="#ResourceLoader">Resource |
| Loader</a></li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| Concerning saving objects, there are some specific parts that can be customized: |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><a href="#ResourceSaveStrategy">Resource Save Strategy</a>, if you want to manage the save.</li> |
| </ul> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Resource Loader<a id="ResourceLoader"></a></h3> |
| <p> |
| The class <abbr title="org.eclipse.emf.parsley.resource.ResourceLoader">ResourceLoader</abbr> |
| can be used to handle resource loading. |
| This class uses internally the <a href="#ResourceManager">Resource Manager</a>. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Resource Manager<a id="ResourceManager"></a></h3> |
| <p> |
| Tasks concerning an EMF <abbr title="org.eclipse.emf.ecore.resource.Resource">Resource</abbr> |
| are |
| delegated to <abbr title="org.eclipse.emf.parsley.resource.ResourceManager">ResourceManager</abbr> |
| . |
| </p> |
| <p> |
| One of such tasks is initializing the resource, e.g., when, after loading, it is |
| found empty. You can derive from this class (and bind it in the Guice module) and provide a custom implementation |
| of the method <strong>initialize</strong>. |
| </p> |
| <p> |
| Saving a resource is also delegated to this class, using the method <strong>save</strong>, |
| which is expected to return a boolean value representing whether saving |
| has succeeded (the default implementation simply saves the resource and returns true). |
| </p> |
| <p> |
| In the DSL, you can specify a <strong>resourceManager</strong> block, and within that block |
| you can specify <strong>initializeResource</strong> and <strong>saveResource</strong>, which correspond to |
| <strong>inizialize</strong> and <strong>save</strong> methods, respectively. In both cases, inside the |
| block expression, the resource is available with the name <strong>it</strong>; for example |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| import org.eclipse.emf.parsley.examples.library.EXTLibraryFactory |
| |
| ... |
| |
| resourceManager { |
| val EXTLibraryFactory libraryFactory = EXTLibraryFactory.eINSTANCE; |
| |
| initializeResource { |
| // it is of type org.eclipse.emf.ecore.resource.Resource |
| it.getContents() += libraryFactory.createLibrary |
| } |
| saveResource { |
| // it is of type org.eclipse.emf.ecore.resource.Resource |
| it.save(null) |
| return true |
| } |
| } |
| |
| ... |
| </pre> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Resource Save Strategy<a id="ResourceSaveStrategy"></a></h3> |
| <p> |
| Resource saving is delegated to <abbr title="org.eclipse.emf.parsley.resource.ResourceSaveStrategy">ResourceSaveStrategy</abbr> |
| |
| which, by defaults only saves the passed <abbr title="org.eclipse.emf.ecore.resource.Resource">Resource</abbr> |
| , |
| by delegating to <abbr title="org.eclipse.emf.parsley.resource.ResourceManager">ResourceManager</abbr> |
| |
| (see <a href="#ResourceManager"></a>). |
| You can inject your own save strategy and customize the saving strategy, for |
| instance, you may want to validate the resource before saving |
| (a usable example of this strategy is |
| <abbr title="org.eclipse.emf.parsley.resource.ValidateBeforeSaveStrategy">ValidateBeforeSaveStrategy</abbr> |
| , |
| see also section <a href="#addref" rel="Validation">Validation</a>). |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Configurator</h2> |
| <p> |
| In Parsley, instead of using abstract classes, we often provide concrete |
| classes that implement superclass' abstract methods (or interface methods) |
| by delegating to an injected <abbr title="org.eclipse.emf.parsley.config.Configurator">Configurator</abbr> |
| . |
| Such configurator calls methods in its hierarchy using polymorphic dispatch; |
| in particular, the first argument passed to these methods is the object |
| requesting that specific service to the configurator; typically it will be |
| a UI object, e.g., a view part. |
| </p> |
| <p> |
| These are the methods that can be customized declaratively: |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| /** |
| * Returns the {@link URI} of the resource for the requestor for any use the requestor may need it |
| * @param requestor |
| * @return |
| */ |
| public URI resourceURI(Object requestor) { |
| return null; |
| } |
| |
| /** |
| * Returns the {@link EClass} for the requestor |
| * @param requestor |
| * @return |
| */ |
| public EClass eClass(Object requestor) { |
| return null; |
| } |
| |
| /** |
| * Returns the {@link EStructuralFeature} for the requestor |
| * @param requestor |
| * @return |
| */ |
| public EStructuralFeature eStructuralFeature(Object requestor) { |
| return null; |
| } |
| |
| /** |
| * Returns the contents from the resource for the requestor |
| * @param requestor |
| * @param resource |
| * @return |
| */ |
| public Object contents(Object requestor, Resource resource) { |
| return null; |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The idea is that clients that use such an injected instance should call |
| the <strong>get</strong> methods, e.g., <strong>getContents</strong>, while the customization should be defined |
| using polymorphic dispatch, e.g., |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| class MyConfigurator extends Configurator { |
| |
| public Object contents(MyView1 view1, Resource resource) { |
| return ...; |
| } |
| |
| public Object contents(MyOtherView view, Resource resource) { |
| return ...; |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| In the DSL, you can specify a <strong>configurator</strong> section, e.g., |
| (the requestor object can be accessed using the implicit variable |
| <strong>it</strong>, while additional parameters can be accessed through their names, |
| as named in the original <abbr title="org.eclipse.emf.parsley.config.Configurator">Configurator</abbr> |
| |
| class, e.g., <strong>resource</strong> for <strong>contents</strong>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| module my.project { |
| |
| configurator { |
| resourceURI { |
| MyTreeFormView -> { |
| return ...; |
| } |
| } |
| eClass { |
| MyTreeView -> { |
| return ...; |
| } |
| } |
| eStructuralFeature { |
| MyTreeFormView -> { |
| return ...; |
| } |
| MyFormView -> { |
| return ...; |
| } |
| } |
| contents { |
| MyTreeView -> { |
| return ...; |
| } |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The project wizard will generate in the <strong>module.parsley</strong> the |
| required <strong>configurator</strong> sections, depending on the specific template chosen, |
| with some <strong>// TODO</strong> comments to help implementing them, e.g., |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint lang-parsley" skin="desert"> |
| module my.project { |
| |
| configurator { |
| contents { |
| MyView -> { |
| // TODO return the contents from the resource |
| // e.g., resource.^contents.get(0) |
| } |
| } |
| eClass { |
| MyView -> { |
| // TODO return the EClass to represent |
| } |
| } |
| resourceURI { |
| MyView -> { |
| // TODO create and return a org.eclipse.emf.common.util.URI |
| return null; |
| } |
| } |
| eStructuralFeature { |
| MyView -> { |
| // TODO return the EStructuralFeature to get the elements to represent |
| } |
| } |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Validation</h2> |
| <p> |
| EMF Parsley supports standard EMF validation automatically, e.g., via the context menu |
| "Validate"; thus, if you already have constraints implemented for your meta-model, the |
| validation action will check them. |
| </p> |
| <p> |
| EMF validation can also be triggered manually using an injected <abbr title="org.eclipse.emf.parsley.validation.ValidationRunner">ValidationRunner</abbr> |
| , |
| which provides methods for validating a single <abbr title="org.eclipse.emf.ecore.EObject">EObject</abbr> |
| or an entire |
| <abbr title="org.eclipse.emf.ecore.resource.Resource">Resource</abbr> |
| . These <strong>validate</strong> methods return an EMF |
| <abbr title="org.eclipse.emf.common.util.Diagnostic">Diagnostic</abbr> |
| that can be used to find out possible errors, warnings |
| and infos collected during the validation. |
| </p> |
| <p> |
| There are overloaded versions of <strong>validate</strong> methods that also take an |
| <abbr title="org.eclipse.emf.parsley.validation.IssueReporter">IssueReporter</abbr> |
| : |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| /** |
| * Validates, reports diagnostics through the passed {@link IssueReporter} |
| * and returns the list of reported diagnostics. |
| * |
| * @param eObject |
| * @param reporter |
| * @return |
| */ |
| public List<Diagnostic> validate(EObject eObject, IssueReporter reporter) { |
| return reporter.report(validate(eObject)); |
| } |
| |
| /** |
| * Validates, reports diagnostics through the passed {@link IssueReporter} |
| * and returns the list of reported diagnostics. |
| * |
| * @param resource |
| * @param reporter |
| * @return |
| */ |
| public List<Diagnostic> validate(Resource resource, IssueReporter reporter) { |
| return reporter.report(validate(resource)); |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| The reporter is asked to report the collected diagnostic and it is expected to return |
| the list of issues effectively reported. For example, an issue reporter can |
| report only errors (e.g., diagnostic whose severity is <strong>Diagnostic.ERROR</strong>), while |
| ignoring warnings and other diagnostic information. |
| </p> |
| <p> |
| We provide a utility class that can be injected, <abbr title="org.eclipse.emf.parsley.validation.DiagnosticUtil">DiagnosticUtil</abbr> |
| , |
| with utility methods, like flattening diagnostic into a list (EMF diagnostic are typically nested in |
| a tree form), to quickly select only the errors, and to have a string representation. |
| </p> |
| <p> |
| The default implementation of <abbr title="org.eclipse.emf.parsley.validation.IssueReporter">IssueReporter</abbr> |
| |
| is <abbr title="org.eclipse.emf.parsley.validation.DialogErrorReporter">DialogErrorReporter</abbr> |
| , which uses an EMF |
| dialog to report ONLY errors. Another implementation that can be used for testing purposes |
| is <abbr title="org.eclipse.emf.parsley.validation.LogIssueReporter">LogIssueReporter</abbr> |
| , which logs diagnostic using |
| the corresponding log4j methods (i.e., <strong>error</strong>, <strong>warn</strong>, <strong>info</strong>). |
| </p> |
| <p> |
| An example of use of the above classes can be found in <abbr title="org.eclipse.emf.parsley.resource.ValidateBeforeSaveStrategy">ValidateBeforeSaveStrategy</abbr> |
| |
| (see section <a href="#ResourceSaveStrategy">Resource Save Strategy</a>): |
| </p> |
| <p> |
| </p> |
| <pre class="prettyprint" skin="desert"> |
| public class ValidateBeforeSaveStrategy extends ResourceSaveStrategy { |
| |
| @Inject |
| private ValidationRunner validationRunner; |
| |
| @Inject |
| private IssueReporter issueReporter; |
| |
| @Override |
| public boolean save(Resource resource) throws IOException { |
| if (!precondition(resource)) { |
| return false; |
| } |
| return super.save(resource); |
| } |
| |
| protected boolean precondition(Resource resource) { |
| return validationRunner.validate(resource, issueReporter).size() == 0; |
| } |
| } |
| </pre> |
| <p> |
| </p> |
| <p> |
| Thus, if you use a <abbr title="org.eclipse.emf.parsley.resource.ValidateBeforeSaveStrategy">ValidateBeforeSaveStrategy</abbr> |
| , |
| with the default Guice bindings, upon saving, if validation finds errors, it will |
| cancel the saving and it will show a dialog with errors. |
| </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">Advanced Features</h1> |
| <p> |
| In this chapter we describe some advanced features. |
| </p> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Testing Framework</h2> |
| <p> |
| We provide some utility classes for testing <strong>EMF Parsley</strong> components in the feature |
| "Emf Parsley Junit4 Support". By deriving from one of the abstract classes in our |
| testing bundle, you will be able to write tests that are meant to be run as Junit test, |
| that is to say, NOT as Plug-in Junit tests. Thus, you will not need a running Eclipse product |
| to execute such tests: they will be much faster. Indeed, many parts of Parsley can |
| be tested even without a running Eclipse. |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li><abbr title="org.eclipse.emf.parsley.junit4.AbstractEmfParsleyTest">AbstractEmfParsleyTest</abbr> |
| : this provides |
| a few utility methods, e.g., for creating an <abbr title="com.google.inject.Injector">Injector</abbr> |
| .</li> |
| <li><abbr title="org.eclipse.emf.parsley.junit4.AbstractEmfParsleyShellBasedTest">AbstractEmfParsleyShellBasedTest</abbr> |
| : this allows |
| to run Junit tests that require a <abbr title="org.eclipse.swt.widgets.Display">Display</abbr> |
| and a |
| <abbr title="org.eclipse.swt.widgets.Shell">Shell</abbr> |
| .</li> |
| <li><abbr title="org.eclipse.emf.parsley.junit4.AbstractEmfParsleyControlBasedTest">AbstractEmfParsleyControlBasedTest</abbr> |
| : an extension |
| of the previous class for tests that also require databinding capabilities, e.g., |
| tests for <abbr title="org.eclipse.swt.widgets.Control">Control</abbr> |
| elements; this provides many assert |
| methods for several kinds of controls, such as <strong>assertCheckbox</strong>, <strong>assertCombo</strong>, etc.</li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| We use these classes for testing most of our classes; you might want to have a look |
| at the project <strong>org.eclipse.emf.parsley.tests</strong> for some usage examples. |
| </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">RAP</h1> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Introduction</h2> |
| <p> |
| As you may know <a href="http://eclipse.org/rap/">RAP (Remote Application Platform)</a> is a technology that allows you to run an Eclipse RCP application over the web. |
| </p> |
| <p> |
| In order to obtain this goal you have to setup a specific RAP Target Platform, for instance the one that RAP itself provides once you install it. |
| </p> |
| <p> |
| However when you want to use an Eclipse RCP framework over the RAP Platform, you generally have to deal with |
| dependencies, since not all Eclipse frameworks are ready-to-use with RAP, especially those related with the SWT layer. |
| </p> |
| <p> |
| EMF Parsley provides a proper RAP Target Platform that allows you to start leveraging Parsley potentials to the web the same way you have |
| learned to do with desktop (RCP) development. |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Setup</h2> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Installing the RAP Tools<a id="installRapTools"></a></h3> |
| <p> |
| To begin with, you need to install the RAP Tools into the IDE. |
| This can be accomplished with the following steps: |
| </p> |
| <ol> |
| <li>Help -> Install New Software ...</li> |
| <li>select the main Eclipse Update site (e.g. <strong>"http://download.eclipse.org/releases/luna"</strong>)</li> |
| <li>expand category "Web, XML, Java EE and OSGi Enterprise Development"</li> |
| <li>select "RAP Tools" and complete the installation, restarting the IDE at the end</li> |
| <li>after IDE restarts just close the Welcome page</li> |
| </ol> |
| <p> |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Setup the EMF Parsley RAP Target Platform<a id="rapSetTargetPlatform"></a></h3> |
| <p> |
| After having installed EMF Parsley as described <a href="https://www.eclipse.org/emf-parsley/download.html">here</a> and |
| created a new workspace, you can setup the EMF Parsley RAP Target Platform in the following way: |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Emf Parsley Examples", select "Emf Parsley Rap Target Platform Example"</li> |
| <li>press Next and Finish</li> |
| <li>open the Target Definition file <strong>emf-parsely-rap-2.3.target</strong></li> |
| <li>wait until the "Resolving Target Definition" job is done (check the status bar)</li> |
| <li>when finished, click on hyperlink "Set as Target Platform"</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| You will end up with a RAP-enabled workspace, enhanced by EMF and Parsley! |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">Examples</h2> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Running the Parsley RAP UI Example<a id="rapFirstExample"></a></h3> |
| <p> |
| Here is the fastest way to get a working web application with all the stuff put togheter: |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Emf Parsley Examples", select "Emf Parsley Rap Example"</li> |
| <li>press Next and Finish</li> |
| <li>expand plug-in <strong>"org.eclipse.emf.parsley.examples.rap.ui"</strong></li> |
| <li>right-click "Emf_Parsley_RAP_UI_Example.launch" and click "Run as" "Emf_Parsley_RAP_UI_Example"</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| What you will get is a web application that allows you to interact with the model instance as you would |
| do in a desktop (RCP) environment. |
| </p> |
| <p> |
| </p> |
| <img src="images/08-rap-ui-example-running.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| In this web application you can see two views: |
| </p> |
| <ul> |
| <li>the one on the left is a read-only view; it just reflects the model content, but it does not react to changes (the classic Eclipse dirty indicator is not triggered |
| by changes) and you are not able to save. Its model is created in class <strong>org.eclipse.emf.parsley.examples.rap.ui.GuiceModule.CustomEmptyResourceInitializer</strong> |
| and is not persisted</li> |
| <li>the view on the right is instead a Saveable view and therefore it not only triggers the dirty state after |
| a change, but also allows you to save the modifications with the automatic dirty state reset. Its model |
| is persisted in file <strong>System.getProperty("java.io.tmpdir")+"/My.model")</strong></li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| Of course, since this is a web application, you can also open a browser on another pc or device on the same network and type the address, |
| replacing 127.0.0.1 with the IP of the machine where the application was launched. |
| </p> |
| </br> |
| <h3 class="featurette-heading text-parsley2">Running the Parsley RAP CDO Example<a id="rapCdoExample"></a></h3> |
| <p> |
| The EMF default XMI persistence is certainly very handy to start with, but as soon as you want a more |
| production-ready EMF persistence architecture, well, <a href="http://wiki.eclipse.org/CDO">CDO</a> is for sure the way to go. |
| In fact with CDO you basically have an EMF model instance shared between clients, that also allows the |
| clients to be synchronized with the model changes. |
| </p> |
| <p> |
| In this example, in order to keep things simple, we will use CDO with an in-memory store (MEMStore) whose contents will be lost once the server is stopped. |
| However CDO can be configured for usage with RDBMS, Object-oriented or NO-SQL databases (see <a href="http://eclipse.org/cdo/documentation/">here</a> for details) |
| </p> |
| <p> |
| To start with we need a CDO Server running and we can obtain it with an example plugin that can be used |
| both in an RCP and in a RAP workspace. |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Emf Parsley Examples", select "Emf Parsley Cdo Server Example"</li> |
| <li>press Next and Finish</li> |
| <li>expand plug-in <strong>"org.eclipse.emf.parsley.examples.cdo.server"</strong></li> |
| <li>right-click "CDOServerExample.launch" and click "Run as" "CDOServerExample"</li> |
| <li>a message on the Console <strong>"Repository[demo] started!"</strong> informs that the CDO Server instance |
| is started!</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| Now we can create the web application that will use the CDO server just started. |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>File -> New... -> Example...</li> |
| <li>from Category "Emf Parsley Examples", select "Emf Parsley Rap Cdo Example"</li> |
| <li>press Next and Finish</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| The plug-in projects created are: |
| </p> |
| <p> |
| </p> |
| <ul> |
| <li>the Model (org.eclipse.emf.parsley.examples.cdo.model)</li> |
| <li>a Parsley plug-in with a TreeForm (org.eclipse.emf.parsley.examples.cdo.treeform)</li> |
| <li>the webapp (org.eclipse.emf.parsley.examples.cdo.rap)</li> |
| </ul> |
| <p> |
| </p> |
| <p> |
| Then let's start the application |
| </p> |
| <p> |
| </p> |
| <ol> |
| <li>expand plug-in <strong>"org.eclipse.emf.parsley.examples.cdo.rap"</strong></li> |
| <li>right-click "EMF-Parsley_Library_RAP.launch" and click "Run as" "EMF-Parsley_Library_RAP"</li> |
| </ol> |
| <p> |
| </p> |
| <p> |
| If you happen to see this |
| </p> |
| <p> |
| </p> |
| <img src="images/08-rap-refresh.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| just press the refresh button and should see the following |
| </p> |
| <p> |
| </p> |
| <img src="images/08-rap-cdo-1.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <p> |
| </p> |
| <p> |
| Now feel free to open the same address from more browsers window (yes, on different machines or devices, possibly) |
| and see the power of this technology stack at work! |
| </p> |
| <p> |
| </p> |
| <img src="images/08-rap-cdo-2.png" class="img-responsive centered" style="margin-top:10px;margin-bottom:10px;"> |
| <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> |
| <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">Migration Guide</h1> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">From 0.4 to 0.5</h2> |
| <p> |
| </p> |
| <ul> |
| <li>the packages <strong>factories</strong> and <strong>builders</strong> have been removed |
| and their classes have been moved to other packages. |
| If you get compiler errors, a simple "Organize Imports" should fix |
| the imports. If you use the DSL a simple regeneration should fix things.</li> |
| <li><strong>IViewerMouseListener</strong> has been moved from the <strong>listeners</strong> |
| package to the <strong>viewers</strong> package.</li> |
| <li>classes in <strong>editor.outline</strong> have been moved into <strong>editors</strong> |
| package.</li> |
| </ul> |
| <p> |
| </p> |
| </div> |
| </br> |
| <div > |
| <h2 id="par" class="featurette-heading text-parsley1">From 0.3 to 0.4</h2> |
| <p> |
| </p> |
| <ul> |
| <li><strong>EmptyResourceInitializer</strong> has been removed: you should now use |
| <abbr title="org.eclipse.emf.parsley.resource.ResourceManager">ResourceManager</abbr> |
| , |
| see section <a href="#ResourceManager">Resource Manager</a></li> |
| <li><strong>ResourceSaveManager</strong> has been removed: you should now use |
| <abbr title="org.eclipse.emf.parsley.resource.ResourceSaveStrategy">ResourceSaveStrategy</abbr> |
| , |
| see section <a href="#ResourceSaveStrategy">Resource Save Strategy</a></li> |
| <li>Project wizards have been redesigned: they generate a <strong>module.parsley</strong> |
| that uses the <strong>configurator</strong> for specifying required information |
| (see section <a href="#addref" rel="Configurator">Configurator</a> and the updated |
| first example, section <a href="#addref" rel="First Example">First Example</a>)</li> |
| </ul> |
| <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.3%;"> |
| <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 4% 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'); |
| }); |
| |
| $('.scrollup').mouseover(function() { |
| $('a.scrollup').css('opacity', '1'); |
| }); |
| $('.scrollup').mouseout(function() { |
| $('a.scrollup').css('opacity', '0.35'); |
| }); |
| |
| //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).scroll(function() { |
| var y = $(this).scrollTop(); |
| if (y < 800) |
| $('a.scrollup').fadeOut(); |
| else |
| $('a.scrollup').fadeIn(); |
| }); |
| //prevscroll |
| var prevscroll = 0; |
| $(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"); |
| } |
| }); |
| //inizio prevscroll |
| //Gestione scroll del menu laterale in base alla posizione della pagina |
| var menuScrollSize = '-250px'; |
| var pageScrollThreshold = 16730; |
| if($(window).height()<$(".dropdown-menu").height()+190){ |
| if(prevscroll<scrollposition){ |
| if(scrollposition>pageScrollThreshold) |
| $(".dropdown-menu").css('top', menuScrollSize); |
| } else |
| $(".dropdown-menu").css('top', '0px'); |
| prevscroll=scrollposition; |
| } else if($(".dropdown-menu").css('top')!=null && $(".dropdown-menu").css('top')==menuScrollSize){ |
| $(".dropdown-menu").css('top', '0px'); |
| } |
| //fine prevscroll |
| }); |
| |
| $(document).ready(function() { |
| //Setto link attivo nel menu |
| var mieili = $('.miomenu li'); |
| mieili.each(function(idx) { |
| var indirizzo = $(this).children().attr('href'); |
| if(indirizzo!=null && indirizzo.length>0 && (window.location.href.indexOf(indirizzo)>0 || (window.location.href=='http://www.eclipse.org/emf-parsley/' || window.location.href=='https://www.eclipse.org/emf-parsley/' && indirizzo.indexOf('index')>0))){ |
| $(this).addClass('mioactive'); |
| return false; |
| } |
| }); |
| //Setto link attivo nel footer |
| mieili = $('.miolifooter li'); |
| mieili.each(function(idx) { |
| var indirizzo = $(this).children().attr('href'); |
| if(indirizzo!=null && indirizzo.length>0 && (window.location.href.indexOf(indirizzo)>0 || (window.location.href=='http://www.eclipse.org/emf-parsley/' || window.location.href=='https://www.eclipse.org/emf-parsley/' && indirizzo.indexOf('index')>0))){ |
| $(this).children().addClass('mioactivefooter'); |
| return false; |
| } |
| }); |
| |
| //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|featuresProvider|features|formControlFactory|control|target|viewerContentProvider|children|viewpart|viewname|viewclass|viewcategory|for|new|switch|default|boolean|do|if|this|double|throw|null|true|false|it|as|byte|else|case|enum|instanceof|return|featureCaptionProvider|val|var|catch|extends|int|short|try|char|void|finally|long|float|super|while|proposals|dialogControlFactory|menuBuilder|menus|emfMenus|resourceManager|initializeResource|saveResource|configurator|resourceURI|eClass|eStructuralFeature|contents|bindings|type|provide|value', 'emfparsley'); |
| </script> |
| </body> |
| </html> |