Jump to: navigation, search

Difference between revisions of "Graphical Modeling Framework/Archived Newsgroup Q and A"

([http://dev.eclipse.org/newslists/news.eclipse.technology.gmf/msg03717.html How can I access the parent of a model element?])
(No difference)

Revision as of 05:27, 13 December 2010

Contents

Why does CanonicalEditPolicy create transient view elements by default?

  • Q: By defaut CanonocalEditPolicy creates view elements as transient. What is the reason for such behaviour? Why do not use persistent children by default? Is there any performance concerns?
  • A: The canonical edit policy kicks in to synchronizethe Notation views with the semantic model. This might result in creating or deleting views, andwill happen at diagram loading time. IF the canonical edit policy creates transient views this means the transient views will be created only when the diagram isopened, so they will not affect the model memory foot print unless thediagram is opened. This is a major requirement for big models that hostsmany big diagrams.

Also one of the concerns we had if the canonical editpolicy creates persisted views, the diagram might get dirty at load time.Which might not be expected by the user and it might trigger a check outaction if the model is under source control. That is why we decided to make the canonical editpolicy create transient views by default. The transient views will be persisted as soon as theuser change any of the view attributes.

Regarding performance, the fact that the views aretransient would not help your performance, actually it might slow it alittle bit because each time you open your model the views will be re-created.

How can I set up a header and footer in my print options?

  • Q: Some months ago I wrote in the GEF group asking about printing a header and footer on pages, which I guess falls under the area of page setup for printing. At that time I was pointed at GMF. Recently I've tried the GMF print facilities using the examples (including Taipan, which I got help with from this group). However I do not see any header or footer options in the page-setup dialog. Does GMF have any kind of header or footer support? Please advise, thanks.
  • A: The functionality for setting and getting header and footer strings was taken out from the UI (i.e. the Page Setup dialog) but the printing still supports header and footer.

You can still use your own UI to get/set the preferences of your diagram to enable header and footer. GMF supports four types of headers and footers:

1. Custom text 2. The title 2. The date 3. The page number

Please note that if you do set a header and footer, it will be used for every page printed.

What to set in preferences to enable header and footer:

You will need the following strings...

public static final String HEADER_PREFIX = "header"; public static final String FOOTER_PREFIX = "footer"; public static final String PRINT_TEXT_SUFFIX = "PrintText"; public static final String PRINT_TITLE_SUFFIX = "PrintTitle"; public static final String PRINT_DATE_SUFFIX = "PrintDate"; public static final String PRINT_PAGE_SUFFIX = "PrintPage";

you can combine HEADER_PREFIX _or_ FOOTER_PREFIX with any of the last four strings (e.g. setting the preference for HEADER_PREFIX + PRINT_DATE_SUFFIX to a boolean true will print the date in the header of every page). Following this, the last three preference types are of type boolean, while for PrintText, you can set your own text to be printed.

Why doesn't the source element get updated when I delete a link's target?

  • Q: I could not find my problem in the bugzilla or the newsgroup and that's why I am asking for your comments.

The following situation: To model a sequence of elements I have two main elements, nodes and transitions. A node can contain a number of transitions and a transition always has a node as source and target. This is expressed as two EClasses with Node having a containment reference to Transition and Transition having two references, source and target to Node.

I've modelled this in GMF and generated the code. Modelling the sequence works fine and if I delete a target node of a transition both elements are removed from the diagram. But the transition still exists in the source node (without a target which causes an error during model validation). Means, the node is deleted properly but not the transition. And there is no possibility for me to fix this in the diagram. I have to delete this manually in the model.

I am not sure, if this is a problem of my model or the generated code. If I delete first the transition and the node everything is OK. Is there a way to propagate the removal of the transition also to the source node in GMF or do I have to tweak the EMF code?

  • A: Hopefully someone will correct me if I'm wrong, but I don't think this is supported by the generator. At least, I observe similar behavour in the TaiPan example; a route connecting two ports is not destroyed when I destroy one of the ports.

One way you can solve this problem is by implementing the [Node?]EditHelper#getDestroyDependentsCommand(DestroyDependentsRequest) to return a command that will also destroy any Transitions referencing that Node. As an example, you can look at the TerminalEditHelper in the logic diagram, in which Wires are destroyed as dependents of the Terminal.

How can I replace the collapse compartment figure?

  • Q: I tried to extend CompartmentCollapseHandle in order to use my own CollapseFigure. However, there was compile error: Implicit super constructor CompartmentCollapseHandle() is undefined. Must explicitly invoke another constructor. Is this class intended to be final or it is just a bug ?
  • A: CompartmentCollapseHandle is public and you are free to extend it. All you need to do is invoke the superclass constructor with the IGraphiclaEditPart parameter from your own subclass constructor(s).

How can I view child nodes in the Outline view?

  • Q: Is it possible to customize the Taipan example to do the following... I create a ship called myShip1. In the Outline View, I see myShip1 as a

root level node. I then add a small item to the ship. I would like to see the small item appear as a child node of myShip1 in the Outline View, but it doesn't show up at all. Can this be done?

  • A: You can customize the factory for the Outline View, and make the parent/child relationships basically whatever you want. The code in your generated editor instantiates an OutlineTreePartFactory, which in turn creates TreeEditParts. Both of these are by default very generic. You can customize the OutlineTreePartFactory be extending it and then calling setEditPartFactory on the OutlineViewer. Then create an edit part for your parent and override "getModelChildren" to customize the children.

How can I make my diagram properties read-only?

  • Q: What do I need to do to make a property read only in the properties view of the final diagram code ? Is there a way to configure this within the generation model or somewhere else? Or do I need to modify the generated code? I need to set that value programatically... How can I do it?
  • A: You can make corresponding property read-only in EMF model (referring to the GenFeature's Property Type property not theEStructuralFeature's Changeable property).

ItemPropertyDescriptor's canSetProperty controls whether the propertycan be modified.

  public boolean canSetProperty(Object object)
  {
    if (isSettable)
    {

How can I work with a domain model in a diagram, but not maintain a diagram file?

  • Q: I have a generated diagram editor but I dont want to store any diagram files. At the moment, I override the setInput() method in the generated diagram editor so that the editor will take a domain file, create a diagram file, and pass the diagram file to super.setInput(). when the diagram editor is closed, it will delete the temporarily created diagram file.

This works with RC6 but not with 1.0. In 1.0, after I called ViewService.createDiagram(), only the a DiagramImpl is created (no children at all). Any idea why? The corresponding CanonicalEditPolicy.getSemanticChildrenList() function never got called. No idea why.

Also, is there any better way to get rid of the diagram files? ie. not to create the diagram files at all (should I modify the XXXDocumentProvider?)

PS: here is my code:

    public void setInput(IEditorInput input) {
        IFile myFile = (IFile)input.getAdapter(IFile.class);
        if (myFile.getFileExtension().equals("xml")) {        
            try {
                // create the model
                TransactionalEditingDomain editingDomain = createEditingDomain();
                ResourceSet resourceSet = editingDomain.getResourceSet();

                resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
                        .put("xml", new NetworkFlowResourceFactoryImpl());
                Resource resource = resourceSet.getResource(URI
                        .createPlatformResourceURI(myFile.getFullPath().toString()), true);

final EObject diagramRoot = (EObject) resource.getContents().get(0);

                // create the diagram file
                IPath containerPath = myFile.getParent().getFullPath();
                DiagramFileCreator fileCreator = 
NetworkflowDiagramFileCreator.getInstance();
                IFile diagramFile = fileCreator.createNewFile(
                        containerPath, 
//                        fileCreator.getUniqueFileName(containerPath, myFile.getName()),
                        fileCreator.appendExtensionToFileName(myFile.getName()),
                        null, null, null);

                final Resource diagramResource = resourceSet.createResource(URI
                        .createPlatformResourceURI(diagramFile
                                .getFullPath().toString()));

                // create the diagram
                List affectedFiles = new LinkedList();
                affectedFiles.add(myFile);
                affectedFiles.add(diagramFile);
                AbstractTransactionalCommand command = new 
AbstractTransactionalCommand(
                        editingDomain, "Create new diagram file", affectedFiles) {
                    protected CommandResult doExecuteWithResult(IProgressMonitor monitor, 
IAdaptable info) throws ExecutionException {
                        int diagramVID = 
NetworkflowVisualIDRegistry.getDiagramVisualID(diagramRoot);
                        if (diagramVID != ConfigurationEditPart.VISUAL_ID) {
                            return CommandResult
                                    .newErrorCommandResult("Incorrect model object stored as a root 
resource object"); //$NON-NLS-1$
                        }
                        Diagram diagram = ViewService.createDiagram(
                                        diagramRoot,
                                        ConfigurationEditPart.MODEL_ID,
                                        NetworkflowDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT);
                        diagramResource.getContents().add(diagram);
                        return CommandResult.newOKCommandResult();
                    }
                };
                OperationHistoryFactory.getOperationHistory().execute(command, new 
NullProgressMonitor(), null);
                diagramResource.save(Collections.EMPTY_MAP);

                super.setInput(new FileEditorInput(diagramFile));
            } catch (Exception ex) {
                NetworkflowDiagramEditorPlugin
                        .getInstance()
                        .logError(
                                "Unable to load resource: " + myFile.getFullPath().toString(), 
ex); //$NON-NLS-1$
            }
        } else {
            super.setInput(input);
        }
    }
  • A: Try following all the process - this method should be called as a result of .activate() method call on the ?CanonicalEditPolicy generated for your diagram (the only generated edit policy extending CanonicalConnectionEditPolicy).

I have found the bug:

I registered the ResourceFactory before I created and save the diagram. After the diagram was created and saved successfully, I passed the diagram file to super.setInput(). And when the diagram editor was actually opening the diagram file, it couldn't find the ResourceFactory anymore.

Now I register the ResourceFactory in the createEditingDomain() function, and the editor works fine now.

How to force the diagram editor to reload a resource which is modified into another editor?

  • Q: I've an ecore model which is referenced by a diagram model. The diagram model loads this ecore model to access some extra data in it. When the diagram editor is opened for a diagram model and the other ecore model editor is also opened, how can I force the diagram editor to reload the resource of the ecore model when the ecore model editor saves it?
  • A: Starting from GMF 2.0 M3 generated diagram editor is listening for any changes in the eclipse resources, so diagram will be automatically updated on saving other ecore model editor. To update diagram contents without saving another editor you can share editing domain instance across these two editors.

In older GMF versions you should reopen the editor or you can try using the same editing domain instance for both editors.

In the doSave of the ecore model editor, after saving the model, I get the list of opened editors using this.getSite().getWorkbenchWindow().getActivePage().getEditors() and catch those corresponding to a diagram model. For each of them, I'm getting the TransactionalEditingDomain. From this edit domain, I can get the ResourceSet and find the resource corresponding to the ecore mode. Then I unload and load again this resource using as option editingDomain.getResourceSet().getLoadOptions(). This works fine and opened editors remain in the same visual state, that's an advantage. The only one drawback is that I'm using getEditors which is deprecated.

How can I get the dimensions of a diagram?

  • Q: How can I get the dimensions of the diagram? I know, I can traverse all components in it and take their sizes and position to calculate the diagram's dimensions but it seems to me it's not the best way to do that. I noticed that when I export the diagram as image - the dimensions of the generated image are exactly what I need...
  • A: We are doing what you suggested when the diagram is exported as an image. See DiagramGenerator.calculateImageRectangle(List editparts).

How can I contribute new palette extensions?

  • Q: I have a base model and extended models. Base model defines some basic abstract domain models, for example, 'Shape', extended models defines some

elements which are derived from the base model, for example, 'Square'. Now I want to generate a diagram using GMF to allow creation of different shapes which are contributed from different extended models which reside in different plugins.

My questions are 1. how do I enable tool palette to display different shapes contributed from different plugins? 2 how to correctly construct different shape domain model in the diagram when the tool palette is used?

  • A: You may want to take a look at the Diagram Palette tutorial.

The GMF CreationTool is constructed with an IElementType, which determines the kind of semantic model element that will be created when the tool is used.

Here's a little patch that puts the half adder palette tool in the logic example (in the Circuit stack).

Each org.eclipse.gmf.runtime.diagram.ui.tools.CreationTool is instantiated with an IElementType. The #createTargetRequest method will create a request that carries this element type through to the edit policies. In the case of the half adder tool, the

SemanticEditPolicy#getSemanticCommand will ultimately honour the semantic part of the request by consulting the element type registry for the semantic command.

However, this will all be done for you behind the scenes. All that you need to do is to contribute your element types through the elementTypes extension point, implement the way to create those types in their edit helpers (or edit helper advice) and contribute the palette tools for those types.

There are some details about the way the element types work here.

How can I obtain all selected elements?

  • Q: We're planning to extend GMF editors with operations, working on multiple elements, due to this we need access to all selected elements.

We know the way with EObject selectedElement = FooElementActionDelegate.getSelectedElement(); but it gives us only the first selected Element and is only updated if called when an Action is executed. But we need it when a command from the palette is executed.

  • A: You could get all selected edit parts on diagram using EditPartViewer.getSelectedEditParts(); model of each edit part is notation View and domain model element is accessible via View.getElement().

How can I access the parent of a model element?

  • Q: How is it possible for a child model element to access its parents attributes and methods?
  • A: Try child.eContainer().get...()

If your Edit Part's model is an EObject,you can do this:

    EObject myModel = (EObject)myEditPart.getModel();

then on your model you can call eContainer()

    EObject myParent = myModel.eContainer();

After getting the parent, you can useeither EMF Reflection API's ( like eGet to access all the parent attributesvalues), or you can cast the EObject to the Class you want and use the generated getters to get the values.

How can I get the size and location of an element?

  • Q: I am trying to retrieve the size and position of a model element. The size may be handled by the method getLayoutConstraint() as follows:
Size size = (Size) ((Node) view).getLayoutConstraint()

where 'view' is the View of the model element. How is it possible to retrieve the position of the model with respect to its parent?

  • A: Getting the position of the modelcan be achieved in different ways:

1- If your LayoutConstraint is Locationconstraint, you can use it to get the position then you can translate if you like 2- if you have your diagram rendered already, in other words you have the Figures around, you can get the figure( GraphicalEditPart.getFigure() ) then call getBounds to get the location of the figure and if you want to translate it you can use one of the translate* Methods on the figure to translate the location to whatever you like for example translateToParent.

How can I open an editor by double-clicking a compartment?

  • Q: I have a diagram element which has a compartment. I can add items to this compartment. But I want to be able to (double) click on the compartment element and open an editor view.

Can someone help me with pointers on how to achieve this?

In older GMF versions you can achieve that by installing an edit policy to handle the open request on the edit part you want. For example, if you want to open an editor in response to double click on list item:

1- first you create an edit policy thatextends the OpenEditPolicy,then implement the getOpenCommand method on it for example

public class OpenEditorEditPolicy extendsOpenEditPolicy {
        protectedCommand getOpenCommand(Request request) {
               EditPart targetEditPart = getTargetEditPart(request);
               if (targetEditPart instanceof IGraphicalEditPart){
                       IGraphicalEditParteditPart = (IGraphicalEditPart)targetEditPart;
                       View view= editPart.getNotationView();
                       if (view!=null){
                              EObject element = ViewUtil.resolveSemanticElement(view);
                              if (element instanceof Diagram) {
                                      returnnew ICommandProxy(
                                             new OpenEditorCommand(element));
                              }
                       }
               }
               return null;
        }
}

2- Override the createDefaultEditPolicies()in your list item edit part and install the OpenEditorEditPolicy against the Open_ROLE like this:

    
    protected void createDefaultEditPolicies() {
        super.createDefaultEditPolicies();
        installEditPolicy(
           EditPolicyRoles.OPEN_ROLE,
           newOpenEditorEditPolicy ());
    }

How can I access a model element from an IObjectActionDelegate?

  • Q: I have implemented a customization plug-in in order to customize the diagram editor generated by GMF. In this customization plug-in, I added an new action, similar to the tutorial 3 of GMF. I can access the EditPart of the selected object on the diagram using IStructuredSelection into the class of the action which is implementing IObjectActionDelegate. But how can I access the model object corresponding to the selected EditPart in order to check some property values ?
  • A: Try: ((org.eclipse.gmf.runtime.notation.View) EditPart.getModel()).getElement()

How do I use a ReorientRequest?

  • Q: Is this request used to switch between different links? If yes, anyone can give a plain programming guide for it?
  • A: This request lets you drag a connection end and move it to a new source/target so that the connection now goes between two different nodes.

Try supporting reorient of your relationship in your semantic model by implementing one of these methods in your EditHelper:

protected ICommand getReorientReferenceRelationshipCommand(ReorientReferenceRelationshipRequest req)

(for connections without a semantic element protected ICommand)

getReorientRelationshipCommand(ReorientRelationshipRequest req)

(for connections with a semantic element)

You should get everything else for free. :-)

How can I create a resizing polygon?

  • Q: I have a polygon inside a custom figure defined in the code below. The problem is when i try to resize my figure in the diagram, only the customFigure is resized and the polygon remains in the same size.
  • A: All point list based figures (including Polygons) are not resibale by nature. Generated code just do not have enough information to understand that (80, 80) is "the bottom right" of some resiable container.

For now, the only way to do it is to implement custom shape that will paint itself in terms of its ratios of its width/height. Please take a look at the "gmfmap resizeable figure" [2006-04-28], in particluar at the post with sample diamond shape.

I've just though that we could write figure (ElasticFigure) that:

   1. Paints nothing
   2. Uses local coordinates and has preferred size
   3. Overrides translate[To/From]Parent(Translatable t) methods so they take preferred size, divide this by current size and use these scale factors to translate t.

In gmfgraph model ElasticFigure could be used as a container for Polyline or Polygon; for example in this case Polygon should be put in ElasticFigure with preferred size 80,80. If I haven't miss something the effect should be scaled Polygon or Polyline figure just like if there was a StackLayout.

How can I set a layout for elements within a compartment?

  • Q: I need to align the elements in compartment in single row (using the

mindmap example - the 'Threads' shoul be in a single row) but when I use layout for the figure that represent the compartment - the element inside doesn't respect that layout...

the List Layout trye/false in gmfgen doesn't work for me.. if it is true the elements are aligned in a columns and only the labels were used, if it is false - the XY Layout is used.

Can somebody give me any hints how to solve it?

after some debug I noticed that the compartment is another figure and that's why the compartment doesn't respect the parent figure's layout manager.

It seems that there is a lack of Layout managers for compartment - there are only 2 layout managers for Compartment - in gmfgen - List Layout - true (FlowLayout vertical) and false(XYLayout).

How can I use other layout? I need flowlayout but horizontal...

  • A: As I may understand it is hard to set custom layout for ResizableCompartmentFigure, due to the internal dependencies. Say, ResizableCompartmentEditPart assumes that the figure has a layoutManager that accepts Float's (ratios) as constraints. Probably someone from runtime team could clarify this more deeper.

But if you just need horizontal flow layout, please try to modify CompartmentEditPart class to call ResizableCompartmentFigure#setHorizontal(true) inside the createFigure() method.

I had exactly same problem as you. It's still unresolved, but fortunately new versions of GMF at least render figures in List Layout (obviously as columns) and you can terminate edges at them. Probably almost all people who use GMF generator try to build UML editors which do not need such functionality :)

How can I use my own LabelProvider in the properties view?

  • Q: I would like to use my own LabelProvider for tabbed properties view instead of CommonLabelProvider of GMF runtime as defined in contribution

of org.eclipse.ui.views.properties.tabbed.propertyContributor. One of reasones is I want to work around the icon service and parser service. I still want to use all existing properties tabs. Is there a way to do this except defining my own contribution id for tabbed propertyContributor?

  • A: I assume you saw the answer on the thread "Removing Advanced tab in properties view and adding new tabs".

Unfortunately, there is no way to override the the label provider defined by the propertyContributor extension point (there is no public API on the TabbedPropertySheetPage to override in a subclass either).

How can I use compartments with custom figures?

  • Q: how can one use Compartments within CustomFigures?

In the concrete case, I have a CustomFigure (representing an UML package) consisting of a Polyline (surrounding the package name) and a Rectangle (representing the package body).

I need a compartment to cover exactly the body Rectangle and possibly with a defined offset.

There are at least two approaches I can think of: (1) In the gmfmap, define the body Rectangle as a Top Level Mapping of its own. -> This causes problems, because the mere body has no semantic element. Only the whole CustomFigure does.

(2) Add some custom code to the Compartment's refreshBounds() method. -> Unsure whether this is good practice.

  • A: First, you do not need custom figures to define simple shapes like "folder"

viewmap. Attached please find the modified gmfgraph model for mindmap sample that will viewmap topics like "folders" with correct compartment behaviour (see screenshot below).

The relevant part of gmfgraph is also below. It consists of 1. Enclosing invisible (outline = false) rectangle "InvisibleFolderRoot" with GridLayout of 2 columns 2. First row of grid layout consist of "FolderNameContainer" (with preferred height of 30 that can not be calculated by layout manager) and invisible "Padding" 3. Second row consists of single "CompartmentContainer" spanning 2 columns with grabVertical = grabHorizontal = true. 4. Label inside FolderNameContainer with referencing diagram label 5. Rectangle "FolderCompartment" as the only child of FolderNameContainer

Note that #5 is optional -- you may setup compartment referencing "CompartmentContainer" without introducing inner figure.

The main trick is to setup Compartment to reference the figure inside the main viewmap hierarchy. In this case runtime will layout the figures as they are simple rectangles and then place compartment into the correctly layouted place.

To make the generated code compilable please take the GridLayout code from https://bugs.eclipse.org/bugs/show_bug.cgi?id=133279. Just in case, I will attach the completely regenerated mindmap sample as a separate post (due to attachment size limit).

In case you are forced to use CustomFigure's you may repeat the same trick (compartment referencing figure from hierarchy) using FigureAccessor as child of custom figure (you will need to have getter corresponding with this Accessor in the custom code).

How can I reference EObject in my mapping definition?

  • Q: I have created an ecore model where one class references elements of type org.eclipse.emf.ecore.EObject. Now in my GMFMAP model I try to create a Node Mapping with the domain element set to EObject (the containment feature of the top-node reference of this node mapping has been set to the attribute referencing elements of type EObject).

I have already loaded the resource platfrom:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore but the drop down list for the domain element has no entry EObject but shows only elements of my own ecore model.

  • A: I'm afraid this happens due to the nature of EMF - EObject taken from yourReference.getEType() is not the same as EObject loaded from platfrom:/.../Ecore.ecore.

Here's the way to deal with that:

load Ecore.ecore resource into your .ecore domain model, and use EObject _from loaded resource_ to set EType of yourReference (not EObject available by default). Make sure xmi looks like (note path to Ecore.ecore file) <eStructuralFeatures xsi:type="ecore:EReference" name="yourReference" eType="ecore:EClass ../../../plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject"

After that, you'll get all EObject subclasses in the drop-down list. Note, unless you make elements of your domain model explicitly extend EObject, you'll get only element of ECore domain model in the list (they are the only to hold EObject in their eSuperTypes references).

How can I layout widgets within a custom figure?

  • Q: I have a CustomFigure with an XY Layout and a Label and a Polyline within.

How do I control the location of the Label (or any other standard widget) within that CustomFigure? I already added to the Label an "XY Layout Data" element and (as a child of that one) a "Point" element.

What I expect is a generated call like "myLabel.setLocation(x,y)". Instead, an additional Rectangle is generated and used in the call to "add(myCustomFigure, constraint)" as a constraint (??).

  • A: The usage of Rectangle's as constaints is a convenient way of using XYLayout. Please take a look into the org.eclipse.draw2d.XYLayout#layout(Figure) -- lines 93-113. IMHO, having constraint rectangle defined for inner figure will force XYLayout to finally call innerFigure.setBounds(...).

Just calling of the childFigure.setPosition(...) is not enough, because it would break the code that calculates the preferred size for parent figure (check org.eclipse.draw2d.XYLayout#calculatePreferredSize() method).

I got it working by overwriting paint(Graphics g) of the outerFigure and inserting:

setConstraint(innerFigure, new Rectangle(3, 2, -1, -1));

You're right about the semantics of the XYLayout#layout(Figure) method but it's not necessary to call the layout manager explicitly.

How can I change the appearance of an element based on its domain element's attributes?

  • Q: I was wondering if there's a way to specify in the gmf models to change the visuals of a node figure depending on the value of an attribute of the underlying model element.

For example, let's say I have a model element with a boolean attribute and I want the node figure to be painted blue if the attribute is true and red if the attribute is false.

Is there a way to accomplish this?

  • A: Actually there are two ways of achieving this.

First one:

Define two rectangles in gmfgraph, with blue and red backgrounds. Define two Node's, say "RedWhenTrue" and "BlueWhenFalse" in the gmfgraph. Then define two mappings in gmfmap, apply constraint based on the boolean attribute to select between these mappings. Set each mapping to reference different nodes.

This way is suited for simple cases, e,g, if you have 4 boolean attributes and want to vary 4 different visual parameters (say, border, foreground, background and font), then unfortunately you will need to create 16 different figures, nodes and mappings for each of the possible combinations.

We are considering the ways to handle this usecase via models in more simple way but it is not for 1.0 release.

Second way: Also you can manually setup listeners for domain model that will change visual representation like it is done in the gmfgraph editor sample plugin. This way was described a lot of times in this newsgroup by the author of gmfgraph editor.

How can I change an attribute in my model without a transactional command?

  • Q: I have a "transient" value in my model that I would like to update at certain times (happens to be during layout). It is similar to something like expansion state. Expanding and collapsing a branch is not an undo/redoable change, but it is a change to the model that should be persisted should the file be saved. A prime example of such a property is the diagram's zoom level.

I am having trouble updating data in my model when these UI states change. Stack trace:

Caused by: java.lang.IllegalStateException: Cannot modify resource set 
without a write transaction
at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.assertWriting(TransactionChangeRecorder.java:291)
at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.appendNotification(TransactionChangeRecorder.java:253)
at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.processObjectNotification(TransactionChangeRecorder.java:235)
at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.notifyChanged(TransactionChangeRecorder.java:191)

I just want to update a boolean value in my model. Is that so wrong? How do I get GMF to ignore the fact that I am not executing a transactional command on the operation history?

  • A: You can execute a transactional command not on the operation history, if you don't need it to be undoable/redoable. You just need to be careful that the objects and properties that the command is changing are not also changed in previous commands that are on the history, because then they

will cease to be valid (being deltas on a different state of the model than what is current).

You can avoid a good deal of transactional overhead by initializing your command with the Transaction.OPTION_UNPROTECTED option. This has the added benefit of allowing it to be executed even in an otherwise read-only context (e.g., when the current thread has an active read-only transaction).

If changing this 'expanded' property in the model can invalidate the undo-ability of existing commands on the operation history, then you'll need to flush the history for your undo context after you've changed the property. I think the easiest way to do this is by making the property change via a non-undoable command executed through the operation history. If you do this, the history will be flushed automatically.

There is a transactional SetValueCommand in GMF that you could re-use, but it is undoable. You would have to subclass it in order to override #canUndo and #canRedo.

The trick is to call: EObject#eSetNotify(false).

This prevents EMFT from knowing about the change to the model. It turns out I need to use this technique in other places to handle lazy initializing of default values in my model. For example, if the default font style for a given View subclass should be "color=blue". The first time someone attempts to grab the FontStyle object, it will be initialized (if its not explicitly set already), and subclasses in my model can hook in to indicate the proper defaults for that view class.

How can I add a label offset between the compartment name and first element?

  • Q: I would to insert an offset between the title of a compartement and the first element of its children list. I'm trying to add a "Label Offset Facet" to this compartment in the .gmfgraph, but nothing happens. The same if I try to add a "Label Offset Facet" in the gmfgen.

Is this the right way? What can I do?

  • A: It is for link labels only.

"Label Offset Facet" in the gmfgen is used as a label snapback position:

static {
registerSnapBackPosition(TaiPanVisualIDRegistry.getType(RouteDescription2EditPart.VISUAL_ID), 
new Point(0, 40));
}

So you can select 'Format' -> 'Snap Back' from the label context menu and it will align to the link in accordance with this offset.

Actually I've expected that labels would align right after the link creation but they pack on top of each other.

The snapback mechanism is not triggered during creation; however, you can set an offset in your label view factory that will be used to calculate the original location of the label.

LabelEditPart.handleNonResizableRefreshBounds() creates a LabelLocator and passes in an offset which is retrieved from the view. These values could be set in your label view factory class like this:

protected void decorateView(View containerView, View view, IAdaptable semanticAdapter, String semanticHint, int index, boolean persisted) {
   super.decorateView(containerView, view, semanticAdapter, semanticHint, index, persisted);
   ViewUtil.setStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_X(), xOffset);
   ViewUtil.setStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_Y(), yOffset);
}

Use a positive and a negative y values to place two labels on opposite sides of the connection.

How can I split the contents of a containment reference among several compartments?

  • Q: If I have a Class containing a list, is it possible to display this Class with a diagram node having compartments each one mapping every list element ?

In particular, is it possible to split a containment feature among different compartments ? In the .gmfmap, in the property named Containment Feature of a Child Reference, is it impossible to refer to the i-th element of a list. If I use the entire list as Containment Feature (this is the only possibility), all the elements are displayed in every compartment. For example, I would get something in which all the "constraint" elements belong to the same containment list. How can I do? Do I need compartments necessarily?

  • A: You can do it by creating additional "Constraint" element for each Node Mapping corresponding to your child elements in .gmfmap model. As an example you can take a look on Link Mappings for associations in Ecore sample diagram. These are link mappings but an idea is similar.

How can I modify a resource set without a write transaction?

  • Q: How can I enable semantic model for direct changes via *Impl.set*() methods? I'm developing shared diagram editor. Models will be synchronised by CDO from EMFT project. CDO doesn't know about TransactionalEditingDomains and (AFAIK) Commands at all. Is there any way to evade this restriction? I'd rather avoid revolution in CDO.
  • A: All of your changes must be performed by Commands executed on the TransactionalEditingDomain's CommandStack, or by AbstractEMFOperations (AbstractTransactionalCommands in GMF) on your editing domain.

See the EMFT Transaction Developer Guide in the on-line help for examples.

The abstract RecordingCommand class defines a doExecute() method (or some such) which subclasses implement to poke their model using the metamodel API. It performs undo/redo by replaying the changes recorded by the transaction in which it is run.

So, this provides the command-free editing model that is required without complicating undo/redo.

Some things to keep in mind are, if the model is changed without usinga command, then very likely the command stack needs to be flushed,since correct undo relies on the model being in exactly the expectedstate that the commands left them in. Are you taking an explicitaction to cause a sync to happen? If so, you can wrap that in atransaction, although you probably don't want to treat it as anundoable command but rather will want to flush the command stack after the refresh...

Synchronizing the model state with an external data store such as a CDO-connected database is exactly the reason why the transaction API has the Transaction.OPTION_UNPROTECTED. This option exempts a transaction (running either as a Command or as an AbstractEMFOperation) from the usual transactional protocol, including:

- unprotected read/write transactions can be created in an otherwise read-only context (child of a read-only transaction) - unprotected changes are not recorded for undo/redo - unprotected changes are not validated (hence, never roll back) - unprotected changes do not invoke triggers (pre-commit changes) for model integrity

Unprotected changes still provide the thread-safety guarantee. However, because unprotected changes will modify the abstract state of the model, you should (as suggested) flush the stack/operationhistory afterwards.

How can I use an alternative to canonical containers?

  • Q: I am currently looking for an alternative to the canonical containers in GMF.

Imagine you have a UML2 package model and want to see just a subset of its classes in one diagram and another subset in another diagram. With the canonical policy that's not possible, because as soon as you add a class to one diagram, it does automatically pop up in the other, because they share the same semantic container.

Is it be possible to enforce another policy in GMF?

I've already had a look at the edit policies of the generated diagram classes. Would it be sufficient just to put a non-canonical policy there, or is there further impact of the canonical container principle on the runtime classes? How big would you estimate the amount of necessary changes?

  • A: GMF can generate non-synchronized diagram; I suggest you to use GenDiagram.synchronized property and fully generate

the code.

How can I add a text editor in my diagram?

  • Q: I've built a diagram with GMF, and now I want to add a text editor in my diagram. How can I do it?
  • A: There is a TextEditPart available the runtime. There is an example of its use in the Geoshapes Example (Text in the palette).

How can I display an SVG figure on the diagram background?

  • Q: would like to show an SVG graphic, that should be scalled with the diagram, behind the GMF objects.

Is there any batik render for SWT or draw2d object encapsulating an SVG object? Is this possible?

  • A: You may consider using ScalableImageFigure from org.eclipse.gmf.runtime.draw2d.ui.render plugin. The solution may be a new diagram layer that contains your svg drawing.

How can I filter out elements when applying my decorator?

  • Q: I have introduced my own decorator similar to the shortcuts decorator for putting an icon on certain nodes on my diagrams. Basically, all nodes of 1 type should be decorated (no decision logic is involved).

Right now, the decorator seems to be visiting every node on the diagram-createDecorators() is being called. Any way to optimize this so that all nodes except the 1 I'm interested in is filtered out?

  • A: You can filter out which nodes you want to decorate in the provides() method of your DecoratorProvider. If you wish to avoid having your plugin loaded for nodes that you do not provide for, you can identify your contribution criteria in the XML for your DecoratorProvider. The XML schema is very similar for all the GMF extension points so you could look at one of the examples for assistance.

How can I add child nodes that anchor to the perimeter of a node?

  • Q: I want to add to a node a child which will appear on the perimeter of the node. Something like a dynamic anchor for example. Additionally i would like to be able to move this anchor freely along the perimeter of the parent node. Could you suggest a way to implement this?
  • A: We support this in the diagram runtime using the border item infrastructure. This is probably only useful if your border items have a semantic element or need the overhead of an editpart. Take a look at TerminalEditPart and TerminalOwnerShapeEditPart for an example. The terminals on a LED and circuit in the GMF logic example are an example of border items. These terminals cannot be moved, but it is easy to allow them to be moved around the border of the shape they are on.

Basically, an editpart that implements IBorderItemEditPart represents a shape that resides on the border and an editpart that implements IBorderedShapeEditPart represents a shape that holds the border shapes along it's border. If you subclass AbstractBorderItemEditPart and AbstractBorderedShapeEditPart you may get most of the behavior you need for free. The location of the border items and their ability to move is determined by a locator. You will need to implement IBorderItemLocator to this to work in our framework. The BorderItemLocator class may be sufficient.

How can I persist my models to a database?

  • Q: I'm trying to load/store the Data editied by a GEF Diagramm-Editor

to a database. How and where do I intercept the normal machnism of storing/loading from two separate filesystem-files?

  • A: Instead of doing it by hand try to use already created O/R mapper for EMF models. I'm working now on integration of GMF generated diagram editor with CDO (from EMFT project). There are other O/R mappers for EMF models too.

Specialized load and save is often accomplished with a specialized ResourceImpl subclass that overrides doSave and doLoad. Of course you could save to a byte array output stream and stuff that in a data base, and then load again from a byte array input stream pulled from the data base. Another approach is to have a specialized URI converter on the resource set and have specialized URI syntax that's interpreted to access the data base directly. I described recently on the EMF newsgroup how to do that, so you might want to search for that. Looking at the URIConverterImpl will give you an idea of how that mechanism is used to access the Eclipse workspace...

How can I bind an element's attribute to a layout property?

  • Q: Can I change the properties of Flow Layout programatically? I mean to create a boolean property vertical in my model and bind it to Flow Layout in any rectangle figure, so when the user change that property, at the same time to change the layout property and all subwidgets will me re-positioned from one row to one column and vice versa.
  • A: You can take a look on org.eclipse.gmf.graphdef.editor from CVS. This is a prototype of WYSIWYG editor for .gmfgraph model. In this plugin we've tried to perform the same synchronization, so you can take it as a sample of such code.

Is it possible to connect two links?

  • Q: Is it possible to connect one link to another using GMF? For instance, I have link L1 going from Node A to Node B, and would like link L2 to go from Node C to some point on link L1.
  • A: The runtime supports this. It is possible to do this with note attachments in the Logic or Geoshapes Example.

How can I use GMF diagrams without using files?

  • Q: I'm investigating opening a GMF generated editor from a selected object in a view. The object is stored in a DB, there's no file available.

The steps I think I might need so far are:

- Modify generateed editor so that it contains

/*
* @generated NOT
*/
protected void setDocumentProvider(IEditorInput input) {
  if (input instanceof IStorageEditorInput) { // addition
    setDocumentProvider(new StorageDiagramDocumentProvider()); // addition
  } else { // addition
    setDocumentProvider(new ModelDocumentProvider());
  }
}

documentProvider.connect(object) will be called at some point with the editor input.

- Create a JDBCResourceImpl extends org.eclipse.emf.ecore.resource.impl.ResourceImpl

- Create a JDBCResourceFactory that extends org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl that creates JDBCResourceImpl objects. The factory gets supplied with the connection to the DB.

- Register an instance of JDBCResourceFactory with the global Resource registry using the protocol scheme, e.g.

Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap().put("jdbc", new JDBCResourceFactoryImpl(jdbcConnection));

but I need to do this somehow such that factories represented by different connections are distinguishable.

Questions - has anyone opened a GMF generated editor on a non IFile resource? If so are there examples? - Do I need to register an AdapterFactory to adapt selected objects to IStorageEditorInput? Then in the handleOpen() method of my view call IDE.openEditor(page, editorInput, editorID) ;

  • A: To my understanding you have to:

1.Create your own implementation of IStorageEditorInput working with DB. 2.Create your own implementation of IdiagramDocumentProvider working with new IStorageEditorInput. You can take a look on existing implementations: FileDiagramDocumentProvider, FileDiagramDocumentProvider. 3.Patch generated ?DiagramEditor.setDocumentProvider() method to return your document provider in case different EditorInput was used.

How can I change a property programmatically?

  • Q: I try to change property's value but without success. The target is variable

from LabelImpl class and I try this:

EObjectImpl ttmmpp = (EObjectImpl) ((org.eclipse.gmf.runtime.notation.Node) 
target.getModel()).getElement();
EStructuralFeature e = 
(EStructuralFeature)ttmmpp.eClass().getEStructuralFeature("name");
ttmmpp.eSet(e, "Test");

java.lang.IllegalStateException: Cannot modify resource set without a write transaction

The same code but instead sSet I try eGet and I receive the value without problem. I thinking that I should use CompositeTransactionalComamnd but I didn't know how do this.

  • A: The reason that eGet Works and ESet not is that you need to execute the

setting through the Editing domain so that you have write permision, here is the example how to do that. I have not implemented the undo because I don't need it for now, but overriding this methods should work, here is an example:

TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) selectedPart).getEditingDomain();
SetRequest setRequest = new SetRequest(editingDomain, comp, your_Package.eINSTANCE.getClassOne_Name(), name);
setRequest.setParameter("oldValue", comp.getName());

SetValueCommand operation = new SetValueCommand(setRequest){
  @Override
  protected IStatus doUndo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
    comp.eSet(your_Package.eINSTANCE.getClassOne_Name(), 
    this.getRequest().getParameter("oldValue"));
    return Status.OK_STATUS;
  }

  @Override
  public boolean canUndo() {
    return true;
  }

  @Override
  protected IStatus doRedo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
    comp.eSet(FoundationPackage.eINSTANCE.getGraBase_Name(), ((SetRequest)this.getRequest()).getValue());
    return Status.OK_STATUS;
  }

  @Override
  public boolean canRedo() {
    return true;
  }
};

