If you already enlarged a EClass in the diagram, you may have observed that the shapes inside the rectangle kept their size (EClass name is not longer in the centre and the line separator is too short). Graphiti provides the concept of layout features, which mainly supports the recalculation of positions and sizes inside the pictogram model.
Theoretical such functionality could also be implemented by providing resize functionality, but using a layout feature for this is the recommended solution.
A layout feature has to implement the interface ILayoutFeature. Instead of implementing it directly you should extend one of the available base classes. In this example we extend the base class AbstractLayoutFeature.
In this case we have to implement/overwrite two methods:
You can see the complete implementation of the move feature here:
package org.eclipse.graphiti.examples.tutorial.features;
public class TutorialLayoutEClassFeature
extends AbstractLayoutFeature {
private static final int
MIN_HEIGHT = 30;
private static final int
MIN_WIDTH = 50;
public TutorialLayoutEClassFeature(IFeatureProvider
fp) {
super(fp);
}
public boolean canLayout(ILayoutContext context)
{
// return
true, if pictogram element is linked to an EClass
PictogramElement pe = context.getPictogramElement();
if (!(pe instanceof
ContainerShape))
return false;
EList<EObject> businessObjects = pe.getLink().getBusinessObjects();
return businessObjects.size() == 1
&& businessObjects.get(0) instanceof EClass;
}
public boolean
layout(ILayoutContext context) {
boolean anythingChanged =
false;
ContainerShape containerShape =
(ContainerShape) context.getPictogramElement();
GraphicsAlgorithm containerGa = containerShape.getGraphicsAlgorithm();
// height
if (containerGa.getHeight() <
MIN_HEIGHT) {
containerGa.setHeight(MIN_HEIGHT);
anythingChanged = true;
}
// width
if (containerGa.getWidth() <
MIN_WIDTH) {
containerGa.setWidth(MIN_WIDTH);
anythingChanged = true;
}
int containerWidth = containerGa.getWidth();
for
(Shape shape : containerShape.getChildren()){
GraphicsAlgorithm graphicsAlgorithm = shape.getGraphicsAlgorithm();
IGaService gaService = Graphiti.getGaService();
IDimension size =
gaService.calculateSize(graphicsAlgorithm);
if (containerWidth != size.getWidth()) {
if (graphicsAlgorithm
instanceof Polyline) {
Polyline polyline = (Polyline) graphicsAlgorithm;
Point secondPoint = polyline.getPoints().get(1);
Point newSecondPoint =
gaService.createPoint(containerWidth, secondPoint.getY());
polyline.getPoints().set(1, newSecondPoint);
anythingChanged = true;
} else {
gaService.setWidth(graphicsAlgorithm,
containerWidth);
anythingChanged = true;
}
}
}
return anythingChanged;
}
}
Additionally the feature provider has to deliver our newly created feature (overwrite the method getLayoutFeature).
This implementation can be seen here:
@Override
public ILayoutFeature
getLayoutFeature(ILayoutContext context) {
PictogramElement
pictogramElement = context.getPictogramElement();
Object bo = getBusinessObjectForPictogramElement(pictogramElement);
if (bo instanceof
EClass) {
return new TutorialLayoutEClassFeature(this);
}
return super.getLayoutFeature(context);
}
Finally we have to call the layout feature at the end of the add method of the TutorialAddEClassFeature, as shown in the following code snippet.
This causes that the layout (especially the layout restrictions like minimum size) are applied after adding a EClass.
public PictogramElement
add(IAddContext context) {
//
... EXISTING CODING ...
// call the layout feature
layoutPictogramElement(containerShape);
return containerShape;
}
Now start the editor again and test it: Try to resize a EClass. You see that the class name stays in the centre and the line separator will be automatically extended.