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