package com.baselet.element.sequence_aio.facet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.baselet.control.basics.Line1D; import com.baselet.control.basics.geom.Line; import com.baselet.control.basics.geom.PointDouble; import com.baselet.control.enums.AlignHorizontal; import com.baselet.control.enums.AlignVertical; import com.baselet.control.enums.LineType; import com.baselet.diagram.draw.DrawHandler; import com.baselet.diagram.draw.TextSplitter; import com.baselet.diagram.draw.helper.ColorOwn; import com.baselet.element.relation.helper.RelationDrawer; import com.baselet.element.relation.helper.RelationDrawer.ArrowEndType; import com.baselet.element.sequence_aio.facet.Message.ArrowType; /** * Class for representing a lost or a found message. * Lost Messages are always on the right side of the lifeline and found messages are always on the left side of the lifeline. * Therefore the message always travels from left to right. * */ public class LostOrFoundMessage implements LifelineOccurrence { private static final Logger log = LoggerFactory.getLogger(LostOrFoundMessage.class); private static final double CIRCLE_RADIUS = 10; private static final double LIFELINE_TEXT_PADDING = Math.max(RelationDrawer.ARROW_LENGTH, CIRCLE_RADIUS * 2) + 3; private final Lifeline lifeline; // private final Lifeline to; private final int sendTick; private final String[] textLines; private final ArrowType arrowType; private final LineType lineType; private final boolean found; /** * * @param lifeline * @param found true if it is a found message, if false it is a lost message * @param sendTick * @param text can be more than one line, but if so the lines must be separated by a \n * @param arrowType * @param lineType */ public LostOrFoundMessage(Lifeline lifeline, boolean found, int sendTick, String text, ArrowType arrowType, LineType lineType) { super(); this.lifeline = lifeline; this.found = found; this.sendTick = sendTick; textLines = text.split("\n"); this.arrowType = arrowType; this.lineType = lineType; } public double getCenterXOffset() { if (found) { return -lifeline.getLifelineLeftPartWidth(sendTick); } else { return lifeline.getLifelineRightPartWidth(sendTick); } } @Override public Line1D draw(DrawHandler drawHandler, PointDouble topLeft, PointDouble size) { RelationDrawer.ArrowEndType arrowEndType = ArrowEndType.NORMAL; boolean fillArrow = false; switch (arrowType) { case OPEN: arrowEndType = ArrowEndType.NORMAL; fillArrow = false; break; case FILLED: arrowEndType = ArrowEndType.CLOSED; fillArrow = true; break; default: log.error("Encountered unhandled enumeration value '" + arrowType + "'."); break; } LineType oldLt = drawHandler.getLineType(); drawHandler.setLineType(lineType); double centerY = topLeft.y + size.y / 2; double lineXStart, lineXEnd; ColorOwn oldBg = drawHandler.getBackgroundColor(); drawHandler.setBackgroundColor(drawHandler.getForegroundColor()); if (found) { drawHandler.drawCircle(topLeft.x + CIRCLE_RADIUS, centerY, CIRCLE_RADIUS); lineXStart = topLeft.x + CIRCLE_RADIUS * 2; lineXEnd = topLeft.x + size.x / 2 + getCenterXOffset(); } else { drawHandler.drawCircle(topLeft.x + size.x - CIRCLE_RADIUS, topLeft.y + size.y / 2, CIRCLE_RADIUS); lineXStart = topLeft.x + size.x / 2 + getCenterXOffset(); lineXEnd = topLeft.x + size.x - CIRCLE_RADIUS * 2; } drawHandler.setBackgroundColor(oldBg); TextSplitter.drawText(drawHandler, textLines, lineXStart, topLeft.y, lineXEnd - lineXStart, size.y / 2, AlignHorizontal.CENTER, AlignVertical.BOTTOM); PointDouble arrowPoint = new PointDouble(lineXEnd, centerY); Line line = new Line(new PointDouble(lineXStart, centerY), arrowPoint); drawHandler.drawLine(line); RelationDrawer.drawArrowToLine(arrowPoint, drawHandler, line, false, arrowEndType, fillArrow, false); drawHandler.setLineType(oldLt); return null; } @Override public double getMinWidth(DrawHandler drawHandler) { return (TextSplitter.getTextMinWidth(textLines, drawHandler) + LIFELINE_TEXT_PADDING * 2 + Math.abs(getCenterXOffset())) * 2; } @Override public double getAdditionalYHeight(DrawHandler drawHandler, PointDouble size) { return TextSplitter.getSplitStringHeight(textLines, size.x / 2 - LIFELINE_TEXT_PADDING * 2 - Math.abs(getCenterXOffset()), drawHandler ) * 2 - size.y; } public OccurrenceSpecification sendOccurrenceSpecification() { if (found) { throw new IllegalStateException("A found message has no send occurrence specification."); } return new LostOrFoundOccurrenceSpecification(); } public OccurrenceSpecification receiveOccurrenceSpecification() { if (!found) { throw new IllegalStateException("A lost message has no receive occurrence specification."); } return new LostOrFoundOccurrenceSpecification(); } private class LostOrFoundOccurrenceSpecification implements OccurrenceSpecification { @Override public Lifeline getLifeline() { return lifeline; } @Override public boolean hasFixedPosition() { return true; } @Override public AlignHorizontal getFixedPositionAlignment() { if (getCenterXOffset() >= 0) { return AlignHorizontal.RIGHT; } else { return AlignHorizontal.LEFT; } } @Override public double getHorizonatlPosition(HorizontalDrawingInfo hDrawingInfo) { return hDrawingInfo.getHDrawingInfo(getLifeline()).getHorizontalCenter() + getCenterXOffset(); } @Override public double getHorizontalPosition(HorizontalDrawingInfo llHDrawingInfo, boolean left) { return 0; } @Override public PointDouble getPosition(DrawingInfo drawingInfo) { return new PointDouble(getHorizonatlPosition(drawingInfo), drawingInfo.getVerticalCenter(sendTick)); } @Override public PointDouble getPosition(DrawingInfo drawingInfo, boolean left) { return new PointDouble(0, 0); } } }