The Graphical Editing Framework (GEF) is a set
of Eclipse plugins for creating editors that support visual editing of arbitrary models.
This framework is very popular and QF-Test has supported recording and playback of GEF
items for a long time (since about version 2.2). It is also a good example for the
power of the
ItemResolver concept (see section 52.4),
gef Jython module contains an implementation of just that
gef module can deal with GEF editors at a generic level and even
support several editors at once. Though reasonable item names are provided out of the
box also for GMF applications, there are limits to what can be determined automatically.
Depending on the underlying model classes, there might still remain some work for you:
Implementing custom resolvers to provide useful names and values for your items.
The actual GEF component is the
FigureCanvas. This control displays
Figures which represent
EditParts. When recording a mouse
click on such an element, QF-Test does not register a pure 'Mouse event' node for
the canvas component with the corresponding (x,y) position but tries to recognize
the object under the mouse cursor. For example, the recorded 'QF-Test component ID' may look
canvas@/Diagram/My ship/ShipLargeCargo (wine)
where "canvas" is the 'QF-Test ID' of the
FigureCanvas component, followed by
the item index of the recognized
EditPart (see section 5.9).
EditParts reside in a tree like hierarchy which
is reflected in the index by a path separator '/'. The names of the individual items
are generated as follows:
EditPartalways reads "Diagram".
As one can imagine, those generated item names may not always be useful. For example, items might be deleted so that the recorded index is not longer valid. Or the generated item name is unstable as "Rectangle 16329001" in the GEF Shapes example: The number is random and when restarting the application a different one will be created. Three options exist to overcome the problem:
/0/1tells nothing about an item.
toString()method of the item's model. It would make live easy for you, but only if the developers are cooperative.
ItemNameResolver2. This is the tough course but unfortunately the most likely scenario. It is covered in the next section.
|Example 52.46: Get started with a GEF ItemNameResolver2|
To ease the installation of the resolver we use the
described in section 52.1. The resolver gets registered for the
FigureCanvas class where the items reside. The default item name
provided by QF-Test is supplied as the last argument to our function
getItemName(). Now run the script, press the record button and then simply
move the mouse over your figures on the canvas - supposing you have created some of
them previously. Note that this first resolver implementation does nothing but print
out out some information into the terminal, something like
name: Rectangle 16329001
The question is now: Does the model of the GEF
EditPart provide any
property that might be used as name for the item? The answer in the case of the GEF
Shapes example is "No", and hopefully you are in a better situation with your
application. To find out insert a line
getItemName() function and run the script again. Now you will
also see the methods of the model when moving the mouse over the items in record
mode. With a bit of luck you will find methods like
getLabel() and can create a resolver like this:
|Example 52.47: A simple ItemNameResolver2|
Let's go back to the GEF Shapes example where we don't have such useful methods. Only geometry information is available for the shapes and that is not really helpful. At least we can distinguish between rectangles and ellipses. To make the item names unique we simply add a child index as shown in the following resolver:
|Example 52.48: An ItemNameResolver2 for GEF Shapes|
With this resolver in place, the item index for a rectangle becomes
where the trailing number is the child index of the item. The above implementation
also provides names for the connections by calling
recursively for the source and the target item of the connection. Checking the types
qf.isInstance() (see section 48.6) will save you the need to import the GEF classes,
something that is not trivial.
Once your resolver is working fine you should move the script into your 'Setup' sequence right behind the 'Wait for client to connect' node. This way the resolver will be registered automatically when the SUT starts.
Usually a GEF editor consists of two parts. Having focused so far on the canvas
where you draw the figures, we now take a look at the palette where you select the
kind of figure to draw (e.g. 'Rectangle', 'Ellipse' or 'Connection'). Its entries
look like tool buttons but actually the palette is a
You will be glad to know that this one works out of the box, that is without
ItemNameResolver2. When you click for example on the
'Rectangle' button, QF-Test recognizes a
/Palette Root/Palette Container (Shapes)/Palette Entry (Rectangle)
item. What will happen when you record a check (cf. section 4.3) for the 'Object value' for this button? You may expect to get the button text 'Rectangle' but in fact the value of this item is
Palette Entry (Rectangle)
The reason is that by default name and value of an item are the same. To alter this
behavior and provide customized values you need to implement an
ItemValueResolver2. This interface is very similar to the
ItemNameResolver2 above. For the palette we can code the
|Example 52.49: An ItemValueResolver2 for the GEF Shapes palette|
getLabel() returns the text as displayed in the palette.
|Last update: 12/4/2023|
Copyright © 1999-2023 Quality First Software GmbH