/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed 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.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package plotter.xy;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import javax.swing.JComponent;
import plotter.xy.XYAxis.TicksChangedListener;
/**
* Draws a grid on an {@link XYPlot}.
* Grids draw lines that correspond with major tick marks on axes.
* @author Adam Crume
*/
public class XYGrid extends JComponent implements TicksChangedListener {
private static final long serialVersionUID = 1L;
/** Used to draw the grid lines. */
private Stroke stroke = new BasicStroke(1, 0, 0, 1, new float[] { 4, 4 }, 0);
/** X axis this grid takes its values from. */
private XYAxis xAxis;
/** Y axis this grid takes its value from. */
private XYAxis yAxis;
/** Period length of the stroke, used to optimize drawing. */
private double strokeLength = 8;
/**
* Creates a grid.
* @param xAxis X axis this grid takes tick marks from
* @param yAxis Y axis this grid takes tick marks from
*/
public XYGrid(XYAxis xAxis, XYAxis yAxis) {
assert xAxis != null;
assert yAxis != null;
this.xAxis = xAxis;
this.yAxis = yAxis;
xAxis.addTickListener(this);
yAxis.addTickListener(this);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Color origColor = g2.getColor();
Stroke origStroke = g2.getStroke();
g2.setColor(getForeground());
g2.setStroke(stroke);
int height = getHeight();
int width = getWidth();
Rectangle clip = g2.getClipBounds();
int xmin = clip.x;
int xmax = clip.x + clip.width - 1;
int ymin = clip.y;
int ymax = clip.y + clip.height - 1;
// Draw shorter lines when possible.
// This makes drawing dashed lines faster.
int linexmin = 0;
int linexmax = width - 1;
int lineymin = 0;
int lineymax = height - 1;
if(strokeLength != 0) {
// We have to adjust the starting points so that the dashes are in phase
// with what they would have been if we drew the whole line.
linexmin = (int) (strokeLength * (int) (xmin / strokeLength));
lineymin = (int) (strokeLength * (int) (ymin / strokeLength));
linexmax = xmax + 1;
lineymax = ymax + 1;
}
for(int x : xAxis.getMajorTicks()) {
if(x >= xmin && x <= xmax) {
g2.drawLine(x, lineymin, x, lineymax);
}
}
for(int y : yAxis.getMajorTicks()) {
y = height - 1 - y;
if(y >= ymin && y <= ymax) {
g2.drawLine(linexmin, y, linexmax, y);
}
}
g2.setColor(origColor);
g2.setStroke(origStroke);
}
@Override
public void ticksChanged(XYAxis a) {
repaint();
}
/**
* Returns the stroke used to draw the lines.
* @return the stroke used to draw the lines
*/
public Stroke getStroke() {
return stroke;
}
/**
* Sets the stroke used to draw the lines.
* @param stroke the stroke used to draw the lines
*/
public void setStroke(Stroke stroke) {
this.stroke = stroke;
if(stroke instanceof BasicStroke) {
float[] dashes = ((BasicStroke) stroke).getDashArray();
float strokeLength = 0;
for(float f : dashes) {
strokeLength += f;
}
this.strokeLength = strokeLength;
} else {
this.strokeLength = 0;
}
}
}