try {
  CommandStack stack = viewPart.getViewer().getEditDomain().getCommandStack();
  stack.execute(new EtoolsProxyCommand(operation));
} catch (ExecutionException e) {
}

How can I add problem markers to a diagram?

  • Q: I have implemented a graphical editor based on the GMF runtime. The user creates a diagram and, when finished, invokes a code generator which takes the associated domain model as input.

As a first step the generator validates the passed model. I didn't employ the validation framework since I could easily combine this validation with a preparation step for the generator. Anyhow, the validation phase might end up with a list of problems together with the offended model objects.

Now it would be nice to present this information graphically in the editor, say as little error markers layed over the offended objects.

Is there a standard way to do this?

  • A: Currently, the generated GMF diagram editors are able run validation action using EMFT validation framework and produce resource markers for all constraint violations. These markers are associated with the diagram file and are also navigable to

the affected diagram elements.

As far as I understand, you rather talk about decorators, which we plan to support as well by using runtime DecoratorService. By default just as images that are used in the Problems View and placed on the afftected visual objects.

It is easy to use a decorator for this purpose. If you have the org.eclipse.gmf.examples.runtime.diagram.decorator example installed, and you change the note text to "Failed" you will see a little error icon.

You can also show Eclipse bookmarks on shapes. See the BookmarkDecorator.

