Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Graphical Modeling Framework/Models/GMFGraph



GMF
Website
Download
Dev Builds
Update Site releases milestones
Community
Mailing ListNewsgroupIRC
Bugzilla
Open
Help Wanted
Bug Day
Source
GMF Notation: View CVS repo

GMF Runtime: View CVS repo
GMF Tooling: View Git Repo, GitHub


Metamodel

Graphical.png

Scenarios

Scalable/resizable figures

Newsgroup post

I have declared DiamondShape implementation as attached one and placed it into the correct package. In the gmfgraph.FigureGallery I have created the CustomFigure with <figures xsi:type="gmfgraph:CustomFigure" name="PortFigure" qualifiedClassName="org.eclipse.gmf.examples.taipan.gmf.editor.edit.parts.DiamondShape"/>

Please make sure that your gmfgraph.Node referencing this CustomFigure instance has resizeConstarint = "NSEW".

/*
 * Copyright (c) 2006 Borland Software Corporation
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Michael Golubev (Borland) - initial API and implementation
 */
 
package org.eclipse.gmf.examples.taipan.gmf.editor.edit.parts;
 
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Rectangle;
 
public class DiamondShape extends Shape {
	private int[] myCachedPath = new int[8];
 
	/**
	 * @see Shape#fillShape(Graphics)
	 */
	protected void fillShape(Graphics graphics) {
		Rectangle r = getBounds();
 
		int centerX = r.x + r.width / 2;
		int centerY = r.y + r.height / 2;
 
		setPathPoint(0, centerX, r.y);
		setPathPoint(1, r.x + r.width, centerY);
		setPathPoint(2, centerX, r.y + r.height);
		setPathPoint(2, r.x, centerY);
 
		graphics.fillRectangle(getBounds());
	}
 
	/**
	 * @see Shape#outlineShape(Graphics)
	 */
	protected void outlineShape(Graphics graphics) {
		Rectangle r = getBounds();
 
		int centerX = r.x + r.width / 2;
		int centerY = r.y + r.height / 2;
 
		graphics.drawLine(centerX, r.y, r.x + r.width, centerY);
		graphics.drawLine(centerX, r.y, r.x, centerY);
		graphics.drawLine(centerX, r.y + r.height, r.x + r.width, centerY);
		graphics.drawLine(centerX, r.y + r.height, r.x, centerY);
	}
 
	private void setPathPoint(int index, int x, int y){
		myCachedPath[index * 2] = x;
		myCachedPath[index * 2 + 1] = x;
	}
 
}

How can I start with CustomFigures

Newsgroup thread

How can I use CustomLayout and what is purpose of the CustomAttribute

From the newsgroup thread

gmfgraph.CustomLayout is just a gate to the custom implementation of the org.eclipse.draw2d.LayoutManager class. Thus there is in fact 2 questions -- how to write draw2d Layout manager and how to plug it into the gmfgraph. This covers only the latter.

Imagine you have com.xyz.SuperLayout class in the com.xyz.misc plugin. The SuperLayout class has method setBoolParam(boolean) and public instance field int myIntParam; It also expects the instanceof superLayoutData that has setter setStringParam(String s).

To plug this into gmfgraph you need:

  1. Create separate ResourceGallery, set implementation bundle to "com.xyz.misc"
  2. Create figures structure.
  3. In the container node create CustomLayout, set fqn = "com.xyz.SuperLayout". Note that bundleName property of CustomLayout is deprecated and not used, it does not make sense to change it.
  4. In the just created Custom Layout create custom attribute, set name = boolParam (or BoolParam -- it doesnot make sense) -- the name is derived from setter name, value = (say) "false" or "42 / 2 >= 21".
  5. Create one more custom attribute, name = "myIntParam" (derived from field name), value = "42", isDirectAccess = true.
  6. In the child figure create CustomLayoutData, set fqn = "com.xyz.SuperLayutData", repeat step 4 for custom attribute "StringParam" if needed.

Note that values set at the steps 4, 5 are considered opaque and just generated into the setter call or assignment statement as is. Thus, to set the string value "MG" for custom attribute StringParam you need to set value = "MG" (with quotes).

