Graphical Modeling Framework/Archived Newsgroup Q and A

From Eclipsepedia

< Graphical Modeling Framework
Revision as of 10:59, 7 November 2006 by Richard.gronback.borland.com (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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 has a reference to 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: Currently 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:

    EObjectmyModel = (EObject)myEditPart.getModel();

then on your model you can call eContainer()

    EObjectmyParent = 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?

  • A: 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.