/* 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;
}
}