What to do with strange ClassCastException while working with (say, opening in editor, validating or generating code from) GMFGraph resource.

The most common reason of ClassCastException like the one described in the newsgroup thread is name collision in the gmfgraph resource. GMFGraph declares the name attribute for Node's and Figure's as ID-attribute so all names used in given resource should be different.

I really want some GMFGraph notions to have the same name. Is there the way to avoid that ClassCastException?

Yes, sometimes there may be good reasons to have diffent GMFGraph notions with the same name. After all, Compartment's name is shown at the diagram, and it may be usefull to setup different compartments for different nodes to be shown with same label. Just define them in different resources.

There's a legacy GEF figure code and I'd like to use it with GMF

tbd (check for MapMode, etc)


I need a figure that is similar to UML package

There's no need to use custom figure, just use some GMFGraph magic...tbd TODO put link to newsgroup discussion If you like to have custom anchor behaviour (e.g. no link attaching to package title box), you need to hand code it (there was a posting in the newsgroup).


How to create several figures at once

I.e. when creating some element, few additional should be created as well. tbd Need to find better place for this, as it's not gmfgraph topic


SVG

Both full and lite runtime clients may use org.eclipse.gmf.runtime.lite.svg plugin (currently obtainable via the gmf-sdk-experimental-2.2.0 distribution). This plugin adds dependency to Batik library and provides SVGFigure class that is a Draw2D figure that's capable of rendering SVG documents within it's bounds, in paintFigure(Graphics) method.

In gmfgraph model you could create SVGFigure element. It's recommended to create it within a figure gallery that specifies org.eclipse.gmf.runtime.lite.svg implementation bundle. You must specify documentURI property; SVG content will be taken from there. SVGFigure may contain a number of properties (SVGProperty element). Each property translates to a getter and setter methods that obtain attribute value from SVG document element or modify their values.

SVGFigure:

  • descriptor: Select descriptor that is associated with this Figure
  • Document URI: Example URI to point to image in the diagram plugin platform:/plugin/My.diagram/images/MyFigure.svg
  • Name: The name
  • No Canvas Height: true/false  ??
  • No Canvas Width: true/false ??

SVGProperty:

  • query: XPath query that must select org.w3c.dom.Elements.
  • attribute: Name of attribute that will be read or modified.
  • type: Type of the property; now may be String or Color.
  • getter: Name of the getter method; if null then method is not generated.
  • setter: Name of the setter method; if null then method is not generated.
  • callSuper: If true then generated setter will call super implementation in the end; useful when overriding methods like setBackgroundColor(Color).

Pitfalls:

  • Be aware of namespaces while writing XPath expressions; see this or this for more details.
  • SVGFigure does not inherit colors from it's parent figure. You must specify setBackgroundColor and setForegroundColor properties and you must set colors directly to SVGFigure.

Evolution of GMFGraph Metamodel

(note: this section is in need of a cleanup.)

Recently you may have noticed that something happened to the GMF Graph metamodel. All your previously created resources got a migration-prompting message. Moreover, it seemed you didn't even know how to create gmfgraphs anymore.

Firstly, most of your figures are gone, and got replaced with some odd Figure Descriptors. Well, figures are not actually gone, if you take a closer look, they are hidden inside the figure descriptor. Nevertheless, you may have a strange feeling about some other figures, which may still exist in your gallery without being wrapped by a Figure Descriptor as others did.

You may think GMF's developers minds' are in some kind of mess. However, withhold judgment for a bit and let us first demonstrate the opportunities that the changes offer moving forward. So sit back and get ready to get involved in the evolution.

First, let us get a bird’s-eye view of the main changes using the visual notation:

Before: Before.png

After: After.png

To summarize, the changes you can observe above here, back link for ‘referencingElements’ has been removed, while the way Diagram Element references its Figure has been transformed with the help of introducing two new entities, called FigureDescriptor and ChildAccess. Obviously, some cracks did appear in their relationship, or maybe it was something awful to come between and fall them out.