How does Layout Data relate to a Layout?

  • Q: In a gmfgraph file it is possible to add a Layout or a Layout Data to a figure. Could someone please explain the difference between each Layout (Border Layout, XY Layout, ...) and the use of the associated Layout Data? When I add different Layouts, almost no changes in made in the result diagram. Is there any documentation explaining this specifically?
  • A: Generally, GMF representation of layouts is very close to "native" draw2d

implementation. The mapping between gmf classifier and generated d2d class is as follows:

gmf -> d2d BorderLayout -> org.eclipse.draw2d.BorderLayout XYLayout -> org.eclipse.draw2d.XYLayout StackLayout -> org.eclipse.draw2d.StackLayout FlowLayout, isForceSingleLine == true -> org.eclipse.draw2d.ToolbarLayout FlowLayout, isForceSingleLine == false -> org.eclipse.draw2d.FlowLayout GridLayout -> (missed now, vote for scr #133281)

Obviously, each layout description associated with parent figure required consistent LayoutData to be associated with gmf-figure children.

Basically, most of the Layout/LayoutData properties are mapped into the same or at least similar properties of the corresponding draw2d layout implementations. In some cases, renamings were made (e.g., d2d.ToolbarLayout#isHorizontal is mapped into gnf.FlowLayout#isVertical, etc). I hope that this mapping should be clear (sure, it does not mean that we are going to avoid formal documentation in future).

The most unusual part of the mapping is probably the part related to the gmfgraph Alignment construct. Some details of this mapping of this (as well as our reasons behind implementation decisions) were already discussed on this thread.

In case if you are interested in the layout codegeneration details, you could take a look at the [eog].graphdef.codegen plugin. Layout-realted templates may be found under the /templates/new/, /templates/layoutData/ and /templates/layout/ folders.

Please note that this code is still under development, so any of your questions or objections will definitely help us to improve it.

Say, for example, my FigureGallery contains following hierarchy:

FigureGallery !--- Rectangle R1 !----Ellipse E1 !----Ellipse E2

I tried to say, that if I have assigned BorderLayout instance to the R1 I also have to assign BorderLayoutData instances for E1 and/or E2. In case if I will try to assign XYLayoutData to the E2, code will be generated successfully, but runtime will probably fail with ClassCastException in the draw2d.

In case if E1 will have LayoutData (say with vertical = true, alignment = Alignment,CENTER) and E2 will NOT have any layout data, the code will not fail, but E1 will take the full space of R and E2 probably won't be shown on the result diagram (details are dependent on the d2d implementation).

How do the Alignment options map to draw2d?

  • Q: I had recently opened a defect on Bugzilla relating to how the Alignment in BorderLayout did not make sense. The defect entry is 133281

The mapping is as follows for the BorderLayoutData:

CENTER == FILL -> BordeLayout.CENTER; BEGINNING & vertical -> BorderLayout.TOP; BEGINNING & !vertical -> BorderLayout.LEFT; END & vertical -> BorderLayout.BOTTOM; END & !vertical -> BorderLayout.RIGHT;

After you read it once it makes perfect sense. But when you have no extra help, i.e. during editing, it would be leap of faith to use it.

  • A: It was intentionally done this way (obviously, it does not mean that the way itself is right :)).

We would like to capture the single concept of "alignment" by single classifier in the gmfgraph model. In particular, we want our Alignment enumeration to be independent on the concrete implementation of the generated code, and contain "natural" set of literals specific to the generally accepted concept of "alignment". We hope that 4 literals are enough for this.

The underlying d2d code uses completely different names for alignment constants in each of the layout manager (e.g, my preferred example is the pair of ToolbarLayout.ALIGN_BOTTOMRIGHT and FlowLayout.ALIGN_RIGHTBOTTOM constants).

We have considered the way you suggested (that is, to create something like BorderAlignmentEnum, FlowAlignmentEnum, ToolbarAlignmentEnum with literal names that match underlying d2d constructs) and finally decided that the single Alignment enum makes things easier. At least we hope that for all of implemented layouts (except the border one) the mapping between gmf-Alignment and generated d2d-Alignment construct is clear.

Yes, it makes the BorderLayout to be a little cryptic. E.g., there are 4 possible ways to specify BorderLayout.CENTER constraint (both CENTER and FILL * any value of vertical). The good part of this mapping is that figure constrainted by BorderLayout.CENTER is the only one that really "fills" the parent figure, so this choice does not looks innatural.

The main problem of the current state is the abcence of comments that clearly specifyes intention of the BorderLayoutData#vertical and BorderLayoutData#alignment fields. I hope that it will be corrected soon in the gmf itself rather then only in the gmf-newsgroup.

How can I use GMF's trace functionality?

  • Q: Could someone please give a short summary or a pointer to on how to use GMF's trace functionality.
  • A: GMF Runtime Trace class makes use of the core Eclipse trace framework.

The code for Trace in your source code typically looks something like:

if (Trace.shouldTrace(MyPlugin.getDefault(), MyDebugOptions.TRACE)) {
  Trace.trace(MyPlugin.getDefault(), message);
}

With the intent that if tracing is on for TRACE for MyPlugin, then the message is printed to standout.

MyDebugOptions will have code like:

public static final String TRACE = MyPlugin.getPluginId() + "/trace"; //$NON-NLS-1$

And the .options for your MyPlugin will look like:

org.eclipse.example.myplugin/trace=false

At runtime, you can turn on tracing for MyPlugin by setting the trace to true in the .options file.

The Trace options are available from the Tracing tab in the Debug run configuration. Select "Enable tracing for the selected plug-ins" Then enable debug on the plug-in as well as selecting the trace options.

How can I extend the notation model?

  • Q: I want to apply some changes to the notation model. I'd prefer to do that in the templates and then regenerate the code automatically.

Unfortunately, I cannot generate the given code from the provided Ecore model with the templates from the CVS.

Did you use antoher code generation technology or has the generated code been manually changed such that it cannot be regenerated again?

  • A: The Jet-Template in the Notation plugin is a temporary thing that will be removedsoon; it had not been updated for a while.

This may explain why you get compiler errors when you regenerate; cause you will be using an out dated Jet-Template.

The thing is, you should not regenerate the notation meta-model. You can always extend it by introducing new notation style (defined in your own meta-model)or even extending the Notation Interfaces (like View or Node, in your ownnotation meta model).

But, if you just regenerate the notation meta model this means you will have lots of troubles when we release a new version of the Meta-Model and you will have to keep updating and regenerating. But if you have your meta-model that extend the Notation meta model it will be independent and way easier for you.

How can I add a rectangle to a diagram when created?

  • Q: When i run the GMF project(editor), i get a EMPTY GMF editor with a

palette. I can drag and drop figures to it. But i dont want to do this. I want to add a figure say a rectangle SOMEWHERE IN THE CODE ITSELF to the editor. So whenever i run editor project, i want a GMF editor with that rectangle as the content, along with a palette.

My question, where in the code i should initialize the editor content with a rectangle figure?

Please Could anybody help me in doing this. Is there any sample?

  • A: You could override DecorateView in yourDiagram View Factory and initialize your diagram the way you like, for example:
/**
 *@generated
 */
protected void decorateView(View view, IAdaptable semanticAdapter, StringdiagramKind) {
       super.decorateView(view, semanticAdapter,diagramKind);
       getViewService().createNode(semanticAdapter,view,
               "MyView",ViewUtil.APPEND,true, getPreferencesHint());
}

This will always create a view withthe type attribute on it set to "MyView" as a child of your diagram. This will happen any time an instance of your diagram view is created.

How can I implement drag-n-drop in my diagram?

  • Q: I'd like to implement a drag and drop operation in my GMF diagram editor. I'm not familiar with "DiagramDropTargetListener". Can anyone give me any pointers about how I would go about implementing drag and drop? Or does anyone have an example of drag and drop in GMF? Any assistance would be greatly appreciated thanks.
  • A: I think all you need to do is implement a DiagramDropTargetListener. The getObjectsBeingDropped() method needs to return get the thing you are dropping onto the editor. If you return EObjects in this list, for which your graphical editor already knows how to create views for, then the DiagramDragDropEditPolicy should work as is. Otherwise, you will have to subclass this editpolicy as well.

You need to register your DiagramDropTargetListener in your editor class. e.g.

protected void initializeGraphicalViewer() {
  super.initializeGraphicalViewer();

  /* Add a drop target listener for my drop events */

  getDiagramGraphicalViewer().addDropTargetListener(myDiagramDropTargetListener);
}

Is there a way to conditionally enable/disable functionality in my diagram?

  • Q: Let's suppose I've got a GMF editor (generated by M3), and for certain users I'd like to allow editing, but for other users I'd just like to show live data in my edit parts, and not allow editing.

1. Is there a way I can turn off edit capability for certain users?

2. Is there a way to conditionally hide the pallette for those same users?

3. Also, could I get rid of the toolbar buttons for arrange, font selection, etc. ? I'd also like to grey out the menu bar items for these functions.

You get the general idea. Basically, some users should be able to edit everything, other users should be in a "read only" mode with as little editing clutter as possible.

  • A: The Palette Service, Contribution Item Service (i.e. toolbar buttons, diagram menus), and Modeling Assistant Service (diagram popup bars, connection handles) can be filtered based on Eclipse capabilities (known as activities in the Eclipse API). This works in the same way that Eclipse would filter its popup menu contributions -- you define an activity (capability) that is matched to a plugin (or file, directory) and any UI contributions made in that plugin will not be enabled if the cability is not enabled. Look in the Eclipse help for info on this (search for "activities" in the Eclipse help).

You could define an activity that is enabled for certain users and disabled for others. Then you can match this activity to the plugin where you contribute a palette, toolbar buttons, etc. I guess to disable all diagram editing you could try matching this activity to the diagram.ui plugins, but this would disable editing for all GMF diagram editors if the user was also using other GMF diagram editors, so I'm not so sure that this is the best idea.

How can I access the Editor from an EditPart?

  • Q: I want to get instance of editor from EditPart. can someone show me the way to do it?
  • A: This should do it:
EditPartViewer targetEditPartViewer = editPart.getViewer();
IEditorReference editorReferences[] = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
for (int i = 0; i < editorReferences.length; i++) {
  IEditorPart editor = editorReferences[i].getEditor(false);
  if (editor instanceof GraphicalEditor) {
    GraphicalEditor graphicalEditor = (GraphicalEditor) editor;
    EditPartViewer anEditPartViewer = (EditPartViewer) graphicalEditor.getAdapter(GraphicalViewer.class);
    if (targetEditPartViewer.equals(anEditPartViewer)) {
      System.out.println("Found the editor");//$NON-NLS-1$
    }
  }
}

How can I build a diagram programmatically?

  • Q: Could anyone sketch briefly what do I need to do to allow in a generated editor placing of several elements programmatically?

For example, I have a domain element Process, which upon creation with a tool on the Diagram surface, should also show on screen around it two or three other domain elements and connections with them. So I need to know (roughly), what command structure and where do I need to do this, and how I access the coordinates of the element so I can position the new ones properly, these sorts of things...

I want to know the architecturally "good" place to hook to in the generated code, so that I can perform the necessary step to build a (piece of the) diagram. Basically, some of the diagram elements the user builds using the tool pallete and drawing, while some the tool instantiates programmaticaly. The programmatic behavior starts from the user selecting and "drawing" a particular element, which should also bring along (onto the diagram) some other elements - this I determine dynamically, so I cannot model it statically. To do this I need to (a) hook to the action the user made, (b) build the proper actions. (b) you explained already, but for (a) I think I need to use the Command infrastructure.

As far as I know, the framework creates "requests" to pass to the policy objects, which then build and return "a structure of commands", that the framework executes at some point to get the things done. So I need to hook to one of the getCommand type of calls and add additional commands to make (b) work. I also saw that there exists a command infrastructure for domain elements (through semantic policies) and command infrastructure for notation elements (through edit policies?), but I miss where these two come/link together in the generated code and in what order.

  • A: I would GMF architecture on 3 layers (models):

- domain model - notation (view) model - editparts (GEF) model

First model is and instance of your metamodel described in .ecore file. All the elements could be created in this model using an API generated for you by EMF. Second model is internal GMF model which bound some domain model elements with the diagram elements (make domain model elements visible on diagram in some particular place) Third model is a native GEF model and will be created/updated by GMF code automatically based on the contents of Second model.

So, mainly your question is how to create correct instances of notation model elements and specify bounds/bendpoints for them. Notation model elements are located in org.eclipse.gmf.runtime.notation package and derived from common superclass "View".

You can create new notation model elements either directly by calling corresponding Factory method or (I suggest this way) by referencing ViewService methods. You can take a look on the generated *InitDiagramFileAction. This class contains a code which created View model based on an existing domain model, so you can understand how to call ViewService from that place.

The second task is to set bounds/bendpoints for newly created Nodes/Edges. This AFAIU could be done using Node.setLayoutConstraint() or Edge.setBendpoints() methods. It's better to ask somebody from our runtime team concerning the details of these methods, but it seems like they are quite simple and you should just create new instance of Bounds or RelativeBendpoints and set corresponding value to them.

Currently GMF allows to generate the code which will automatically update View model based on the contents of domain model (see *CanonicalEditPolicy generated) but we do not support the possibility to invoke this update process manually. We have a plans to implement this functionality in future. So, in future you can simply create domain model elements, invoke corresponding update process and then set some positions for newly created view elements or invoke an automatic layout.

Concerning creation several domain and notation model elements I can suggest you to try to understand how it works now by debugging the code

generated by GMF. ;-) Here are some ideas which will help you understand key points in the generated + runtime code:

