/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.sequence; import java.awt.*; import java.awt.geom.GeneralPath; /** * Created by IntelliJ IDEA. User: dsmith Date: Nov 12, 2010 Time: 12:02:20 PM To change this * template use File | Settings | File Templates. */ public class Arrow { private static int ARROW_WIDTH = 10; private static int CIRCLE_WIDTH = 6; private static int LABEL_OFFSET = 10; private final String label; private final LifelineState startingState; private final LifelineState endingState; public Arrow(String label, LifelineState startingState, LifelineState endingState) { this.label = label; this.startingState = startingState; this.endingState = endingState; } public void paint(Graphics2D g) { Rectangle boundary = g.getClipBounds(); int y = endingState.getStartY(); // don't paint if we're not in the clip area if (y + ARROW_WIDTH < boundary.getMinY() || y - ARROW_WIDTH > boundary.getMaxY()) { return; } // TODO - we need to clip by X coordinate as well. boolean isReflexsive = getStartingLine() == getEndingLine(); if (isReflexsive) { paintReflexive(g); } else { paintNormal(g); } } private Lifeline getStartingLine() { return startingState.getLine(); } private Lifeline getEndingLine() { return endingState.getLine(); } private void paintReflexive(Graphics2D g) { Lifeline startingLine = getStartingLine(); int x = startingLine.getX(); int y = endingState.getStartY(); g.drawArc(x + startingLine.getWidth() - ARROW_WIDTH / 2, y - ARROW_WIDTH, ARROW_WIDTH, ARROW_WIDTH, 90, -180); g.drawString(label, x + startingLine.getWidth() + LABEL_OFFSET, y); // GeneralPath path = new GeneralPath(); // path.moveTo(x, y - ARROW_WIDTH); // path.quadTo(x, y - ARROW_WIDTH); } private void paintNormal(Graphics2D g) { Lifeline startingLine = getStartingLine(); Lifeline endingLine = getEndingLine(); int x1 = startingLine.getX(); int x2 = endingLine.getX(); int y = endingState.getStartY(); if (x2 > x1) { int startX = x1 + startingLine.getWidth(); int endX = x2; GeneralPath path = new GeneralPath(); path.moveTo(startX, y); path.lineTo(endX, y); path.lineTo(endX - ARROW_WIDTH, y - ARROW_WIDTH); path.moveTo(endX, y); path.lineTo(endX - ARROW_WIDTH, y + ARROW_WIDTH); g.draw(path); g.fillArc(startX, y - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360); g.drawString(label, startX + LABEL_OFFSET, y - LABEL_OFFSET); } else { int startX = x1; int endX = x2 + endingLine.getWidth(); GeneralPath path = new GeneralPath(); path.moveTo(startX, y); path.lineTo(endX, y); path.lineTo(endX + ARROW_WIDTH, y - ARROW_WIDTH); path.moveTo(endX, y); path.lineTo(endX + ARROW_WIDTH, y + ARROW_WIDTH); g.draw(path); int labelWidth = g.getFontMetrics().stringWidth(label); g.fillArc(startX - CIRCLE_WIDTH / 2, y - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360); g.drawString(label, startX - LABEL_OFFSET - labelWidth, y - LABEL_OFFSET); } } public LifelineState getStartingState() { return startingState; } }