Well, nothing actually tragic. We have been dreaming a long time of easing their connection as much as possible. Now the time had come to put our cards on the table. We have been thinking of pluggable Figure Galleries to be referenced from anywhere.

Consider basic.gmfgraph as an existing example you had probably seen already. As long as we had ‘referencingElements’ to list all the elements using the figure, every your usage of that pretty figure painfully affected the whole gallery. It was just as if making every new shot of a famous ancient painting would add a stroke on its canvas – horrible!

Besides, the main thing ‘referencingElements’ being used, is for discovering, whether an inner figure (nested within some other one) was referenced from somewhere, so that it would need an instance field to access it. We could not deal with such situations due to having no way to distinct element’s references for toplevel and nested figures, only the silent general ‘figure’ was all we had on the element side.

Therefore, Figure itself involved two aspects of being a diagram element’s figure: the abstract figure shape description and its physical construction description as something real, that you may touch and reference. Nowadays we have finally come to the solution, helping us to separate these design concepts. It is the Figure Descriptor, exactly.

The Figure Descriptor thing describes structure of a figure, and represents a real part of the Figure concept. Besides, it is the only thing you can reference from within your Diagram Element. You can also think of it as if Figure got a grip to handle, or even as if it was put, along with all its child content, into a basket with a firm grip called Figure Descriptor. If you were a Diagram Element yourself and had a Gallery full of Figures to use, firstly you pick up Descriptor basket at the entry to that Gallery, then slightly stroll around its shelves full of figures, choosing the prettiest one, and put it to your basket, following you way to the cash desk. :)

However, there is one more thing left unclear. The basket concept is fine, but what if I want to use some nested figure for my element. Consider, for instance, declaring Diagram Label in order to have a list of the children’ names for some Father one. Internal labels are the most common case. Then what should you put in your basket, still the Father’s toplevel one? Actually, yes. Never forget, we are GMF, and our basket is quite skillful indeed. But what can be more useful than pockets? Right, Child Accesses, as they are our advanced, named pockets. So what you need to reference child figure is wrap its toplevel container with Descriptor, and then create new Child Access within it, pointing to the desired nested shape. Finally, that is it and you are done.

Everything appeared to turn pretty simple, don’t you think? But just imagine all brilliant advantages, all the incredible opportunities we get for freeing up the hands of artists and other people to create their own, unique, extraordinary Figure Galleries, that they will be able to exchange and share. Gosh, we could launch an industry over that! Of course, if we have YOU involved too, right?

To make a long story short: To access figures within the Figure Descriptors you add a child access within the Figure Descriptor and bind it(with its figure property) to the figure you want. You can then access the figures within the Figure Descriptor stating that the accessor is the child access.


How to add a new kind of Figure to the GMFGraph model and editor?

There is a generic workflow to add a figure to the GMFGraph editor and to have code generated for them. Here are the steps:

  1. Ensure that you have set up a development environment to tweak GMF-Tooling.
  2. Select a subclass of org.eclipse.draw2d.Figure you want to add to the model.
  3. Open the gmfgraph.ecore, and add to it a class for your new Figure. Make it extend the RealFigure class
  4. Add to it the fields that are necessary for you to configure the Figure
  5. Reload gmfgraph.genmodel, and regenerate org.eclipse.gmf.graphdef, org.eclipse.gmf.graphdef.edit and org.eclipse.gmf.graphdef.
  6. Edit org.eclipse.gmf.graphdef.codegen/templates
    1. Open Runtime.xpt, and search the block containing lines such as «DEFINE fqn FOR gmfgraph::Polyline»org.eclipse.draw2d.PolylineShape«ENDDEFINE». Add to it a line for your new Figure that maps the gmfgraph figure type to the name of the Figure class
    2. Open Attrs.xpt, and add a block like this one
«DEFINE Init(figureVarName : String) FOR gmfgraph::MyFigure-»
«figureVarName».setMyAttribute("«myAttributeNaeInModel»");
«EXPAND attr::Figure::figureAttrs(figureVarName)-»
«ENDDEFINE»
  1. Share it, by creating a patch and opening a bug!

Back to GMF Documentation

Back to the top