For the creation/deletion of domain model elements, we have a separate EditPolicy - *ItemSemanticEditPolicy. This EditPolicy contains methods "getCreateCommand(CreateElementRequest req)" and "getDestroyElementCommand(DestroyElementRequest req)". It is important that getCreateCommand method should exists in an EditPolicy which corresponds with the an element (installed for the corresponding EditPart) there you would like to create new one. For example, if you have to create something on diagram, getCreateCommand of diagram's *ItemSemanticEditPolicy have to be modified in accordance. getDestroyElementCommand() should be located in an EditPolicy corresponds to the element you would like to destroy. In case of node on the diagram, on pressing "del" on this node, getDestroyElementCommand() of *ItemSemanticEditPolicy installed on Node editpart will be called.

Concerning creation of view (notation) model elements, it is not so clear for me. I can see that CreationEditPolicy of an element will redirect control from getCommand() method to getCreateElementAndViewCommand() one. In getCreateElementAndViewCommand() first of all, semanticCommand will be created. This command will be created in accordance with the logic which I've described above. In other words, this command will wrap command returned by corresponding *ItemSemanticEditPolicy. On the next step, viewCommand will be created by calling getCreateCommand(request). AFAIU, viewCommand will wrap all command which should create notation model elements. You can see that getCreateCommand() method of this editpolicy just creates new CreateCommand() for each CreateViewRequest.ViewDescriptor from the request. So, to achieve your goal you have to put several CreateViewRequest.ViewDescriptor into the create request.

