blob: d3c286ccc76d12a4387aecc7f579dfb9edb59ebe [file] [log] [blame]
/*
* Copyright 2012 AndroidPlot.com
*
* 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.
*/
package com.androidplot.xy;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import com.androidplot.Plot;
import com.androidplot.ui.*;
import com.androidplot.ui.TextOrientationType;
import com.androidplot.ui.widget.TextLabelWidget;
import com.androidplot.util.PixelUtils;
import java.text.Format;
import java.util.ArrayList;
import java.util.List;
/**
* A View to graphically display x/y coordinates.
*/
public class XYPlot extends Plot<XYSeries, XYSeriesFormatter, XYSeriesRenderer> {
private BoundaryMode domainOriginBoundaryMode;
private BoundaryMode rangeOriginBoundaryMode;
// widgets
private XYLegendWidget legendWidget;
private XYGraphWidget graphWidget;
private TextLabelWidget domainLabelWidget;
private TextLabelWidget rangeLabelWidget;
private XYStepMode domainStepMode = XYStepMode.SUBDIVIDE;
private double domainStepValue = 10;
private XYStepMode rangeStepMode = XYStepMode.SUBDIVIDE;
private double rangeStepValue = 10;
// user settable min/max values
private Number userMinX;
private Number userMaxX;
private Number userMinY;
private Number userMaxY;
// these are the final min/max used for dispplaying data
private Number calculatedMinX;
private Number calculatedMaxX;
private Number calculatedMinY;
private Number calculatedMaxY;
// previous calculated min/max vals.
// primarily used for GROW/SHRINK operations.
private Number prevMinX;
private Number prevMaxX;
private Number prevMinY;
private Number prevMaxY;
// uses set boundary min and max values
// should be null if not used.
private Number rangeTopMin = null;
private Number rangeTopMax = null;
private Number rangeBottomMin = null;
private Number rangeBottomMax = null;
private Number domainLeftMin = null;
private Number domainLeftMax = null;
private Number domainRightMin = null;
private Number domainRightMax = null;
// used for calculating the domain/range extents that will be displayed on the plot.
// using boundaries and origins are mutually exclusive. because of this,
// setting one will disable the other. when only setting the FramingModel,
// the origin or boundary is set to the current value of the plot.
private XYFramingModel domainFramingModel = XYFramingModel.EDGE;
private XYFramingModel rangeFramingModel = XYFramingModel.EDGE;
private Number userDomainOrigin;
private Number userRangeOrigin;
private Number calculatedDomainOrigin;
private Number calculatedRangeOrigin;
@SuppressWarnings("FieldCanBeLocal")
private Number domainOriginExtent = null;
@SuppressWarnings("FieldCanBeLocal")
private Number rangeOriginExtent = null;
private BoundaryMode domainUpperBoundaryMode = BoundaryMode.AUTO;
private BoundaryMode domainLowerBoundaryMode = BoundaryMode.AUTO;
private BoundaryMode rangeUpperBoundaryMode = BoundaryMode.AUTO;
private BoundaryMode rangeLowerBoundaryMode = BoundaryMode.AUTO;
private boolean drawDomainOriginEnabled = true;
private boolean drawRangeOriginEnabled = true;
private ArrayList<YValueMarker> yValueMarkers;
private ArrayList<XValueMarker> xValueMarkers;
private RectRegion defaultBounds;
private static final int DEFAULT_LEGEND_WIDGET_H_DP = 10;
private static final int DEFAULT_LEGEND_WIDGET_ICON_SIZE_DP = 7;
private static final int DEFAULT_GRAPH_WIDGET_H_DP = 18;
private static final int DEFAULT_GRAPH_WIDGET_W_DP = 10;
private static final int DEFAULT_DOMAIN_LABEL_WIDGET_H_DP = 10;
private static final int DEFAULT_DOMAIN_LABEL_WIDGET_W_DP = 80;
private static final int DEFAULT_RANGE_LABEL_WIDGET_H_DP = 50;
private static final int DEFAULT_RANGE_LABEL_WIDGET_W_DP = 10;
private static final int DEFAULT_LEGEND_WIDGET_Y_OFFSET_DP = 0;
private static final int DEFAULT_LEGEND_WIDGET_X_OFFSET_DP = 40;
private static final int DEFAULT_GRAPH_WIDGET_Y_OFFSET_DP = 0;
private static final int DEFAULT_GRAPH_WIDGET_X_OFFSET_DP = 0;
private static final int DEFAULT_DOMAIN_LABEL_WIDGET_Y_OFFSET_DP = 0;
private static final int DEFAULT_DOMAIN_LABEL_WIDGET_X_OFFSET_DP = 20;
private static final int DEFAULT_RANGE_LABEL_WIDGET_Y_OFFSET_DP = 0;
private static final int DEFAULT_RANGE_LABEL_WIDGET_X_OFFSET_DP = 0;
private static final int DEFAULT_GRAPH_WIDGET_TOP_MARGIN_DP = 3;
private static final int DEFAULT_GRAPH_WIDGET_RIGHT_MARGIN_DP = 3;
private static final int DEFAULT_PLOT_LEFT_MARGIN_DP = 2;
private static final int DEFAULT_PLOT_RIGHT_MARGIN_DP = 2;
private static final int DEFAULT_PLOT_BOTTOM_MARGIN_DP = 2;
public XYPlot(Context context, String title) {
super(context, title);
}
public XYPlot(Context context, String title, RenderMode mode) {
super(context, title, mode);
}
public XYPlot(Context context, AttributeSet attributes) {
super(context, attributes);
}
public XYPlot(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onPreInit() {
legendWidget = new XYLegendWidget(
getLayoutManager(),
this,
new SizeMetrics(
PixelUtils.dpToPix(DEFAULT_LEGEND_WIDGET_H_DP),
SizeLayoutType.ABSOLUTE, 0.5f, SizeLayoutType.RELATIVE),
new DynamicTableModel(0, 1),
new SizeMetrics(
PixelUtils.dpToPix(DEFAULT_LEGEND_WIDGET_ICON_SIZE_DP),
SizeLayoutType.ABSOLUTE,
PixelUtils.dpToPix(DEFAULT_LEGEND_WIDGET_ICON_SIZE_DP),
SizeLayoutType.ABSOLUTE));
graphWidget = new XYGraphWidget(
getLayoutManager(),
this,
new SizeMetrics(
PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_H_DP),
SizeLayoutType.FILL,
PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_W_DP),
SizeLayoutType.FILL));
Paint backgroundPaint = new Paint();
backgroundPaint.setColor(Color.DKGRAY);
backgroundPaint.setStyle(Paint.Style.FILL);
graphWidget.setBackgroundPaint(backgroundPaint);
domainLabelWidget = new TextLabelWidget(
getLayoutManager(),
new SizeMetrics(
PixelUtils.dpToPix(DEFAULT_DOMAIN_LABEL_WIDGET_H_DP),
SizeLayoutType.ABSOLUTE,
PixelUtils.dpToPix(DEFAULT_DOMAIN_LABEL_WIDGET_W_DP),
SizeLayoutType.ABSOLUTE),
TextOrientationType.HORIZONTAL);
rangeLabelWidget = new TextLabelWidget(
getLayoutManager(),
new SizeMetrics(
PixelUtils.dpToPix(DEFAULT_RANGE_LABEL_WIDGET_H_DP),
SizeLayoutType.ABSOLUTE,
PixelUtils.dpToPix(DEFAULT_RANGE_LABEL_WIDGET_W_DP),
SizeLayoutType.ABSOLUTE),
TextOrientationType.VERTICAL_ASCENDING);
legendWidget.position(
PixelUtils.dpToPix(DEFAULT_LEGEND_WIDGET_X_OFFSET_DP),
XLayoutStyle.ABSOLUTE_FROM_RIGHT,
PixelUtils.dpToPix(DEFAULT_LEGEND_WIDGET_Y_OFFSET_DP),
YLayoutStyle.ABSOLUTE_FROM_BOTTOM,
AnchorPosition.RIGHT_BOTTOM);
graphWidget.position(
PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_X_OFFSET_DP),
XLayoutStyle.ABSOLUTE_FROM_RIGHT,
PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_Y_OFFSET_DP),
YLayoutStyle.ABSOLUTE_FROM_CENTER,
AnchorPosition.RIGHT_MIDDLE);
domainLabelWidget.position(
PixelUtils.dpToPix(DEFAULT_DOMAIN_LABEL_WIDGET_X_OFFSET_DP),
XLayoutStyle.ABSOLUTE_FROM_LEFT,
PixelUtils.dpToPix(DEFAULT_DOMAIN_LABEL_WIDGET_Y_OFFSET_DP),
YLayoutStyle.ABSOLUTE_FROM_BOTTOM,
AnchorPosition.LEFT_BOTTOM);
rangeLabelWidget.position(
PixelUtils.dpToPix(DEFAULT_RANGE_LABEL_WIDGET_X_OFFSET_DP),
XLayoutStyle.ABSOLUTE_FROM_LEFT,
PixelUtils.dpToPix(DEFAULT_RANGE_LABEL_WIDGET_Y_OFFSET_DP),
YLayoutStyle.ABSOLUTE_FROM_CENTER,
AnchorPosition.LEFT_MIDDLE);
getLayoutManager().moveToTop(getTitleWidget());
getLayoutManager().moveToTop(getLegendWidget());
graphWidget.setMarginTop(PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_TOP_MARGIN_DP));
graphWidget.setMarginRight(PixelUtils.dpToPix(DEFAULT_GRAPH_WIDGET_RIGHT_MARGIN_DP));
getDomainLabelWidget().pack();
getRangeLabelWidget().pack();
setPlotMarginLeft(PixelUtils.dpToPix(DEFAULT_PLOT_LEFT_MARGIN_DP));
setPlotMarginRight(PixelUtils.dpToPix(DEFAULT_PLOT_RIGHT_MARGIN_DP));
setPlotMarginBottom(PixelUtils.dpToPix(DEFAULT_PLOT_BOTTOM_MARGIN_DP));
xValueMarkers = new ArrayList<XValueMarker>();
yValueMarkers = new ArrayList<YValueMarker>();
setDefaultBounds(new RectRegion(-1, 1, -1, 1));
}
public void setGridPadding(float left, float top, float right, float bottom) {
getGraphWidget().setGridPaddingTop(top);
getGraphWidget().setGridPaddingBottom(bottom);
getGraphWidget().setGridPaddingLeft(left);
getGraphWidget().setGridPaddingRight(right);
}
@Override
protected void notifyListenersBeforeDraw(Canvas canvas) {
super.notifyListenersBeforeDraw(canvas);
// this call must be AFTER the notify so that if the listener
// is a synchronized series, it has the opportunity to
// place a read lock on it's data.
calculateMinMaxVals();
}
/**
* Checks whether the point is within the plot's graph area.
*
* @param x
* @param y
* @return
*/
public boolean containsPoint(float x, float y) {
if (getGraphWidget().getGridRect() != null) {
return getGraphWidget().getGridRect().contains(x, y);
}
return false;
}
/**
* Convenience method - wraps containsPoint(PointF).
*
* @param point
* @return
*/
public boolean containsPoint(PointF point) {
return containsPoint(point.x, point.y);
}
public void setCursorPosition(PointF point) {
getGraphWidget().setCursorPosition(point);
}
public void setCursorPosition(float x, float y) {
getGraphWidget().setCursorPosition(x, y);
}
public Number getYVal(PointF point) {
return getGraphWidget().getYVal(point);
}
public Number getXVal(PointF point) {
return getGraphWidget().getXVal(point);
}
private boolean isXValWithinView(double xVal) {
return (userMinY == null || xVal >= userMinY.doubleValue()) &&
userMaxY == null || xVal <= userMaxY.doubleValue();
}
private boolean isPointVisible(Number x, Number y) {
// values without both an x and y val arent visible
if (x == null || y == null) {
return false;
}
return isValWithinRange(y.doubleValue(), userMinY, userMaxY) &&
isValWithinRange(x.doubleValue(), userMinX, userMaxX);
}
private boolean isValWithinRange(double val, Number min, Number max) {
boolean isAboveMinThreshold = min == null || val >= min.doubleValue();
boolean isBelowMaxThreshold = max == null || val <= max.doubleValue();
return isAboveMinThreshold &&
isBelowMaxThreshold;
}
public void calculateMinMaxVals() {
prevMinX = calculatedMinX;
prevMaxX = calculatedMaxX;
prevMinY = calculatedMinY;
prevMaxY = calculatedMaxY;
calculatedMinX = userMinX;
calculatedMaxX = userMaxX;
calculatedMinY = userMinY;
calculatedMaxY = userMaxY;
// next we go through each series to update our min/max values:
for (final XYSeries series : getSeriesSet()) {
// step through each point in each series:
for (int i = 0; i < series.size(); i++) {
Number thisX = series.getX(i);
Number thisY = series.getY(i);
if (isPointVisible(thisX, thisY)) {
// only calculate if a static value has not been set:
if (userMinX == null) {
if (thisX != null && (calculatedMinX == null ||
thisX.doubleValue() < calculatedMinX.doubleValue())) {
calculatedMinX = thisX;
}
}
if (userMaxX == null) {
if (thisX != null && (calculatedMaxX == null ||
thisX.doubleValue() > calculatedMaxX.doubleValue())) {
calculatedMaxX = thisX;
}
}
if (userMinY == null) {
if (thisY != null && (calculatedMinY == null ||
thisY.doubleValue() < calculatedMinY.doubleValue())) {
calculatedMinY = thisY;
}
}
if (userMaxY == null) {
if (thisY != null && (calculatedMaxY == null || thisY.doubleValue() > calculatedMaxY.doubleValue())) {
calculatedMaxY = thisY;
}
}
}
}
}
// at this point we now know what points are going to be visible on our
// plot, but we still need to make corrections based on modes being used:
// (grow, shrink etc.)
switch (domainFramingModel) {
case ORIGIN:
updateDomainMinMaxForOriginModel();
break;
case EDGE:
updateDomainMinMaxForEdgeModel();
calculatedMinX = ApplyUserMinMax(calculatedMinX, domainLeftMin,
domainLeftMax);
calculatedMaxX = ApplyUserMinMax(calculatedMaxX,
domainRightMin, domainRightMax);
break;
default:
throw new UnsupportedOperationException(
"Domain Framing Model not yet supported: " + domainFramingModel);
}
switch (rangeFramingModel) {
case ORIGIN:
updateRangeMinMaxForOriginModel();
break;
case EDGE:
if (getSeriesSet().size() > 0) {
updateRangeMinMaxForEdgeModel();
calculatedMinY = ApplyUserMinMax(calculatedMinY,
rangeBottomMin, rangeBottomMax);
calculatedMaxY = ApplyUserMinMax(calculatedMaxY, rangeTopMin,
rangeTopMax);
}
break;
default:
throw new UnsupportedOperationException(
"Range Framing Model not yet supported: " + domainFramingModel);
}
calculatedDomainOrigin = userDomainOrigin != null ? userDomainOrigin : getCalculatedMinX();
calculatedRangeOrigin = this.userRangeOrigin != null ? userRangeOrigin : getCalculatedMinY();
}
/**
* Should ONLY be called from updateMinMax.
* Results are undefined otherwise.
*/
private void updateDomainMinMaxForEdgeModel() {
switch (domainUpperBoundaryMode) {
case FIXED:
break;
case AUTO:
break;
case GROW:
if (!(prevMaxX == null || (calculatedMaxX.doubleValue() > prevMaxX.doubleValue()))) {
calculatedMaxX = prevMaxX;
}
break;
case SHRINNK:
if (!(prevMaxX == null || calculatedMaxX.doubleValue() < prevMaxX.doubleValue())) {
calculatedMaxX = prevMaxX;
}
break;
default:
throw new UnsupportedOperationException(
"DomainUpperBoundaryMode not yet implemented: " + domainUpperBoundaryMode);
}
switch (domainLowerBoundaryMode) {
case FIXED:
break;
case AUTO:
break;
case GROW:
if (!(prevMinX == null || calculatedMinX.doubleValue() < prevMinX.doubleValue())) {
calculatedMinX = prevMinX;
}
break;
case SHRINNK:
if (!(prevMinX == null || calculatedMinX.doubleValue() > prevMinX.doubleValue())) {
calculatedMinX = prevMinX;
}
break;
default:
throw new UnsupportedOperationException(
"DomainLowerBoundaryMode not supported: " + domainLowerBoundaryMode);
}
}
public void updateRangeMinMaxForEdgeModel() {
switch (rangeUpperBoundaryMode) {
case FIXED:
break;
case AUTO:
break;
case GROW:
if (!(prevMaxY == null || calculatedMaxY.doubleValue() > prevMaxY.doubleValue())) {
calculatedMaxY = prevMaxY;
}
break;
case SHRINNK:
if (!(prevMaxY == null || calculatedMaxY.doubleValue() < prevMaxY.doubleValue())) {
calculatedMaxY = prevMaxY;
}
break;
default:
throw new UnsupportedOperationException(
"RangeUpperBoundaryMode not supported: " + rangeUpperBoundaryMode);
}
switch (rangeLowerBoundaryMode) {
case FIXED:
break;
case AUTO:
break;
case GROW:
if (!(prevMinY == null || calculatedMinY.doubleValue() < prevMinY.doubleValue())) {
calculatedMinY = prevMinY;
}
break;
case SHRINNK:
if (!(prevMinY == null || calculatedMinY.doubleValue() > prevMinY.doubleValue())) {
calculatedMinY = prevMinY;
}
break;
default:
throw new UnsupportedOperationException(
"RangeLowerBoundaryMode not supported: " + rangeLowerBoundaryMode);
}
}
/**
* Apply user supplied min and max to the calculated boundary value.
*
* @param value
* @param min
* @param max
*/
private Number ApplyUserMinMax(Number value, Number min, Number max) {
value = (((min == null) || (value.doubleValue() > min.doubleValue()))
? value
: min);
value = (((max == null) || (value.doubleValue() < max.doubleValue()))
? value
: max);
return value;
}
/**
* Centers the domain axis on origin.
*
* @param origin
*/
public void centerOnDomainOrigin(Number origin) {
centerOnDomainOrigin(origin, null, BoundaryMode.AUTO);
}
/**
* Centers the domain on origin, calculating the upper and lower boundaries of the axis
* using mode and extent.
*
* @param origin
* @param extent
* @param mode
*/
public void centerOnDomainOrigin(Number origin, Number extent, BoundaryMode mode) {
if (origin == null) {
throw new NullPointerException("Origin param cannot be null.");
}
domainFramingModel = XYFramingModel.ORIGIN;
setUserDomainOrigin(origin);
domainOriginExtent = extent;
domainOriginBoundaryMode = mode;
if (domainOriginBoundaryMode == BoundaryMode.FIXED) {
double domO = userDomainOrigin.doubleValue();
double domE = domainOriginExtent.doubleValue();
userMaxX = domO + domE;
userMinX = domO - domE;
} else {
userMaxX = null;
userMinX = null;
}
}
/**
* Centers the range axis on origin.
*
* @param origin
*/
public void centerOnRangeOrigin(Number origin) {
centerOnRangeOrigin(origin, null, BoundaryMode.AUTO);
}
/**
* Centers the domain on origin, calculating the upper and lower boundaries of the axis
* using mode and extent.
*
* @param origin
* @param extent
* @param mode
*/
@SuppressWarnings("SameParameterValue")
public void centerOnRangeOrigin(Number origin, Number extent, BoundaryMode mode) {
if (origin == null) {
throw new NullPointerException("Origin param cannot be null.");
}
rangeFramingModel = XYFramingModel.ORIGIN;
setUserRangeOrigin(origin);
rangeOriginExtent = extent;
rangeOriginBoundaryMode = mode;
if (rangeOriginBoundaryMode == BoundaryMode.FIXED) {
double raO = userRangeOrigin.doubleValue();
double raE = rangeOriginExtent.doubleValue();
userMaxY = raO + raE;
userMinY = raO - raE;
} else {
userMaxY = null;
userMinY = null;
}
}
/**
* Returns the distance between x and y.
* Result is never a negative number.
*
* @param x
* @param y
* @return
*/
private double distance(double x, double y) {
if (x > y) {
return x - y;
} else {
return y - x;
}
}
public void updateDomainMinMaxForOriginModel() {
double origin = userDomainOrigin.doubleValue();
double maxXDelta = distance(calculatedMaxX.doubleValue(), origin);
double minXDelta = distance(calculatedMinX.doubleValue(), origin);
double delta = maxXDelta > minXDelta ? maxXDelta : minXDelta;
double dlb = origin - delta;
double dub = origin + delta;
switch (domainOriginBoundaryMode) {
case AUTO:
calculatedMinX = dlb;
calculatedMaxX = dub;
break;
// if fixed, then the value already exists within "user" vals.
case FIXED:
break;
case GROW: {
if (prevMinX == null || dlb < prevMinX.doubleValue()) {
calculatedMinX = dlb;
} else {
calculatedMinX = prevMinX;
}
if (prevMaxX == null || dub > prevMaxX.doubleValue()) {
calculatedMaxX = dub;
} else {
calculatedMaxX = prevMaxX;
}
}
break;
case SHRINNK:
if (prevMinX == null || dlb > prevMinX.doubleValue()) {
calculatedMinX = dlb;
} else {
calculatedMinX = prevMinX;
}
if (prevMaxX == null || dub < prevMaxX.doubleValue()) {
calculatedMaxX = dub;
} else {
calculatedMaxX = prevMaxX;
}
break;
default:
throw new UnsupportedOperationException("Domain Origin Boundary Mode not yet supported: " + domainOriginBoundaryMode);
}
}
public void updateRangeMinMaxForOriginModel() {
switch (rangeOriginBoundaryMode) {
case AUTO:
double origin = userRangeOrigin.doubleValue();
double maxYDelta = distance(calculatedMaxY.doubleValue(), origin);
double minYDelta = distance(calculatedMinY.doubleValue(), origin);
if (maxYDelta > minYDelta) {
calculatedMinY = origin - maxYDelta;
calculatedMaxY = origin + maxYDelta;
} else {
calculatedMinY = origin - minYDelta;
calculatedMaxY = origin + minYDelta;
}
break;
case FIXED:
case GROW:
case SHRINNK:
default:
throw new UnsupportedOperationException(
"Range Origin Boundary Mode not yet supported: " + rangeOriginBoundaryMode);
}
}
/**
* Convenience method - wraps XYGraphWidget.getTicksPerRangeLabel().
* Equivalent to getGraphWidget().getTicksPerRangeLabel().
*
* @return
*/
public int getTicksPerRangeLabel() {
return graphWidget.getTicksPerRangeLabel();
}
/**
* Convenience method - wraps XYGraphWidget.setTicksPerRangeLabel().
* Equivalent to getGraphWidget().setTicksPerRangeLabel().
*
* @param ticksPerRangeLabel
*/
public void setTicksPerRangeLabel(int ticksPerRangeLabel) {
graphWidget.setTicksPerRangeLabel(ticksPerRangeLabel);
}
/**
* Convenience method - wraps XYGraphWidget.getTicksPerDomainLabel().
* Equivalent to getGraphWidget().getTicksPerDomainLabel().
*
* @return
*/
public int getTicksPerDomainLabel() {
return graphWidget.getTicksPerDomainLabel();
}
/**
* Convenience method - wraps XYGraphWidget.setTicksPerDomainLabel().
* Equivalent to getGraphWidget().setTicksPerDomainLabel().
*
* @param ticksPerDomainLabel
*/
public void setTicksPerDomainLabel(int ticksPerDomainLabel) {
graphWidget.setTicksPerDomainLabel(ticksPerDomainLabel);
}
public XYStepMode getDomainStepMode() {
return domainStepMode;
}
public void setDomainStepMode(XYStepMode domainStepMode) {
this.domainStepMode = domainStepMode;
}
public double getDomainStepValue() {
return domainStepValue;
}
public void setDomainStepValue(double domainStepValue) {
this.domainStepValue = domainStepValue;
}
public void setDomainStep(XYStepMode mode, double value) {
setDomainStepMode(mode);
setDomainStepValue(value);
}
public XYStepMode getRangeStepMode() {
return rangeStepMode;
}
public void setRangeStepMode(XYStepMode rangeStepMode) {
this.rangeStepMode = rangeStepMode;
}
public double getRangeStepValue() {
return rangeStepValue;
}
public void setRangeStepValue(double rangeStepValue) {
this.rangeStepValue = rangeStepValue;
}
public void setRangeStep(XYStepMode mode, double value) {
setRangeStepMode(mode);
setRangeStepValue(value);
}
public String getDomainLabel() {
return getDomainLabelWidget().getText();
}
public void setDomainLabel(String domainLabel) {
getDomainLabelWidget().setText(domainLabel);
}
public String getRangeLabel() {
return getRangeLabelWidget().getText();
}
public void setRangeLabel(String rangeLabel) {
getRangeLabelWidget().setText(rangeLabel);
}
public XYLegendWidget getLegendWidget() {
return legendWidget;
}
public void setLegendWidget(XYLegendWidget legendWidget) {
this.legendWidget = legendWidget;
}
public XYGraphWidget getGraphWidget() {
return graphWidget;
}
public void setGraphWidget(XYGraphWidget graphWidget) {
this.graphWidget = graphWidget;
}
public TextLabelWidget getDomainLabelWidget() {
return domainLabelWidget;
}
public void setDomainLabelWidget(TextLabelWidget domainLabelWidget) {
this.domainLabelWidget = domainLabelWidget;
}
public TextLabelWidget getRangeLabelWidget() {
return rangeLabelWidget;
}
public void setRangeLabelWidget(TextLabelWidget rangeLabelWidget) {
this.rangeLabelWidget = rangeLabelWidget;
}
/**
* Convenience method - wraps XYGraphWidget.getRangeValueFormat().
*
* @return
*/
public Format getRangeValueFormat() {
return graphWidget.getRangeValueFormat();
}
/**
* Convenience method - wraps XYGraphWidget.setRangeValueFormat().
*
* @param rangeValueFormat
*/
public void setRangeValueFormat(Format rangeValueFormat) {
graphWidget.setRangeValueFormat(rangeValueFormat);
}
/**
* Convenience method - wraps XYGraphWidget.getDomainValueFormat().
*
* @return
*/
public Format getDomainValueFormat() {
return graphWidget.getDomainValueFormat();
}
/**
* Convenience method - wraps XYGraphWidget.setDomainValueFormat().
*
* @param domainValueFormat
*/
public void setDomainValueFormat(Format domainValueFormat) {
graphWidget.setDomainValueFormat(domainValueFormat);
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param lowerBoundary
* @param upperBoundary
* @param mode
*/
public synchronized void setDomainBoundaries(Number lowerBoundary, Number upperBoundary, BoundaryMode mode) {
setDomainBoundaries(lowerBoundary, mode, upperBoundary, mode);
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param lowerBoundary
* @param lowerBoundaryMode
* @param upperBoundary
* @param upperBoundaryMode
*/
public synchronized void setDomainBoundaries(Number lowerBoundary, BoundaryMode lowerBoundaryMode,
Number upperBoundary, BoundaryMode upperBoundaryMode) {
setDomainLowerBoundary(lowerBoundary, lowerBoundaryMode);
setDomainUpperBoundary(upperBoundary, upperBoundaryMode);
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param lowerBoundary
* @param upperBoundary
* @param mode
*/
public synchronized void setRangeBoundaries(Number lowerBoundary, Number upperBoundary, BoundaryMode mode) {
setRangeBoundaries(lowerBoundary, mode, upperBoundary, mode);
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param lowerBoundary
* @param lowerBoundaryMode
* @param upperBoundary
* @param upperBoundaryMode
*/
public synchronized void setRangeBoundaries(Number lowerBoundary, BoundaryMode lowerBoundaryMode,
Number upperBoundary, BoundaryMode upperBoundaryMode) {
setRangeLowerBoundary(lowerBoundary, lowerBoundaryMode);
setRangeUpperBoundary(upperBoundary, upperBoundaryMode);
}
protected synchronized void setDomainUpperBoundaryMode(BoundaryMode mode) {
this.domainUpperBoundaryMode = mode;
}
protected synchronized void setUserMaxX(Number boundary) {
// Ifor 12/10/2011
// you want null for auto grow and shrink
//if(boundary == null) {
// throw new NullPointerException("Boundary value cannot be null.");
//}
this.userMaxX = boundary;
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param boundary
* @param mode
*/
public synchronized void setDomainUpperBoundary(Number boundary, BoundaryMode mode) {
setUserMaxX((mode == BoundaryMode.FIXED) ? boundary : null);
setDomainUpperBoundaryMode(mode);
setDomainFramingModel(XYFramingModel.EDGE);
}
protected synchronized void setDomainLowerBoundaryMode(BoundaryMode mode) {
this.domainLowerBoundaryMode = mode;
}
protected synchronized void setUserMinX(Number boundary) {
// Ifor 12/10/2011
// you want null for auto grow and shrink
//if(boundary == null) {
// throw new NullPointerException("Boundary value cannot be null.");
//}
this.userMinX = boundary;
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param boundary
* @param mode
*/
public synchronized void setDomainLowerBoundary(Number boundary, BoundaryMode mode) {
setUserMinX((mode == BoundaryMode.FIXED) ? boundary : null);
setDomainLowerBoundaryMode(mode);
setDomainFramingModel(XYFramingModel.EDGE);
//updateMinMaxVals();
}
protected synchronized void setRangeUpperBoundaryMode(BoundaryMode mode) {
this.rangeUpperBoundaryMode = mode;
}
protected synchronized void setUserMaxY(Number boundary) {
// Ifor 12/10/2011
// you want null for auto grow and shrink
//if(boundary == null) {
// throw new NullPointerException("Boundary value cannot be null.");
//}
this.userMaxY = boundary;
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param boundary
* @param mode
*/
public synchronized void setRangeUpperBoundary(Number boundary, BoundaryMode mode) {
setUserMaxY((mode == BoundaryMode.FIXED) ? boundary : null);
setRangeUpperBoundaryMode(mode);
setRangeFramingModel(XYFramingModel.EDGE);
}
protected synchronized void setRangeLowerBoundaryMode(BoundaryMode mode) {
this.rangeLowerBoundaryMode = mode;
}
protected synchronized void setUserMinY(Number boundary) {
// Ifor 12/10/2011
// you want null for auto grow and shrink
//if(boundary == null) {
// throw new NullPointerException("Boundary value cannot be null.");
//}
this.userMinY = boundary;
}
/**
* Setup the boundary mode, boundary values only applicable in FIXED mode.
*
* @param boundary
* @param mode
*/
public synchronized void setRangeLowerBoundary(Number boundary, BoundaryMode mode) {
setUserMinY((mode == BoundaryMode.FIXED) ? boundary : null);
setRangeLowerBoundaryMode(mode);
setRangeFramingModel(XYFramingModel.EDGE);
}
private Number getUserMinX() {
return userMinX;
}
private Number getUserMaxX() {
return userMaxX;
}
private Number getUserMinY() {
return userMinY;
}
private Number getUserMaxY() {
return userMaxY;
}
public Number getDomainOrigin() {
return calculatedDomainOrigin;
}
public Number getRangeOrigin() {
return calculatedRangeOrigin;
}
protected BoundaryMode getDomainUpperBoundaryMode() {
return domainUpperBoundaryMode;
}
protected BoundaryMode getDomainLowerBoundaryMode() {
return domainLowerBoundaryMode;
}
protected BoundaryMode getRangeUpperBoundaryMode() {
return rangeUpperBoundaryMode;
}
protected BoundaryMode getRangeLowerBoundaryMode() {
return rangeLowerBoundaryMode;
}
public synchronized void setUserDomainOrigin(Number origin) {
if (origin == null) {
throw new NullPointerException("Origin value cannot be null.");
}
this.userDomainOrigin = origin;
}
public synchronized void setUserRangeOrigin(Number origin) {
if (origin == null) {
throw new NullPointerException("Origin value cannot be null.");
}
this.userRangeOrigin = origin;
}
public XYFramingModel getDomainFramingModel() {
return domainFramingModel;
}
@SuppressWarnings("SameParameterValue")
protected void setDomainFramingModel(XYFramingModel domainFramingModel) {
this.domainFramingModel = domainFramingModel;
}
public XYFramingModel getRangeFramingModel() {
return rangeFramingModel;
}
@SuppressWarnings("SameParameterValue")
protected void setRangeFramingModel(XYFramingModel rangeFramingModel) {
this.rangeFramingModel = rangeFramingModel;
}
/**
* CalculatedMinX value after the the framing model has been applied.
*
* @return
*/
public Number getCalculatedMinX() {
return calculatedMinX != null ? calculatedMinX : getDefaultBounds().getMinX();
}
/**
* CalculatedMaxX value after the the framing model has been applied.
*
* @return
*/
public Number getCalculatedMaxX() {
return calculatedMaxX != null ? calculatedMaxX : getDefaultBounds().getMaxX();
}
/**
* CalculatedMinY value after the the framing model has been applied.
*
* @return
*/
public Number getCalculatedMinY() {
return calculatedMinY != null ? calculatedMinY : getDefaultBounds().getMinY();
}
/**
* CalculatedMaxY value after the the framing model has been applied.
*
* @return
*/
public Number getCalculatedMaxY() {
return calculatedMaxY != null ? calculatedMaxY : getDefaultBounds().getMaxY();
}
public boolean isDrawDomainOriginEnabled() {
return drawDomainOriginEnabled;
}
public void setDrawDomainOriginEnabled(boolean drawDomainOriginEnabled) {
this.drawDomainOriginEnabled = drawDomainOriginEnabled;
}
public boolean isDrawRangeOriginEnabled() {
return drawRangeOriginEnabled;
}
public void setDrawRangeOriginEnabled(boolean drawRangeOriginEnabled) {
this.drawRangeOriginEnabled = drawRangeOriginEnabled;
}
/**
* Appends the specified marker to the end of plot's yValueMarkers list.
*
* @param marker The YValueMarker to be added.
* @return true if the object was successfully added, false otherwise.
*/
public boolean addMarker(YValueMarker marker) {
if (yValueMarkers.contains(marker)) {
return false;
} else {
return yValueMarkers.add(marker);
}
}
/**
* Removes the specified marker from the plot.
*
* @param marker
* @return The YValueMarker removed if successfull, null otherwise.
*/
public YValueMarker removeMarker(YValueMarker marker) {
int markerIndex = yValueMarkers.indexOf(marker);
if (markerIndex == -1) {
return null;
} else {
return yValueMarkers.remove(markerIndex);
}
}
/**
* Convenience method - combines removeYMarkers() and removeXMarkers().
*
* @return
*/
public int removeMarkers() {
int removed = removeXMarkers();
removed += removeYMarkers();
return removed;
}
/**
* Removes all YValueMarker instances from the plot.
*
* @return
*/
public int removeYMarkers() {
int numMarkersRemoved = yValueMarkers.size();
yValueMarkers.clear();
return numMarkersRemoved;
}
/**
* Appends the specified marker to the end of plot's xValueMarkers list.
*
* @param marker The XValueMarker to be added.
* @return true if the object was successfully added, false otherwise.
*/
public boolean addMarker(XValueMarker marker) {
return !xValueMarkers.contains(marker) && xValueMarkers.add(marker);
}
/**
* Removes the specified marker from the plot.
*
* @param marker
* @return The XValueMarker removed if successfull, null otherwise.
*/
public XValueMarker removeMarker(XValueMarker marker) {
int markerIndex = xValueMarkers.indexOf(marker);
if (markerIndex == -1) {
return null;
} else {
return xValueMarkers.remove(markerIndex);
}
}
/**
* Removes all XValueMarker instances from the plot.
*
* @return
*/
public int removeXMarkers() {
int numMarkersRemoved = xValueMarkers.size();
xValueMarkers.clear();
return numMarkersRemoved;
}
protected List<YValueMarker> getYValueMarkers() {
return yValueMarkers;
}
protected List<XValueMarker> getXValueMarkers() {
return xValueMarkers;
}
public RectRegion getDefaultBounds() {
return defaultBounds;
}
public void setDefaultBounds(RectRegion defaultBounds) {
this.defaultBounds = defaultBounds;
}
/**
* @return the rangeTopMin
*/
public Number getRangeTopMin() {
return rangeTopMin;
}
/**
* @param rangeTopMin the rangeTopMin to set
*/
public synchronized void setRangeTopMin(Number rangeTopMin) {
this.rangeTopMin = rangeTopMin;
}
/**
* @return the rangeTopMax
*/
public Number getRangeTopMax() {
return rangeTopMax;
}
/**
* @param rangeTopMax the rangeTopMax to set
*/
public synchronized void setRangeTopMax(Number rangeTopMax) {
this.rangeTopMax = rangeTopMax;
}
/**
* @return the rangeBottomMin
*/
public Number getRangeBottomMin() {
return rangeBottomMin;
}
/**
* @param rangeBottomMin the rangeBottomMin to set
*/
public synchronized void setRangeBottomMin(Number rangeBottomMin) {
this.rangeBottomMin = rangeBottomMin;
}
/**
* @return the rangeBottomMax
*/
public Number getRangeBottomMax() {
return rangeBottomMax;
}
/**
* @param rangeBottomMax the rangeBottomMax to set
*/
public synchronized void setRangeBottomMax(Number rangeBottomMax) {
this.rangeBottomMax = rangeBottomMax;
}
/**
* @return the domainLeftMin
*/
public Number getDomainLeftMin() {
return domainLeftMin;
}
/**
* @param domainLeftMin the domainLeftMin to set
*/
public synchronized void setDomainLeftMin(Number domainLeftMin) {
this.domainLeftMin = domainLeftMin;
}
/**
* @return the domainLeftMax
*/
public Number getDomainLeftMax() {
return domainLeftMax;
}
/**
* @param domainLeftMax the domainLeftMax to set
*/
public synchronized void setDomainLeftMax(Number domainLeftMax) {
this.domainLeftMax = domainLeftMax;
}
/**
* @return the domainRightMin
*/
public Number getDomainRightMin() {
return domainRightMin;
}
/**
* @param domainRightMin the domainRightMin to set
*/
public synchronized void setDomainRightMin(Number domainRightMin) {
this.domainRightMin = domainRightMin;
}
/**
* @return the domainRightMax
*/
public Number getDomainRightMax() {
return domainRightMax;
}
/**
* @param domainRightMax the domainRightMax to set
*/
public synchronized void setDomainRightMax(Number domainRightMax) {
this.domainRightMax = domainRightMax;
}
}