/* RulerMeasurmentPlot.java created 2007-10-05 * */ package org.signalml.app.view.signal; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.Stroke; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; import org.signalml.app.util.GeometryUtils; import org.signalml.app.util.IconUtils; import org.signalml.util.Util; /** RulerMeasurmentPlot * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class RulerMeasurmentPlot extends JComponent { private static final float MIN_LABEL_WIDTH = 60F; private static final int OVAL_RADIUS = 6; private static final int OVAL_DIAMETER = 2*OVAL_RADIUS; private static final Color NORMAL_BOX_COLOR = new Color(255,255,187); private static final Color WARNING_BOX_COLOR = new Color(255,0,0); private static final long serialVersionUID = 1L; private static final Stroke lineStroke = new BasicStroke(3F); private Color boxColor = new Color(255,255,187); private Point start; private Point end; private Point origin; private float xValue; private float yValue; /** * True if each point defining a distance is under different scaling - in that case * we want to show the user that he has to double-check if what he is measuring * is allright. */ private boolean valueMeasurementControversial; public RulerMeasurmentPlot() { super(); setCursor(IconUtils.getEmptyCursor()); } @Override protected void paintComponent(Graphics gOrig) { if (start == null || end == null || origin == null) { return; } Graphics2D g = (Graphics2D) gOrig; Stroke origStroke = g.getStroke(); g.setColor(Color.RED); Point relStart = new Point(start.x - origin.x, start.y - origin.y); Point relEnd = new Point(end.x - origin.x, end.y - origin.y); g.fillOval(relStart.x-OVAL_RADIUS, relStart.y-OVAL_RADIUS, OVAL_DIAMETER, OVAL_DIAMETER); if (!relStart.equals(relEnd)) { g.setStroke(lineStroke); g.drawOval(relEnd.x-OVAL_RADIUS, relEnd.y-OVAL_RADIUS, OVAL_DIAMETER, OVAL_DIAMETER); if (relStart.distance(relEnd) > OVAL_RADIUS) { GeometryUtils.translatePointToCircleBorder(relEnd, relStart, OVAL_RADIUS); g.drawLine(relStart.x, relStart.y, relEnd.x, relEnd.y); } g.setStroke(origStroke); g.drawLine(relEnd.x, relEnd.y, relEnd.x, relEnd.y); } boxColor = NORMAL_BOX_COLOR; drawValueBox(g, xValue, relEnd.x, relEnd.y, true); boxColor = valueMeasurementControversial ? WARNING_BOX_COLOR : NORMAL_BOX_COLOR; drawValueBox(g, yValue, relEnd.x, relEnd.y, false); } private void drawValueBox(Graphics2D g, float value, int x, int y, boolean under) { String text = Float.toString(value); Rectangle2D labelRect2D = g.getFont().getStringBounds(text, g.getFontRenderContext()); int offset = 0; double width = labelRect2D.getWidth(); if (width < MIN_LABEL_WIDTH) { offset = (int) Math.round(((MIN_LABEL_WIDTH-width)/2)); width = MIN_LABEL_WIDTH; } Rectangle labelRect = new Rectangle( x, y, (int) Math.ceil(width), (int) Math.ceil(labelRect2D.getHeight()) ); labelRect.grow(3, 3); int realX; int realY; if (under) { realX = x - (labelRect.width / 2); realY = y + 10 + (labelRect.height / 2); } else { realX = x + 12; realY = y - (labelRect.height / 2); } g.setColor(boxColor); g.fillRect(realX, realY, labelRect.width, labelRect.height); g.setColor(Color.BLACK); g.drawRect(realX, realY, labelRect.width-1, labelRect.height-1); g.drawString(text, realX+3+offset, realY+3-((int) labelRect2D.getY())); } @Override public boolean isOpaque() { return false; } public Point getStart() { return start; } public void setStart(Point start) { if (!Util.equalsWithNulls(this.start, start)) { this.start = start; repaint(); } } public Point getEnd() { return end; } public void setEnd(Point end) { if (!Util.equalsWithNulls(this.end, end)) { this.end = end; repaint(); } } public Point getOrigin() { return origin; } public void setOrigin(Point origin) { if (!Util.equalsWithNulls(this.origin, origin)) { this.origin = origin; repaint(); } } public float getXValue() { return xValue; } public void setXValue(float value) { if (xValue != value) { xValue = value; repaint(); } } public float getYValue() { return yValue; } public void setYValue(float value) { if (yValue != value) { yValue = value; repaint(); } } public void setStartParameters(Point start, Point origin) { this.start = start; this.end = start; this.xValue = 0; this.yValue = 0; this.origin = origin; repaint(); } public void setEndParameters(Point end, float xValue, float yValue, Point origin) { this.end = end; this.xValue = xValue; this.yValue = yValue; this.origin = origin; repaint(); } public void setValueMeasurementControversial( boolean valueMeasurementControversial) { this.valueMeasurementControversial = valueMeasurementControversial; } public boolean isValueMeasurementControversial() { return valueMeasurementControversial; } }