Finally, I think you have two options: either override CreationEditPolicy.getCreateCommand(request) for the editpolicy which will be installed on your EditPart or by putting several ViewDescriptors into CreateViewRequest and it is a bit more tricky - you have to override CreateUnspecifiedTypeRequest.createRequests() finally for the specific palette tool.

I'm not sure that there is no other ways to achieve this goal in runtime, but I hope runtime team will correct me if I've missed something.

Overriding the CreationEditPolicy is probably the simplest option for you right now. If you override the CreationTool that is used by the palette, you would not get this behavior for free if your "process" type were created using the connection handles and popup bars. You would also have to override the CreationTools used by these mechanisms.

We could add support for a "MultipleViewElementType" in GMF similar to how we handle the UnspecifiedElementType. This ElementType could hold multiple element types so that when the CreateViewRequest or CreateViewAndElementRequest is created in the CreateViewRequestFactory it would create multiple view descriptors. If we did this, and your process type was a "MultipleViewElementType" you would get everything for free. These are just my thoughts right now. Feel free to log an enhancement request (and to provide a patch :-) ).

You may want to consider arranging the new shapes instead of setting their locations. Try sending an ArrangeRequest after you have created all the shapes in your CreationEditPolicy to see if the outcome is acceptable.

For future reference, if you want to support drag and drop of your process type from a domain model explorer (if you have such a thing) instead of creation from the palette, you will need to override DiagramDragDropEditPolicy similar to how you will override CreationEditPolicy to create the views for the other elements around the process.

