Most of you aren't developing GEF applications on top of Eclipse RCP - in your case move along there's nothing to see here. However if you're one of the three people out doing GEF development, sit down I have story to tell.
I wanted a label attached to my figures that was wider than the parent figure. The label should be tied to the parent - but not be included in the parents grab handle. The previously suggested solution that I found was to stack the original figure and label in a composite (using a Flow/Toolbar Layout to position the children). Sadly that just created the Ugly Duckling (left figure) and not the Elegant one (see right).
After some more digging I discovered an interface HandleBounds (dig the crazy name), its tailor made for this situation:
HandleBounds Identifies figures which use an alternative rectangle to place their handles. Normally, handles will appear around a GraphicalEditPart's figure's bounds. However, if that figure has an irregular shape, it may implement this interface to indicate that some rectangle other than its bounding rectangle should be used to place handles.
If you ignore the word irregular this solution is tailor made for our problem.
My Solution:
1) Wrap the original figure in a wrapping figure that also includes the label. The wrapping figure grows to be as large as required by the label.
2) Implement the interface HandleBounds on the wrapping figure and get it to report the size of the original figure.
So far so good - but now your connections appear a million miles away from the figure (on the old bounding box). To fix this you need to derive a custom anchor class and override getBox() to return the same rectangle as you used for the HandleBounds (see HandleBoundsAnchor).
Sample code - N.B. This code has been sanitized to avoid reveal corporate details. Its not guaranteed to compile.
public class LabelWrapperFigure extends Figure implements HandleBounds
public LabelWrapperFigure(IFigure wrappedFigure) {
layout = new ToolbarLayout();
layout.setMinorAlignment(ToolbarLayout.ALIGN_CENTER);
layout.setStretchMinorAxis(false);
layout.setSpacing(2);
layout.setVertical(true);
// why didn't flowLayout work??
// FlowLayout layout = new FlowLayout();
// layout.setHorizontal(false);
// layout.setMajorSpacing(2);
// layout.setMajorSpacing(0);
// layout.setMinorAlignment(FlowLayout.ALIGN_CENTER);
// layout.setMajorAlignment(FlowLayout.ALIGN_CENTER);
setLayoutManager(layout);
setOpaque(true);
add(wrappedFigure);
Label label = new Label();
label.setText(" some text ");
label.setTextPlacement(PositionConstants.SOUTH);
add(label);
}
public Rectangle getHandleBounds() {
// Get size from your figure somehow
return wrappedFigure.getBounds();
}
}
public class HandleBoundsAnchor extends ChopboxAnchor {
private final HandleBounds handleBounds;
public HandleBoundsAnchor(IFigure figure) {
super(figure);
// TODO consider requiring a derivation of ModelElementFigure
if (false == (figure instanceof HandleBounds)) {
// This won't compile we've got custom exception code
throw new IllegalArgException();
}
handleBounds = (HandleBounds) figure;
}
protected Rectangle getBox() {
return handleBounds.getHandleBounds();
}
}
If you enjoyed this post, subscribe now to get free updates. In addition you may also find: Eclipse/GEF More questions that answers interesting