package org.eclipse.uml2.diagram.sequence.figures;
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Border;
import org.eclipse.draw2d.BorderLayout;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FlowLayout;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.TreeSearch;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.uml2.diagram.common.draw2d.PileLayout;
import org.eclipse.uml2.diagram.sequence.draw2d.shadow.ShadowStealth;
import org.eclipse.uml2.diagram.sequence.internal.layout.GeometryConstants;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMLifeLine;
import org.eclipse.uml2.diagram.sequence.part.UMLDiagramEditorPlugin;
public class LifelineViewMap {
public static class LifelineShape extends /*RectangleFigure*/InvisibleRectangle {//transparent for shdow master
private final LifelineTailShape myTail;
private final LifelineHeadShape myHead;
private final LifelineLayout myLifelineLayout;
public LifelineShape() {
setOutline(false);
setFill(false);
myLifelineLayout = new LifelineLayout();
setLayoutManager(myLifelineLayout);
myHead = new LifelineHeadShape(this);
add(myHead);
myTail = new LifelineTailShape(this);
add(myTail);
myLifelineLayout.setHorizontalPositions(30, 30);
}
public LMLifeLine.DetailsLayouter getLifelineLayout() {
return myLifelineLayout;
}
public LifelineHeadShape getHead() {
return myHead;
}
public LifelineTailShape getTail() {
return myTail;
}
public IFigure findFigureAt(int x, int y, TreeSearch search) {
IFigure result = super.findFigureAt(x, y, search);
return (result == this) ? null : result;
}
public Label getLifelineStereotypesLabel() {
return getHead().getLifelineStereotypesLabel();
}
public Label getLifelineIdentLabel() {
return getHead().getLifelineIdentLabel();
}
public Label getLifelineDecomposedAsLabel() {
return getHead().getLifelineDecomposedAsLabel();
}
public Label getLifelineRefLabel() {
return getHead().getLifelineRefLabel();
}
public void setDecomposedAsBlockVisible(boolean visible) {
getHead().getLifelineDecomposedAsPanel().setVisible(visible);
}
}
public static class LifelineHeadShape extends RectangleFigure {
private static final Border HEAD_TEXT_MARGIN = new MarginBorder(5, 5, 0, 5);
private Label myStereotypesLabel;
private Label myLifelineIdentLabel;
private Label myDecomposedAsLabel;
private Label myRefLabel;
private IFigure myDecomposedAsPanel;
public LifelineHeadShape(IFigure lifeLineShape) {
setLineWidth(1);
setLifelineHeadText(this);
assert getLayoutManager() instanceof PileLayout;
if (getLayoutManager() == null) {
setLayoutManager(new PileLayout());
}
setBorder(new MarginBorder(0, 0, GeometryConstants.Lifeline.UNDER_HEAD_SPACE, 0));
setMinimumSize(new Dimension(GeometryConstants.Lifeline.MINIMUM_HEAD_WIDTH, GeometryConstants.Lifeline.HEIGHT + GeometryConstants.Lifeline.UNDER_HEAD_SPACE));
}
//Preferred size must be more than minimum size
public Dimension getPreferredSize(int wHint, int hHint) {
Dimension d = super.getPreferredSize(wHint, hHint);
return d.union(minSize);
}
public Label getLifelineStereotypesLabel() {
return myStereotypesLabel;
}
public Label getLifelineIdentLabel() {
return myLifelineIdentLabel;
}
public Label getLifelineDecomposedAsLabel() {
return myDecomposedAsLabel;
}
public Label getLifelineRefLabel() {
return myRefLabel;
}
public IFigure getLifelineDecomposedAsPanel() {
return myDecomposedAsPanel;
}
private void setLifelineHeadText(IFigure headFigure) {
headFigure.setLayoutManager(new PileLayout());
myStereotypesLabel = new Label();
add(myStereotypesLabel);
myLifelineIdentLabel = new Label();
myLifelineIdentLabel.setLabelAlignment(PositionConstants.CENTER);
myLifelineIdentLabel.setForegroundColor(ColorConstants.black);
myLifelineIdentLabel.setFont(UMLDiagramEditorPlugin.getInstance().getDefaultFont());
myLifelineIdentLabel.setBorder(HEAD_TEXT_MARGIN);
IFigure centeredLabel = new Figure();
centeredLabel.setLayoutManager(new BorderLayout());
centeredLabel.add(myLifelineIdentLabel, BorderLayout.CENTER);
headFigure.add(centeredLabel, PileLayout.ALIGN_CENTER);
myDecomposedAsPanel = new InvisibleRectangle();
myDecomposedAsPanel.setLayoutManager(new FlowLayout(true));
myRefLabel = new Label("ref "); //$NON-NLS-1$
myRefLabel.setFont(UMLDiagramEditorPlugin.getInstance().getDefaultBoldFont());
myDecomposedAsPanel.add(myRefLabel);
myDecomposedAsLabel = new Label();
myDecomposedAsPanel.add(myDecomposedAsLabel);
//[#18037]container.setForegroundColor(LabelUtil.getForegroundColor(nodeEditPart, null));
myDecomposedAsPanel.setBorder(HEAD_TEXT_MARGIN);
//myDecomposedAsPanel.setHorizontalAligment(PositionConstants.CENTER);
//registerInplace(decomposeLabel, nodeEditPart, SD20_LifeLineImpl.STORED_DECOMPOSITION, "decomposedAs");
IFigure centeredContainer = new Figure();
centeredContainer.setLayoutManager(new BorderLayout());
centeredContainer.add(myDecomposedAsPanel, BorderLayout.CENTER);
headFigure.add(centeredContainer, PileLayout.ALIGN_CENTER);
}
}
public static class LifelineTailShape extends RectangleFigure implements ShadowStealth {
public LifelineTailShape(final LifelineShape lifelineShape) {
setOpaque(false);
setFill(false);
setLineStyle(Graphics.LINE_DASH);
setMinimumSize(new Dimension());//to avoid head shrinking
setLayoutManager(new XYLayout(){
@Override
public Point getOrigin(IFigure parent) {
if (parent == LifelineTailShape.this){
return lifelineShape.getClientArea().getLocation();
}
return super.getOrigin(parent);
}
});
}
public IFigure findFigureAt(int x, int y, TreeSearch search) {
IFigure result = super.findFigureAt(x, y, search);
if (result == this) {
int distToLine = Math.abs(getLineAbsoluteX() - x);
if (distToLine >= getLineWidth() + SELECTABLE_WIDTH) {
result = null;
}
}
return result;
}
//CR# 20187
// public boolean containsPoint(int x, int y) {
// int distToLine = Math.abs(myX - x);
// if (distToLine >= getLineWidth() + SELECTABLE_WIDTH) {
// return false;
// }
// return super.containsPoint(x, y);
// }
protected void outlineShape(Graphics graphics) {
Rectangle bounds = getBounds();
graphics.drawLine(getLineAbsoluteX(), bounds.y, getLineAbsoluteX(), bounds.y + bounds.height);
}
private int getLineAbsoluteX() {
return bounds.x + myLineRelativeX;//don't assume that line is always centered, SD layout should set this position
}
void setLineRelativeX(int x) {
myLineRelativeX = x;
}
private int myLineRelativeX;
/**
* don't move children
*/
// CR# 21137
// protected void primTranslate(int dx, int dy) {
// bounds.x += dx;
// bounds.y += dy;
// }
private static final int SELECTABLE_WIDTH = 10;
}
private static class LifelineLayout extends AbstractLayout implements LMLifeLine.DetailsLayouter {
// LMLifeLine.DetailsLayouter methods:
public int getHeadPreferredWidth() {
return myHead.getPreferredSize().width;
}
public int getHeadPreferredHeight() {
return myHead.getPreferredSize().height;
}
public int getHeadTopPos() {
return myHead.getBounds().y;
}
public void setHorizontalPositions(int centerRelativePos, int headHalfWidth) {
myCenterRelativePos = centerRelativePos;
myHeadHalfWidth = headHalfWidth;
myHead.revalidate();
myTail.setLineRelativeX(centerRelativePos);
myTail.revalidate();
}
public int getCenterRelativePos() {
return myCenterRelativePos;
}
public int getHeadHalfWidth() {
return myHeadHalfWidth;
}
//------------------------------------------------------
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
int minWHint = 0, minHHint = 0;
if (wHint < 0)
minWHint = -1;
if (hHint < 0)
minHHint = -1;
Insets border = container.getInsets();
wHint = Math.max(minWHint, wHint - border.getWidth());
hHint = Math.max(minHHint, hHint - border.getHeight());
Dimension prefSize = new Dimension();
Dimension headSize = myHead.getPreferredSize(wHint, hHint);
hHint = Math.max(minHHint, hHint - headSize.height);
prefSize.setSize(headSize);
Dimension tailSize = myTail.getPreferredSize(wHint, hHint);
prefSize.height += tailSize.height;
prefSize.width = Math.max(prefSize.width, tailSize.width);
return prefSize.expand(border.getWidth(), border.getHeight());
}
public void layout(IFigure container) {
Rectangle area = container.getClientArea();
Rectangle headBounds = new Rectangle(area);
headBounds.translate(myCenterRelativePos - myHeadHalfWidth, 0);
headBounds.width = 2 * myHeadHalfWidth;
Dimension headPreferredSize = myHead.getPreferredSize(headBounds.width, -1);
headBounds.height = headPreferredSize.height;
myHead.setBounds(headBounds);
area.y += headBounds.height;
area.height -= headBounds.height;
myTail.setBounds(area);
}
public void setConstraint(IFigure child, Object constraint) {
if (child instanceof LifelineHeadShape) {
myHead = child;
} else if (child instanceof LifelineTailShape) {
myTail = (LifelineTailShape) child;
} else {
throw new IllegalArgumentException();
}
super.setConstraint(child, constraint);
}
private IFigure myHead;
private LifelineTailShape myTail;
private int myCenterRelativePos;
private int myHeadHalfWidth;
}
}