Comment 1: You don't have the domain element at command creation time in the getCreateCommand() method.

Generally, if I need something that is only available at command execution time, then I just put the work I am going to do in the execute() method of another command. So, you could change Alex's original suggestion:

// Creating the rest of the notation model elements: EObject createdObject = (EObject) descriptor.getAdapter(EObject.class); EObject firstAdditionalObject = getFirstAdditionalObject(createdObject); CreateViewRequest.ViewDescriptor firstAdditionalDescriptor = new CreateViewRequest.ViewDescriptor(new EObjectAdapter(firstAdditionalObject), EcoreDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT); cc.compose(new CreateCommand(firstAdditionalDescriptor, (View)(getHost().getModel())));

to something like this (pseudocode only):

cc.compose(new Command() { void doExecute() { // Creating the rest of the notation model elements: EObject createdObject = (EObject) descriptor.getAdapter(EObject.class); EObject firstAdditionalObject = getFirstAdditionalObject(createdObject); CreateViewRequest.ViewDescriptor firstAdditionalDescriptor = new CreateViewRequest.ViewDescriptor(new EObjectAdapter(firstAdditionalObject), EcoreDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT); Command createCommand = CreateCommand(firstAdditionalDescriptor, (View)(getHost().getModel()); createCommand.execute(); } });

Comment 2: Regarding the creation of a new CreateCommand (in the line above).

If the above works fine, you can ignore this comment, but it is a suggestion based on my experience. Instead of creating the CreateCommands yourself, I would suggest sending a CreateViewRequest to the host editpart (i.e. the diagram editpart). So instead of doing this (from above):

CreateViewRequest.ViewDescriptor firstAdditionalDescriptor = new CreateViewRequest.ViewDescriptor(new EObjectAdapter(firstAdditionalObject), EcoreDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT); Command createCommand = CreateCommand(firstAdditionalDescriptor, (View)(getHost().getModel()); createCommand.execute();

I would suggest something like:

CreateViewRequest.ViewDescriptor firstAdditionalDescriptor = new CreateViewRequest.ViewDescriptor(new EObjectAdapter(firstAdditionalObject), EcoreDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT); Command createCommand = getHost().getCommand(new CreateViewRequest((firstAdditionalDescriptor)); createCommand.execute();

Why? You never know how your code is going to evolve. If you follow the paradigm of sending requests to get a command to accomplish a certain task it will avoid having to make changes throughout your code in the future. For example, let's take your case where you are creating a view for a model element of type X. Let's say in the future, for every view that gets created for a model element of type X, someone now wants to do something else as well. Someone might go and add another command to be executed in an editpolicy in response to a request to create a view for a model element of type X. If you create the CreateCommand yourself your use case would not get this additional behavior.

If this point isn't clear, don't worry about it. However, in general, it's best to send requests to get commands when possible instead of creating the commands yourself.

Comment 3: Creating the connections that you want created between your new shapes when you create a "process" from the palette

It is a bit more complicated to create the requests or create the commands to create the new connections you want to add in the CreationEditPolicy in this manner. To benefit from all the infrastructure GMF has to offer, I would suggest you do not create your connection views here, but instead in response to a RefreshConnectionsRequest. GMF will send a RefreshConnectionsRequest in a few different scenarios when new shapes are added to the diagram. For example, if you were to drag elements from a domain model explorer to the diagram, it will refresh all the connectors. This is probably the behavior you want if you ever drag one of your process elements and its related elements from a domain model explorer (if you had one) to the diagram. It would automatically draw connections for all the semantic relationships that exist. Therefore, I would suggest you have an editpolicy that will create the connection views representing the semantic relationships in your model in response to a RefreshConnectionsRequest. Unfortunately, we do not have an example of this currently in GMF (i.e. the RefreshConnectionsRequest is never responded to). Basically, the idea would be to find all the relationships between your domain elements from the views in the RefreshConnectionsRequest and send a request to create a connection for each relationship.

Comment 4: Arranging your new shapes

To send a request to perform a layout of your shapes, do something like this: ArrangeRequest arrangeRequest = new ArrangeRequest(RequestConstants.REQ_ARRANGE_DEFERRED); arrangeRequest.setViewAdaptersToArrange(a list of adapters to all the shapes you will create, this list of adapters has to be created at command creation time, but they are only adaptable at command execution time); Command arrangeCommand = getHost().getCommand(arrangeRequest); and add this command to the one returned.

If you don't like the way it arranges your shapes, look into providing a custom layout provider. Again, this will ensure that wherever GMF does an arrange (e.g. Arrange All menu item) your layout will be called.

How can I synchronize editing domains?

  • Q: I have created a Navigator for my EMF model using the CommonNavigator frameworking. I am using org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain to load the model. I can edit the model from the navigator via menus and a properties view.

I have also created a GMF diagram editor for my model. I understand that GMF uses the org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain.

Now I would like to link these together so that changes in one show up in the other. Is this possible? The following suggests that it is possible from an EMF stand point: https://bugs.eclipse.org/bugs/show_bug.cgi?id=60224

Maybe I need to use MEditingDomain in my navigator instead of AdapterFactoryEditingDomain. Any suggestions?

I would also like to have multiple GMF editors open against the same model simultaniously also. I suspect the solution is similar.

  • A: I assume that you are loading the same resource separately in the navigator and in the diagram editor. That already might not be something that you would ideally want to do (depending on the size of your models). You can use the MListener API with the MEditingDomain to listen for changes in the diagram editor and synchronize them with changes in the navigator (by attaching your own EContentAdapter to that resource set).

Or, you could use an MEditingDomain in the navigator (distinct from the diagram editor's MEditingDomain) so that at least you can use two MListeners to synchronize changes.

The third option is is to use the same MEditingDomain for both the navigator and the diagram editor. Then, no complex synchronization code would be required. I think this is probably the best option. It would allow you to implement JDT-like editing behaviour, in which every edit implicitly saves the resource unless that same resource is also open in a diagram editor, in which case the editor is responsible for saving. This is easiest and most efficiently done with a single resource in a single resource set in a single editing domain, shared by both the navigator and the editor.

When an editor is not open, you can decide on a possible strategy for managing open resources for displaying contents of the navigator. How to determine when a resource can be unloaded if the navigator no longer needs it etc.

I think the multiple-editors-on-the-same-model scenario is different. The trick there is to decide what users will expect. Will they expect each editor instance to have its own buffer (as is common with Eclipse editors)? This would mean that each editor needs a separate in-memory copy of the resource and must prompt the user when on-disk changes are detected, whether to refresh from disk or continue editing. I think that this is the likely expectation, because where an Eclipse application would show multiple editors for different views of a model, they is usually presented in tabs of a single multi-page editor (as with PDE manifest editors). In this case, you would need each editor to have a distinct resource set (and, hence, MEditingDomain) because a single resource set can only load one copy of a resource. It will get very confusing, though, if your application supports cross-resource references, which will cause multiple resources to load into the resource set of each editor, creating an NxM matrix of mayhem.

BTW, the "correct" way to obtain the MEditingDomain for an object that you are editing is by the MEditingDomain.getEditingDomain(Resource) method. This will ensure that you get the right domain, in case your object is not managed by the singleton. In the new EMF-TX API, this would be TXEditingDomain.Factory.INSTANCE.getEditingDomain(ResourceSet).

What's the recommended way to allow for the editing of attributes?

  • Q: I want to edit the EAttributes of an EObject which is represented as a graphical

node in the diagram. However, the way this is done certainly is a question of style.

I see the following options:

- use compartments and let the user edit directly in the diagram

   should be used only for a couple of prominent attributes to avoid
   overloading the diagram

- use the Property View by adding a new category to the Advanced tab using standard EMF property descriptors (similar to the Notation styles of GMF)

   this is not very nice since items are ordered alphabetically rather than
   by meaning

- use a custom additional property view tab similar to the Appearance tab with its style editor and equip it with sort of a form for the desired fields

   this would be only useful if the (contents of the) tab could be switched
   depending on the current selection including the case that the whole tab
   is hidden if not appropriate
   Is this possible?

- use a dialog which e.g. is opened from the context menu of the current selection. This dialog could be implemented using a generic framework similar to the field editors of the preferences

  • A: You can make the sections in a custom property tab context-sensitive, and the entire tab will be hidden if there are no appropriate sections to be shown on the tab. The way to do this is by declaring the input type(s) that are acceptable for your property section. You can modify or adapt the workbench selection using a property section filter, and the modified result will be tested against the specified input type(s).

For example, to contribute a property tab and section only for logic Circuit elements on a logic example diagram, you could use the GenericModelElementFilter that adapts the selected edit part to EObject. The EObject is then tested against the input type for Circuit.

<extension point="org.eclipse.wst.common.ui.properties.propertySections">
<propertySections ...>
<propertySection
tab = "MyCircuitTab"
filter =
"org.eclipse.gmf.runtime.diagram.ui.properties.filters.GenericModelElementFi
lter"
...>
<input type
="org.eclipse.gmf.examples.runtime.diagram.logic.model.Circuit"/>
</propertySection>
<propertySections>
</extension>

How can I activate the 'snap back' feature on links?

  • Q: Am I right if I assume that 'snap back' means that a connection label returns to it's original location? And if so, how can I activate this feature?
  • A: You are correct.

As an end user, right-click a connection label and choose Format > Snap Back. This uses the SnapBackAction.

As a GMF user, send a new Request(RequestConstants.REQ_SNAP_BACK) to a LabelEditPart. The LabelSnapBackEditPolicy handles the request.

How can I add a bookmark to an EMF element?

  • Q: I want to add a bookmark marker in the Eclipse Bookmarks view that is linked to an EMF object in my application. I thought this might be part of the GMF general support for EMF, and did find an IBookmark in org.eclipse.gmf.runtime.common.ui.resources, plus a MarkerNavigationService in common.ui.services. But I have not sorted out what/how GMF services framework works...

Any quick tips in employing the marker service to create an Action in my application for creating a new bookmark, and navigating from a bookmark to that object in my editor/outline would be very much appreciated!

  • A: Here are some quick tips to help you get started.

First, you can hook into the global action handler service, hook into the Eclipse global actions yourself, or create your own independent action. If you chose the first option, the corresponding provider to use is org.eclipse.gmf.runtime.diagram.ui.providers.ide.providers.DiagramIDEGlobalActionHandlerProvider. This takes care of most of the work for you, and you can understand it more by looking at

org.eclipse.gmf.runtime.diagram.ui.internal.resources.AddBookmarkHelper.

As for the service, a tip would be to start by extending org.eclipse.gmf.runtime.emf.ui.providers.marker.AbstractModelMarkerNavigationProvider and be sure to implement the doGotoMarker(IMarker marker) to select the object in your editor by doing select and reveal on the Viewer and passing in the edit parts that correspond to the marker.

Markers are attached to the resource (file) in Eclipse. There is an IResource.createMarker() method you need to use. A Bookmark is a Marker attached to the resource with a specific id. The IBookmark and IMarker interface are conveniences that define the id for GMF bookmarks and markers.

To create a bookmark within a location in an EMF file, which is what you want, you need to provide additional attributes to the marker. This is done using the IMarker.setAttributes() method.

We do not have an example of marker creation in GMF, but what you can do is something like:

EObject element = something;
HashMap attribMap = new HashMap();
attribMap.put(IBookmark.ELEMENT_ID, EObjectUtil.getID(element));
IResource resource = ResourceUtil.getFile(element.eResource());
IMarker marker = resource.createMarker(IBookmark.TYPE);
marker.setAttributes(attribMap);

The MarkerNavigationService simply calls on the editor that implements IGoToMarker.goToMarker() to navigate to the marker from the resource. Double clicking on a bookmark does the same goToMarker on the editor for the resource. In this case you have the element id and you use this to get the EObject and then highlight as you wish on your diagram.