Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Graphical Modeling Framework/Tutorial/Part 3
GMF |
Website |
Download |
Dev Builds |
Update Site releases milestones |
Community |
Mailing List • Newsgroup • IRC |
Bugzilla |
Open |
Help Wanted |
Bug Day |
Source |
GMF Notation: View CVS repo GMF Runtime: View CVS repo |
Advanced customization
This third part is dedicated to customization that you cannot make using the generation models. This is where you'll have to code to customize your process. But don't worry, GMF Runtime provides a lot of stuff to make it easier. The complete solution to this tutorial is maintained in CVS here. Viewlets will be available after appropriate sections below to focus their content and keep them short.
Creating a Customization Plug-in
Although making modifications to the generated code and specifying '@generated NOT' to allow JMerge to preserve our changes works well for some customizations, it's also possible to separate other customizations (extensions) to our generated plug-in using a new plug-in. For this purpose, create a new plug-in project named org.eclipse.gmf.examples.mindmap.diagram.custom to your workspace. Use the default settings, although no Activator class is needed, nor is the use of any of the templates provided in the wizard.
Custom Actions
The standard means to create a new subtopic is a bit painful at the moment: click on Topic creation tool, then diagram, name with in-place editor, click Subtopic link creation tool, draw link from parent to subtopic. Ideally, we'd like to simply use a right-click menu option on a selected Topic and choose "Create Subtopic" or better yet, press the Insert key (or some combination) and have the new Topic created, including the link, and with the in-place editor active on the new Topic. In this section, we will explore how to accomplish just this.
To begin, we know that the org.eclipse.ui.bindings can be used to assign a Ctrl+I key combination to our action (as seen on the image, though for OS X). This is easily accomplished by contributing to the extension-point in our new *.diagram.custom plugin.xml file. Note that this is a simplistic example that does not declare a context, as you would probably expect to create for your diagram and potentially extend a default GMF diagram context (if one existed ;-).
<extension point="org.eclipse.ui.bindings"> <key commandId="org.eclipse.gmf.examples.mindmap.insertSubtopic" sequence="M1+I" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/> </extension>
Now, for the command, we'll contribute to the org.eclipse.ui.commands extension-point, as seen below. When you run your diagram, you will see this command category and the shortcut listed in the General | Keys preference page.
<extension point="org.eclipse.ui.commands"> <category name="Mindmap" description="Commands related to Mindmap diagrams." id="org.eclipse.gmf.category.mindmap"/> <command categoryId="org.eclipse.gmf.category.mindmap" description="Inserts a new subtopic" id="org.eclipse.gmf.examples.mindmap.insertSubtopic" name="Insert Subtopic"> </command> </extension>
Now, for the popup menu. We'd like to have a series of potential menu items to insert elements on our diagram (i.e. subtopics, threads, etc.), so our contribution to org.eclipse.ui.popupMenus will define an 'Insert | Subtopic' menu and link it to our binding above through the defintionId:
<extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="false" id="org.eclipse.gmf.examples.mindmap.diagram.ui.objectContribution.TopicEditPart1" objectClass="org.eclipse.gmf.examples.mindmap.diagram.edit.parts.TopicEditPart"> <menu id="MindmapInsert" label="&Insert" path="additions"> <separator name="group1"/> </menu> <action class="org.eclipse.gmf.examples.mindmap.diagram.part.MindmapCreateSubtopicAction" definitionId="org.eclipse.gmf.examples.mindmap.insertSubtopic" enablesFor="1" id="org.eclipse.gmf.examples.mindmap.popup.MindmapCreateSubtopicActionID" label="&Subtopic" menubarPath="MindmapInsert/group1"> </action> </objectContribution> </extension>
Now, for the fun part... to define the declared MindmapCreateSubtopicAction class. To begin, we know that similar functionality exists in the connection handles feature provided by the runtime (see image below).
After some investigation, it seems the CreateViewAndOptionallyElementCommand class gives us a hint at how to implement what we want (thanks to Cherie for providing a simplied version of the original tutorial code below, which leverages the DeferredCreateConnectionViewAndElementCommand).
public void run(IAction action) { CompoundCommand cc = new CompoundCommand("Create Subtopic and Link"); // Create the new topic for the other end. CreateViewRequest topicRequest = CreateViewRequestFactory.getCreateShapeRequest(MindmapElementTypes.Topic_2001, selectedElement.getDiagramPreferencesHint()); Point p = selectedElement.getFigure().getBounds().getTopRight().getCopy(); selectedElement.getFigure().translateToAbsolute(p); int edgeCount = selectedElement.getNotationView().getSourceEdges().size(); // A quick hack to get subtopics to layout to the right, from top to bottom int offset = (edgeCount * 50) - 100; topicRequest.setLocation(p.translate(100, offset)); MapEditPart mapEditPart = (MapEditPart) selectedElement.getParent(); Command createTopicCmd = mapEditPart.getCommand(topicRequest); IAdaptable topicViewAdapter = (IAdaptable) ((List) topicRequest.getNewObject()).get(0); cc.add(createTopicCmd); // create the subtopics link command ICommand createSubTopicsCmd = new DeferredCreateConnectionViewAndElementCommand(new CreateConnectionViewAndElementRequest(MindmapElementTypes.TopicSubtopics_4001, ((IHintedType) MindmapElementTypes.TopicSubtopics_4001).getSemanticHint(), selectedElement.getDiagramPreferencesHint()), new EObjectAdapter((EObject) selectedElement.getModel()), topicViewAdapter, selectedElement.getViewer()); cc.add(new ICommandProxy(createSubTopicsCmd)); selectedElement.getDiagramEditDomain().getDiagramCommandStack().execute(cc); // put the new topic in edit mode final EditPartViewer viewer = selectedElement.getViewer(); final EditPart elementPart = (EditPart) viewer.getEditPartRegistry().get(topicViewAdapter.getAdapter(View.class)); if (elementPart != null) { Display.getCurrent().asyncExec(new Runnable() { public void run() { viewer.setSelection(new StructuredSelection(elementPart)); Request der = new Request(RequestConstants.REQ_DIRECT_EDIT); elementPart.performRequest(der); } }); } }
Rather than type in the code, simply copy the MindmapCreateSubtopicAction class into your project from the solution in CVS. If you observe any Access Restriction errors, add the required packages to the Exported Packages list on the Runtime of the *.diagram plugin. The basic concepts are outlined next.
Our action will implement IObjectActionDelegate, with its run method performing the following:
- create and initialize a CreateConnectionRequest
- create and execute a CompoundCommand, containing a DeferredCreateConnectionViewAndElementCommand
- create and perform a direct edit request on the new subtopic
Run the diagram and test the functionality using the keyboard combination (Ctrl+I) or right-click menu. Note that the subtopic is created above and to the right of the parent with direct editing enabled for you to give it a name. As you can see, the code to determine the position is a temporary hack (layout will be covered in another installment of the tutorial).
Custom Layout
Clearly, the default layout provided is not appropriate for a mindmap. What we are about to add is also less than optimal, but will indicate what is necessary to add a custom layout to your diagram. As described in the Layout Service Example, we will contribute an extension to the runtime's layoutProviders extension-point.
We'll try two layouts: one that extends org.eclipse.gmf.runtime.diagram.ui.providers.LeftRightProvider; the other, extending org.eclipse.gmf.runtime.diagram.ui.providers.internal.RadialProvider (To access these class you need to include org.eclipse.gmf.runtime.diagram.ui.providers in your project dependancies). For each, add the appropriate extension in your plugin.xml file, setting the Priority higher for the one you'd like to take precedence. For example:
<extension point="org.eclipse.gmf.runtime.diagram.ui.layoutProviders"> <layoutProvider class="org.eclipse.gmf.examples.mindmap.diagram.layout.MindmapDefaultLayoutProvider"> <Priority name="Medium"/> </layoutProvider> </extension>
The code for the LeftRightProvider is below:
public class MindmapDefaultLayoutProvider extends LeftRightProvider { public static String DEFAULT_LAYOUT = "Default"; public boolean provides(IOperation operation) { // enable this provider only on mindmap diagrams if (operation instanceof ILayoutNodeOperation) { Iterator nodes = ((ILayoutNodeOperation) operation) .getLayoutNodes().listIterator(); if (nodes.hasNext()) { View node = ((ILayoutNode) nodes.next()).getNode(); Diagram container = node.getDiagram(); if (container == null || !(container.getType().equals("Mindmap"))) //$NON-NLS-1$ return false; } } else { return false; } IAdaptable layoutHint = ((ILayoutNodeOperation) operation) .getLayoutHint(); String layoutType = (String) layoutHint.getAdapter(String.class); return LayoutType.DEFAULT.equals(layoutType); } }
If you run the diagram using both providers, it's clear that the left-right layout is more well-suited for a mindmap, although some adjustments would be necessary to make it more usable.
Removing Tools from the Palette
Let's say you don't want to see the Notes stack and Zoom tool on your palette. To remove them, you need to contribute to the paletteProvider extension-point using the predefinedEntry IDs and remove="true" attribute. For these contributions to not impact all editors, add an editor element with your diagram's ID to the paletteProvider, as seen below:
<extension point="org.eclipse.gmf.runtime.diagram.ui.paletteProviders"> <paletteProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider"> <Priority name="High"/> <contribution> <predefinedEntry id="standardGroup/zoomTool" remove="true"/> <predefinedEntry id="standardGroup/noteStack/noteTool" remove="true"/> <predefinedEntry id="standardGroup/noteStack/textTool" remove="true"/> <predefinedEntry id="standardGroup/noteStack/noteattachmentTool" remove="true"/> </contribution> <editor id="org.eclipse.gmf.examples.mindmap.diagram.part.MindmapDiagramEditorID"> </editor> </paletteProvider> </extension>
This contribution is added to the org.eclipse.gmf.examples.mindmap.custom plugin.xml file in CVS.
Customization Extension points reference
Here is the list of extension point you can use in your customization plugins to improve the diagram without modifying the generated code: http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.gmf.doc/reference/extension-points/index.html
Customizing generation templates
GMF Tooling uses XPT templates to generate your diagram code. But it offers the way to use alternative template if you have to tweak directly generated code.
Set it up
See http://community.bonitasoft.com/customize-your-gmf-editor-customizing-templates
Overriding templates
See http://community.bonitasoft.com/customize-your-gmf-editor-customizing-templates
Using aspects
http://community.bonitasoft.com/customize-your-gmf-editor-customizing-templates
Summary
In this section of the tutorial, we saw how to add a composite figure, create a custom action and layout provider contained within a new extension plug-in. In the next section, we will look at using the dashboard, and generating an RCP-based mindmap with the "lite" runtime: GMF Tutorial Part 4
Following the tutorial
- GMF Tutorial Part 1 - Get Started with GMF
- GMF Tutorial Part 2 - How to configure your editor
- GMF Tutorial Part 3 - Advanced customization
- GMF Tutorial Part 4
References
- GMF Tutorial Part 3 - Advanced customization