| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" > |
| <title>Eclipse 4</title> |
| |
| <link href="book.css" rel="stylesheet" type="text/css"> |
| <link href="code.css" rel="stylesheet" type="text/css"> |
| <link rel="home" href="xtext.html" title=""> |
| </head> |
| <body> |
| <a name="Eclipse4"></a> |
| <h1>Eclipse 4</h1> |
| <p> |
| Instead of using the Extension Point mechanism, EMF Components leverages from DSL and Google Guice Injection. |
| </p> |
| <p> |
| Because of this, it is very easy to use it with Eclipse 4. |
| </p> |
| <a name="GetFirstExample"></a> |
| <h2>First Example Setup</h2> |
| <p> |
| If you followed the steps described in section <a href="02-GettingStarted.html#GettingStarted" title="Go to "Getting Started"">Getting Started</a> you will have already |
| what we need to begin. Otherwise the following wizard will bring you to that point. |
| </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> |
| You will end up with three plug-ins: |
| </p> |
| <p> |
| <ul> |
| <li> |
| org.eclipse.emf.parsley.examples.firstexample (the EMF Components 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> |
| As a reminder, in section <a href="02-GettingStarted.html#GettingStarted" title="Go to "Getting Started"">Getting Started</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> |
| <a name="PrepareForEclipse4Application"></a> |
| <h2>Preparing for a pure Eclipse 4 Application</h2> |
| <p> |
| What we will do now is starting from the previous step and create an Eclipse 4 Application (on top of |
| the previous plug-ins) that gets to the same result, but now with a pure Eclipse 4 Part. |
| </p> |
| <p> |
| In order to do this we need to export the <em>"org.eclipse.emf.parsley.examples.firstexample"</em> package from the first plug-in. |
| </p> |
| <a name="CreateEclipse4Application"></a> |
| <h2>Create an Eclipse 4 Application</h2> |
| <p> |
| Now let's create a new, empty, Eclipse 4 application, e.g. <em>"org.eclipse.emf.parsley.examples.firstexample.application"</em> |
| (you can find details on how to create Eclipse 4 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> |
| <a name="Eclipse4ApplicationAndEMFComponents"></a> |
| <h2>Using an EMF Parsley TreeComposite into an Eclipse 4 Part</h2> |
| <p> |
| In the just created plug-in we need dependencies from the previous plug-ins: so open the <em>org.eclipse.emf.parsley.examples.firstexample.application/MANIFEST.MF</em> file, go to <em>Dependencies</em> |
| tab and add the three previous plug-ins. Add also <em>"org.eclipse.emf.parsley"</em> 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: |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| <span class="comment">// Use these imports during Organizing Imports operation |
| <br/> |
| </span><span class="keyword">import</span> org.eclipse.emf.common.util.URI; |
| <br/> |
| <span class="keyword">import</span> org.eclipse.emf.ecore.resource.Resource; |
| <br/> |
| <span class="keyword">import</span> org.eclipse.swt.widgets.Composite; |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| <span class="comment">// The part implements IMenuListener for context menu handling |
| <br/> |
| </span>public class MyEclipse4Part implements IMenuListener |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| <span class="comment">//the parent composite |
| <br/> |
| </span>private Composite parent; |
| <br/> |
| <span class="comment">//the EMF Parley composite for showing a tree and a detail form |
| <br/> |
| </span>private TreeFormComposite treeFormComposite; |
| <br/> |
| <span class="comment">//the EMF Resource |
| <br/> |
| </span>private Resource resource; |
| <br/> |
| <span class="comment">//Guice injected EMF Parsley component for contributing to the tree context menu |
| <br/> |
| </span>private TreeActionBarContributor treeActionBarContributor = FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(TreeActionBarContributor.class); |
| <br/> |
| |
| <br/> |
| <span class="comment">//Guice injected EMF Parsley factory for the tree detail form |
| <br/> |
| </span>private TreeFormFactory treeFormFactory = FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(TreeFormFactory.class); |
| <br/> |
| <span class="comment">//Guice injected EMF Parsley Resource loader |
| <br/> |
| </span>private ResourceLoader resourceLoader = FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(ResourceLoader.class); |
| <br/> |
| <span class="comment">//Guice injected EMF Parsley editing domain |
| <br/> |
| </span>private AdapterFactoryEditingDomain editingDomain = FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(AdapterFactoryEditingDomain.class); |
| <br/> |
| <span class="comment">//Guice injected viewer initializer |
| <br/> |
| </span>private ViewerInitializer viewerInitializer = (ViewerInitializer) FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(ViewerInitializer.class); |
| <br/> |
| <span class="comment">//Guice injected save manager |
| <br/> |
| </span>private ResourceSaveManager resourceSaveManager = FirstexampleActivator.getDefault().getInjector() |
| <br/> |
| .getInstance(ResourceSaveManager.class); |
| <br/> |
| <span class="comment">//URI for EMF Resource |
| <br/> |
| </span>private URI uri = URI.createFileURI(System.getProperty(<span class="string">"user.home"</span>) |
| <br/> |
| + <span class="string">"/MyLibrary.library"</span>); |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| Modify the <em>@PostConstruct</em> method with this code: |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| @PostConstruct |
| <br/> |
| public void postConstruct(Composite parent) { |
| <br/> |
| this.parent = parent; |
| <br/> |
| <span class="comment">// Initialize TreeFormFactory & ResourceLoader |
| <br/> |
| </span> init(treeFormFactory, resourceLoader); |
| <br/> |
| <span class="comment">// Prepare the menu action bar contributor upon the selection |
| <br/> |
| </span> treeFormComposite.getViewer().addSelectionChangedListener(treeActionBarContributor); |
| <br/> |
| } |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| and add the following methods: |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| public void init(TreeFormFactory treeFormFactory, ResourceLoader resourceLoader) { |
| <br/> |
| <span class="comment">//create the tree-form composite |
| <br/> |
| </span> treeFormComposite = treeFormFactory.createTreeFormMasterDetailComposite(parent, SWT.BORDER); |
| <br/> |
| <span class="comment">//load the resource |
| <br/> |
| </span> resource = resourceLoader.getResource(editingDomain, uri).getResource(); |
| <br/> |
| <span class="comment">//update the composite |
| <br/> |
| </span> treeFormComposite.update(resource); |
| <br/> |
| <span class="comment">//initialize and bind the context menu to the tree-form composite |
| <br/> |
| </span> treeActionBarContributor.initialize(editingDomain); |
| <br/> |
| viewerInitializer.addContextMenu( |
| <br/> |
| treeFormComposite.getViewer(), treeActionBarContributor, editingDomain, this); |
| <br/> |
| } |
| <br/> |
| @Override |
| <br/> |
| public void menuAboutToShow(IMenuManager manager) { |
| <br/> |
| treeActionBarContributor.menuAboutToShow(manager); |
| <br/> |
| } |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| If you now run the application you will be able to manage the model: |
| </p> |
| <p> |
| <div class="image" > |
| <img src="images/07-eclipse4-part.png" class=" " |
| /> |
| <div class="caption"> |
| </div> |
| </div> |
| </p> |
| <p> |
| but you will notice that it is not possible to persist the changes to the model. |
| </p> |
| <a name="Eclipse4Save"></a> |
| <h2>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> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| @Inject |
| <br/> |
| MDirtyable dirtyable; |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| initialize it in the <em>@PostConstruct</em> method |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| @PostConstruct |
| <br/> |
| public void postConstruct(Composite parent, MDirtyable dirtyable) { |
| <br/> |
| this.dirtyable = dirtyable; |
| <br/> |
| this.dirtyable.setDirty(false); |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| add to <em>init</em> method the following code in order to update the dirty state |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| editingDomain.getCommandStack().addCommandStackListener( |
| <br/> |
| new CommandStackListener() { |
| <br/> |
| public void commandStackChanged(EventObject event) { |
| <br/> |
| if (dirtyable != null) |
| <br/> |
| dirtyable.setDirty(true); |
| <br/> |
| } |
| <br/> |
| }); |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| and add the <em>@Persist</em> method, which will be called when the part is saved |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| @Persist |
| <br/> |
| public void save(MDirtyable dirty) throws IOException { |
| <br/> |
| if (resourceSaveManager.save(resource)) { |
| <br/> |
| if (dirty != null) { |
| <br/> |
| dirty.setDirty(false); |
| <br/> |
| } |
| <br/> |
| } |
| <br/> |
| } |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| <p> |
| and, in the end, add the <em>Save</em> handler along with the correspondent <em>Command</em> and <em>Menu</em> |
| (you can find how to create handlers, commands and menus in an Eclipse 4 applications in <a href="http://www.rcp-vision.com/?p=4972&lang=en">our |
| tutorials</a>) |
| </p> |
| <p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"> |
| public class SaveHandler { |
| <br/> |
| @Execute |
| <br/> |
| void execute(EPartService partService, @Named(IServiceConstants.ACTIVE_PART) MPart part) { |
| <br/> |
| partService.savePart(part, false); |
| <br/> |
| } |
| <br/> |
| } |
| <br/> |
| </p> |
| </div> |
| </div> |
| </p> |
| </body> |
| </html> |