/*
* Copyright 2011 Invient (www.invient.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.invient.vaadin.charts;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.ClientWidget;
import com.vaadin.ui.Component;
import com.invient.vaadin.charts.InvientCharts.SeriesCUR.SeriesCURType;
import com.invient.vaadin.charts.InvientChartsConfig.BaseLineConfig;
import com.invient.vaadin.charts.InvientChartsConfig.PointConfig;
import com.invient.vaadin.charts.InvientChartsConfig.SeriesConfig;
import com.invient.vaadin.charts.InvientChartsConfig.XAxis;
import com.invient.vaadin.charts.InvientChartsConfig.YAxis;
import com.invient.vaadin.charts.widgetset.client.ui.VInvientCharts;
/**
* A Vaddin component representing charts. It is a the main class of
* InvientCharts library.
*
* A chart typically contains one or more series of same or different types.
* This class allows us to specify series of different types say line and pie
* and hence it makes it easy to build a combination chart.
*
* After a chart {@link InvientChart} is created, the following changes to the
* chart will be reflected rendered on the webkit.
* <ul>
* <li>Update chart {@link Title} and/or {@link SubTitle}</li>
* <li>Modify chart size</li>
* <li>Add, update and delete of {@link PlotBand} and {@link PlotLine}</li>
* <li>Set or update axis categories</li>
* <li>Set or update axis min and max values</li>
* <li>Add, update and removal of {@link Series}</li>
* <li>Register and unregister event listeners</li>
* </ul>
*
* @author Invient
*
*/
/**
* @author chirag
*
*/
@SuppressWarnings("serial")
@ClientWidget(VInvientCharts.class)
public class InvientCharts extends AbstractComponent {
private InvientChartsConfig chartConfig;
/**
* Creates this chart object with given chart configuration
*
* @param chartConfig
*/
public InvientCharts(InvientChartsConfig chartConfig) {
if (chartConfig == null) {
throw new IllegalArgumentException(
"The chart cannot be created without chartConfig argument.");
}
this.chartConfig = chartConfig;
}
/**
* Returns chart configuration object
* @return
*/
public InvientChartsConfig getConfig() {
return this.chartConfig;
}
@Override
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
// Configurations options
target.startTag("options");
if (chartConfig != null) {
InvientChartsUtil.writeTitleConfig(target, chartConfig.getTitle());
InvientChartsUtil.writeSubtitleConfig(target,
chartConfig.getSubtitle());
InvientChartsUtil.writeCreditConfig(target, chartConfig.getCredit());
InvientChartsUtil.writeLegendConfig(target, chartConfig.getLegend());
InvientChartsUtil.writeTooltipConfig(target,
chartConfig.getTooltip());
InvientChartsUtil.writeGeneralChartConfig(target,
chartConfig.getGeneralChartConfig());
InvientChartsUtil.writeSeriesConfigPerSeriesType(target,
chartConfig.getSeriesConfig());
InvientChartsUtil.writeXAxes(target, chartConfig.getXAxes());
InvientChartsUtil.writeYAxes(target, chartConfig.getYAxes());
InvientChartsUtil.writeChartLabelConfig(target,
chartConfig.getChartLabel());
}
target.endTag("options");
target.startTag("chartData");
InvientChartsUtil.writeSeries(target, chartConfig
.getGeneralChartConfig().getType(), this.chartSeries,
chartConfig.getXAxes(), chartConfig.getYAxes());
target.endTag("chartData");
// Events
target.startTag("events");
// Chart Events
paintChartEvents(target);
// Series/Point Events
paintSeriesAndPointEvents(target);
target.endTag("events");
// If the flag reloadChartData is true then the
// client will ignore seriesOperations and
// remove all existing series of a chart and
// add series info received from the server.
target.addAttribute("reloadChartSeries", reloadChartSeries);
target.startTag("chartDataUpdates");
if (!reloadChartSeries) {
InvientChartsUtil.writeChartDataUpdates(target, seriesCURSet);
}
target.endTag("chartDataUpdates");
// reset flag
reloadChartSeries = false;
// reset series operations
seriesCURSet.clear();
}
private void paintChartEvents(PaintTarget target) throws PaintException {
target.startTag("chartEvents");
if (chartAddSeriesListener != null && chartAddSeriesListener.size() > 0) {
target.addAttribute("addSeries", true);
}
if (chartClickListener != null && chartClickListener.size() > 0) {
target.addAttribute("click", true);
}
if (chartZoomListener != null && chartZoomListener.size() > 0) {
target.addAttribute("selection", true);
}
target.endTag("chartEvents");
}
private void paintSeriesAndPointEvents(PaintTarget target)
throws PaintException {
target.startTag("seriesEvents");
// For each series type, check if listeners exist. If so then add.
for (SeriesType seriesType : SeriesType.values()) {
paintSeriesEvents(target, seriesType);
}
target.endTag("seriesEvents");
}
private void paintSeriesEvents(PaintTarget target, SeriesType seriesType)
throws PaintException {
String tagName = seriesType.getName();
target.startTag(tagName);
if (seriesClickListeners.containsKey(seriesType)
&& seriesClickListeners.get(seriesType).size() > 0) {
target.addAttribute("click", true);
}
if (seriesHideListeners.containsKey(seriesType)
&& seriesHideListeners.get(seriesType).size() > 0) {
target.addAttribute("hide", true);
}
if (seriesShowListeners.containsKey(seriesType)
&& seriesShowListeners.get(seriesType).size() > 0) {
target.addAttribute("show", true);
}
if (seriesLegendItemClickListeners.containsKey(seriesType)
&& seriesLegendItemClickListeners.get(seriesType).size() > 0) {
target.addAttribute("legendItemClick", true);
}
// Check for point events
paintPointEvents(target, seriesType);
//
target.endTag(tagName);
}
private void paintPointEvents(PaintTarget target, SeriesType seriesType)
throws PaintException {
target.startTag("pointEvents");
if (pointClickListeners.containsKey(seriesType)
&& pointClickListeners.get(seriesType).size() > 0) {
target.addAttribute("click", true);
}
if (pointRemoveListeners.containsKey(seriesType)
&& pointRemoveListeners.get(seriesType).size() > 0) {
target.addAttribute("remove", true);
}
if (pointSelectListeners.containsKey(seriesType)
&& pointSelectListeners.get(seriesType).size() > 0) {
target.addAttribute("select", true);
}
if (pointUnselectListeners.containsKey(seriesType)
&& pointUnselectListeners.get(seriesType).size() > 0) {
target.addAttribute("unselect", true);
}
// Event applicable only for pie chart
if (SeriesType.PIE.equals(seriesType)
&& pieChartLegendItemClickListener.size() > 0) {
target.addAttribute("legendItemClick", true);
}
target.endTag("pointEvents");
}
@Override
@SuppressWarnings("unchecked")
public void changeVariables(Object source, Map<String, Object> variables) {
if (variables.containsKey("event")) {
Map<String, Object> eventData = (Map<String, Object>) variables
.get("eventData");
String eventName = (String) variables.get("event");
if (eventName.equalsIgnoreCase("addSeries")) {
fireAddSeries();
} else if (eventName.equalsIgnoreCase("chartClick")) {
double xAxisPos = Double.parseDouble((String) eventData
.get("xAxisPos"));
double yAxisPos = Double.parseDouble((String) eventData
.get("yAxisPos"));
//
MousePosition mousePosition = getClickPosition(eventData);
fireChartClick(new DecimalPoint(xAxisPos, yAxisPos),
mousePosition);
} else if (eventName.equalsIgnoreCase("chartZoom")) {
double xAxisMin = Double.parseDouble((String) eventData
.get("xAxisMin"));
double xAxisMax = Double.parseDouble((String) eventData
.get("xAxisMax"));
double yAxisMin = Double.parseDouble((String) eventData
.get("yAxisMin"));
double yAxisMax = Double.parseDouble((String) eventData
.get("yAxisMax"));
fireChartZoom(new ChartArea(xAxisMin, xAxisMax, yAxisMin,
yAxisMax));
} else if (eventName.equalsIgnoreCase("chartResetZoom")) {
fireChartResetZoom();
} else if (eventName.equalsIgnoreCase("seriesClick")) {
PointEventData pointEventData = getPointEventData(eventData);
//
MousePosition mousePosition = getClickPosition(eventData);
fireSeriesClick(
getSeriesFromEventData(pointEventData.getSeriesName()),
getPointFromEventData(pointEventData), mousePosition);
} else if (eventName.equalsIgnoreCase("seriesHide")) {
String seriesName = (String) eventData.get("seriesName");
fireSeriesHide(getSeriesFromEventData(seriesName));
} else if (eventName.equalsIgnoreCase("seriesShow")) {
String seriesName = (String) eventData.get("seriesName");
fireSeriesShow(getSeriesFromEventData(seriesName));
} else if (eventName.equalsIgnoreCase("seriesLegendItemClick")) {
String seriesName = (String) eventData.get("seriesName");
fireSeriesLegendItemClick(getSeriesFromEventData(seriesName));
} else if (eventName.equalsIgnoreCase("pieLegendItemClick")) {
PointEventData pointEventData = getPointEventData(eventData);
fireLegendItemClick(getPointFromEventData(pointEventData));
} else if (eventName.equalsIgnoreCase("pointClick")) {
MousePosition mousePosition = getClickPosition(eventData);
//
PointEventData pointEventData = getPointEventData(eventData);
firePointClick(pointEventData.getCategory(),
getPointFromEventData(pointEventData), mousePosition);
} else if (eventName.equalsIgnoreCase("pointSelect")) {
PointEventData pointEventData = getPointEventData(eventData);
firePointSelect(pointEventData.getCategory(),
getPointFromEventData(pointEventData));
} else if (eventName.equalsIgnoreCase("pointUnselect")) {
PointEventData pointEventData = getPointEventData(eventData);
firePointUnselect(pointEventData.getCategory(),
getPointFromEventData(pointEventData));
} else if (eventName.equalsIgnoreCase("pointRemove")) {
PointEventData pointEventData = getPointEventData(eventData);
firePointRemove(pointEventData.getCategory(),
getPointFromEventData(pointEventData));
}
}
}
private Point getPointFromEventData(PointEventData eventData) {
// First locate a series and then point
Series series = getSeriesFromEventData(eventData.getSeriesName());
if (series != null) {
if (series instanceof XYSeries) {
for (DecimalPoint point : ((XYSeries) series).getPoints()) {
if (point.getY() != null
&& point.getY().doubleValue() == eventData
.getPointY()
&& point.getX() != null
&& point.getX().doubleValue() == eventData
.getPointX()) {
return point;
}
}
} else {
for (DateTimePoint point : ((DateTimeSeries) series)
.getPoints()) {
if (point.getY() != null
&& point.getY().doubleValue() == eventData
.getPointY()
&& point.getX() != null
&& getDateInMilliseconds(point.getX(),
((DateTimeSeries) series).isIncludeTime()) == (long) eventData
.getPointX()) {
return point;
}
}
}
}
// Should not happen
// If it happens then why? Any comments???
return null;
}
private static Long getDateInMilliseconds(Date dt, boolean isIncludeTime) {
if (dt == null) {
return null;
}
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(dt);
if (!isIncludeTime) {
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
}
return cal.getTimeInMillis();
}
private Series getSeriesFromEventData(String seriesName) {
for (Series series : this.chartSeries) {
if (series.getName().equals(seriesName)) {
return series;
}
}
// Should not happen
// If it happens then why? Any comments???
return null;
}
private void fireAddSeries() {
fireEvent(new ChartAddSeriesEvent(this, this));
}
private void fireChartClick(Point point, MousePosition mousePosition) {
fireEvent(new ChartClickEvent(this, this, point, mousePosition));
}
private void fireChartZoom(ChartArea selectedArea) {
fireEvent(new ChartZoomEvent(this, this, selectedArea));
}
private void fireChartResetZoom() {
fireEvent(new ChartResetZoomEvent(this, this));
}
private void fireSeriesClick(Series series, Point point,
MousePosition mousePosition) {
fireEvent(new SeriesClickEvent(this, this, series, point, mousePosition));
}
private void fireSeriesShow(Series series) {
fireEvent(new SeriesShowEvent(this, this, series));
}
private void fireSeriesHide(Series series) {
fireEvent(new SeriesHideEvent(this, this, series));
}
private void fireSeriesLegendItemClick(Series series) {
fireEvent(new SeriesLegendItemClickEvent(this, this, series));
}
private void firePointClick(String category, Point point,
MousePosition mousePosition) {
fireEvent(new PointClickEvent(this, this, category, point,
mousePosition));
}
private void firePointSelect(String category, Point point) {
fireEvent(new PointSelectEvent(this, this, category, point));
}
private void firePointUnselect(String category, Point point) {
fireEvent(new PointUnselectEvent(this, this, category, point));
}
private void firePointRemove(String category, Point point) {
fireEvent(new PointRemoveEvent(this, this, category, point));
}
private void fireLegendItemClick(Point point) {
fireEvent(new PieChartLegendItemClickEvent(this, this, point));
}
private PointEventData getPointEventData(Map<String, Object> eventData) {
String seriesName = (String) eventData.get("seriesName");
String category = (String) eventData.get("category");
double pointX = Double.valueOf((String) eventData.get("pointX"));
double pointY = Double.valueOf((String) eventData.get("pointY"));
return new PointEventData(seriesName, category, pointX, pointY);
}
private MousePosition getClickPosition(Map<String, Object> eventData) {
Integer mouseX = null;
if (eventData.get("mouseX") instanceof Integer) {
mouseX = (Integer) eventData.get("mouseX");
}
Integer mouseY = null;
if (eventData.get("mouseY") instanceof Integer) {
mouseY = (Integer) eventData.get("mouseY");
}
if (mouseX != null && mouseY != null) {
return new MousePosition(mouseX, mouseY);
}
return null;
}
/**
* This class contain mouse coordinates when a click event occurs on a
* chart, a series or a point.
*
* The mouse coordinates are in pixels.
*
* @author Invient
*
*/
public final class MousePosition implements Serializable {
private int mouseX;
private int mouseY;
/**
* Creates this object with given arguments.
*
* @param mouseX
* x position of mouse when a click event occurred, in pixel
* @param mouseY
* y position of mouse when a click event occurred, in pixel
*/
public MousePosition(int mouseX, int mouseY) {
this.mouseX = mouseX;
this.mouseY = mouseY;
}
/**
* Returns x position of mouse when a click event occurred, in pixel
*
* @return
*/
public int getMouseX() {
return mouseX;
}
/**
* x position of mouse when a click event occurred, in pixel
*
* @return
*/
public int getMouseY() {
return mouseY;
}
@Override
public String toString() {
return "MousePosition [mouseX=" + mouseX + ", mouseY=" + mouseY
+ "]";
}
}
private final class PointEventData implements Serializable {
private String seriesName;
private String category;
private double pointX;
private double pointY;
public PointEventData(String seriesName, String category,
double pointX, double pointY) {
super();
this.seriesName = seriesName;
this.category = category;
this.pointX = pointX;
this.pointY = pointY;
}
public String getSeriesName() {
return seriesName;
}
public String getCategory() {
return category;
}
public double getPointX() {
return pointX;
}
public double getPointY() {
return pointY;
}
@Override
public String toString() {
return "PointEventData [seriesName=" + seriesName + ", category="
+ category + ", pointX=" + pointX + ", pointY=" + pointY
+ "]";
}
}
/***************************** POINT CLICK EVENT *****************************/
/**
* Click event. This event is thrown, when any point of this chart is
* clicked and the point marker is enabled. The point marker is enabled by
* default.
*
* @author Invient
*/
public class PointClickEvent extends Component.Event {
private String category;
private Point point;
private InvientCharts chart;
private MousePosition mousePosition;
/**
* New instance of the point click event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param category
* a category to which point is associated in case of
* categorized axis,
* @param point
* the point on which the click event occurred
* @param mousePosition
* the position of a mouse when the click event occurred
*/
public PointClickEvent(Component source, InvientCharts chart,
String category, Point point, MousePosition mousePosition) {
super(source);
this.chart = chart;
this.category = category;
this.point = point;
this.mousePosition = mousePosition;
}
/**
* Returns a category to which point is associated in case of
* categorized axis only.
*
* @return
*/
public String getCategory() {
return category;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return chart;
}
/**
* Returns the point on which the click event occurred
*
* @return
*/
public Point getPoint() {
return this.point;
}
/**
* Returns the position of a mouse when the click event occurred
*
* @return
*/
public MousePosition getMousePosition() {
return mousePosition;
}
}
/**
* Interface for listening for a {@link PointClickEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface PointClickListener extends Serializable {
public void pointClick(PointClickEvent pointClickEvent);
}
private Map<SeriesType, Set<PointClickListener>> pointClickListeners = new HashMap<SeriesType, Set<PointClickListener>>();
/**
* Adds the point click listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(PointClickListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointClickListeners.containsKey(seriesType)) {
pointClickListeners.get(seriesType).add(listener);
} else {
Set<PointClickListener> listeners = new HashSet<PointClickListener>();
listeners.add(listener);
pointClickListeners.put(seriesType, listeners);
}
}
addListener(PointClickEvent.class, listener, POINT_CLICK_METHOD);
}
/**
* Removes the point click listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(PointClickListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointClickListeners.containsKey(seriesType)) {
pointClickListeners.get(seriesType).remove(listener);
}
}
removeListener(PointClickEvent.class, listener, POINT_CLICK_METHOD);
}
/**
* Point remove event. This event is thrown, when any point of this chart is
* removed from its series.
*
* This event is EXPERIMENTAL ONLY.
*
* @author Invient
*/
public class PointRemoveEvent extends Component.Event {
private String category;
private Point point;
private InvientCharts chart;
/**
* New instance of the point remove event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param category
* a category to which point is associated in case of
* categorized axis,
* @param point
* the point removed
*/
public PointRemoveEvent(Component source, InvientCharts chart,
String category, Point point) {
super(source);
this.chart = chart;
this.category = category;
this.point = point;
}
/**
* Returns a category to which point is associated in case of
* categorized axis only.
*
* @return
*/
public String getCategory() {
return category;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return chart;
}
/**
* Returns the point which has been removed
*
* @return
*/
public Point getPoint() {
return this.point;
}
}
/**
* Interface for listening for a {@link PointRemoveEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface PointRemoveListener extends Serializable {
public void pointRemove(PointRemoveEvent pointRemoveEvent);
}
private Map<SeriesType, Set<PointRemoveListener>> pointRemoveListeners = new HashMap<SeriesType, Set<PointRemoveListener>>();
/**
* Adds the point remove listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(PointRemoveListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointRemoveListeners.containsKey(seriesType)) {
pointRemoveListeners.get(seriesType).add(listener);
} else {
Set<PointRemoveListener> listeners = new HashSet<PointRemoveListener>();
listeners.add(listener);
pointRemoveListeners.put(seriesType, listeners);
}
}
addListener(PointRemoveEvent.class, listener, POINT_REMOVE_METHOD);
}
/**
* Removes the point remove listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(PointRemoveListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointRemoveListeners.containsKey(seriesType)) {
pointRemoveListeners.get(seriesType).remove(listener);
}
}
pointRemoveListeners.remove(listener);
removeListener(PointRemoveEvent.class, listener, POINT_REMOVE_METHOD);
}
/**
* Poin unselect event. This event is thrown, when any point of this chart
* is unselected and the point marker is enabled. The point marker is
* enabled by default.
*
* @author Invient
*/
public class PointUnselectEvent extends Component.Event {
private String category;
private Point point;
private InvientCharts chart;
/**
* New instance of the point unselect event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param category
* a category to which point is associated in case of
* categorized axis,
* @param point
* the point unselected as a result of this event
*/
public PointUnselectEvent(Component source, InvientCharts chart,
String category, Point point) {
super(source);
this.chart = chart;
this.category = category;
this.point = point;
}
/**
* Returns a category to which point is associated in case of
* categorized axis only.
*
* @return
*/
public String getCategory() {
return category;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return chart;
}
/**
* Returns the unselected point
*
* @return
*/
public Point getPoint() {
return this.point;
}
}
/**
* Interface for listening for a {@link PointUnselectEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface PointUnselectListener extends Serializable {
public void pointUnSelect(PointUnselectEvent pointUnSelectEvent);
}
private Map<SeriesType, Set<PointUnselectListener>> pointUnselectListeners = new HashMap<SeriesType, Set<PointUnselectListener>>();
/**
* Adds the point unselect listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(PointUnselectListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointUnselectListeners.containsKey(seriesType)) {
pointUnselectListeners.get(seriesType).add(listener);
} else {
Set<PointUnselectListener> listeners = new HashSet<PointUnselectListener>();
listeners.add(listener);
pointUnselectListeners.put(seriesType, listeners);
}
}
addListener(PointUnselectEvent.class, listener, POINT_UNSELECT_METHOD);
}
/**
* Removes the point unselect listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(PointUnselectListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointUnselectListeners.containsKey(seriesType)) {
pointUnselectListeners.get(seriesType).remove(listener);
}
}
removeListener(PointUnselectEvent.class, listener,
POINT_UNSELECT_METHOD);
}
/**
* Point select event. This event is thrown, when any point of this chart is
* selected and the point marker is enabled. The point marker is enabled by
* default.
*
* @author Invient
*/
public class PointSelectEvent extends Component.Event {
private String category;
private Point point;
private InvientCharts chart;
/**
* New instance of the point select event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param category
* a category to which point is associated in case of
* categorized axis,
* @param point
* the point selected as a result of this event
*/
public PointSelectEvent(Component source, InvientCharts chart,
String category, Point point) {
super(source);
this.chart = chart;
this.category = category;
this.point = point;
}
/**
* Returns a category to which point is associated in case of
* categorized axis only.
*
* @return
*/
public String getCategory() {
return category;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return chart;
}
/**
* Returns the selected point
*
* @return
*/
public Point getPoint() {
return this.point;
}
}
/**
* Interface for listening for a {@link PointSelectListener} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface PointSelectListener extends Serializable {
public void pointSelected(PointSelectEvent pointSelectEvent);
}
private Map<SeriesType, Set<PointSelectListener>> pointSelectListeners = new HashMap<SeriesType, Set<PointSelectListener>>();
/**
* Adds the point select listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(PointSelectListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointSelectListeners.containsKey(seriesType)) {
pointSelectListeners.get(seriesType).add(listener);
} else {
Set<PointSelectListener> listeners = new HashSet<PointSelectListener>();
listeners.add(listener);
pointSelectListeners.put(seriesType, listeners);
}
}
addListener(PointSelectEvent.class, listener, POINT_SELECT_METHOD);
}
/**
* Removes the point select listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(PointSelectListener listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (pointSelectListeners.containsKey(seriesType)) {
pointSelectListeners.get(seriesType).remove(listener);
}
}
removeListener(PointSelectEvent.class, listener, POINT_SELECT_METHOD);
}
private static final Method POINT_CLICK_METHOD;
private static final Method POINT_REMOVE_METHOD;
private static final Method POINT_SELECT_METHOD;
private static final Method POINT_UNSELECT_METHOD;
static {
try {
POINT_CLICK_METHOD = PointClickListener.class.getDeclaredMethod(
"pointClick", new Class[] { PointClickEvent.class });
POINT_REMOVE_METHOD = PointRemoveListener.class.getDeclaredMethod(
"pointRemove", new Class[] { PointRemoveEvent.class });
POINT_SELECT_METHOD = PointSelectListener.class.getDeclaredMethod(
"pointSelected", new Class[] { PointSelectEvent.class });
POINT_UNSELECT_METHOD = PointUnselectListener.class
.getDeclaredMethod("pointUnSelect",
new Class[] { PointUnselectEvent.class });
} catch (final java.lang.NoSuchMethodException e) {
// This should not happen
throw new java.lang.RuntimeException(
"Internal error finding methods in Button");
}
}
// ***************************** Series Events ****************************/
/**
* Series click event. This event is thrown, when any series of this chart
* is clicked.
*
* @author Invient
*/
public class SeriesClickEvent extends Component.Event {
private Point point;
private Series series;
private InvientCharts chart;
private MousePosition mousePosition;
/**
* New instance of the series click event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param series
* the series on which click event occurred
* @param point
* the closest point of a series
* @param mousePosition
* the position of a mouse when the click event occurred
*/
public SeriesClickEvent(Component source, InvientCharts chart,
Series series, Point point, MousePosition mousePosition) {
super(source);
this.chart = chart;
this.series = series;
this.point = point;
this.mousePosition = mousePosition;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the series object on which the click event occurred
*
* @return
*/
public Series getSeries() {
return this.series;
}
/**
* Returns the closest point of a series
*
* @return
*/
public Point getNearestPoint() {
return this.point;
}
/**
* Returns the position of a mouse when the click event occurred
*
* @return
*/
public MousePosition getMousePosition() {
return mousePosition;
}
}
/**
* Interface for listening for a {@link SeriesClickListerner} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface SeriesClickListerner extends Serializable {
public void seriesClick(SeriesClickEvent seriesClickEvent);
}
private Map<SeriesType, Set<SeriesClickListerner>> seriesClickListeners = new HashMap<SeriesType, Set<SeriesClickListerner>>();
/**
* Adds the series click listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(SeriesClickListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesClickListeners.containsKey(seriesType)) {
seriesClickListeners.get(seriesType).add(listener);
} else {
Set<SeriesClickListerner> listeners = new HashSet<SeriesClickListerner>();
listeners.add(listener);
seriesClickListeners.put(seriesType, listeners);
}
}
addListener(SeriesClickEvent.class, listener, SERIES_CLICK_METHOD);
}
/**
* Removes the series click listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(SeriesClickListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesClickListeners.containsKey(seriesType)) {
seriesClickListeners.get(seriesType).remove(listener);
}
}
removeListener(SeriesClickEvent.class, listener, SERIES_CLICK_METHOD);
}
/**
* Series Hide event. This event is thrown, when any series of this chart is
* hidden.
*
* @author Invient
*/
public class SeriesHideEvent extends Component.Event {
private Series series;
private InvientCharts chart;
/**
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param series
* the series which got hidden
*/
public SeriesHideEvent(Component source, InvientCharts chart,
Series series) {
super(source);
this.chart = chart;
this.series = series;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the series which got hidden
*
* @return
*/
public Series getSeries() {
return this.series;
}
}
/**
* Interface for listening for a {@link SeriesHideEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface SeriesHideListerner extends Serializable {
public void seriesHide(SeriesHideEvent seriesHideEvent);
}
private Map<SeriesType, Set<SeriesHideListerner>> seriesHideListeners = new HashMap<SeriesType, Set<SeriesHideListerner>>();
/**
* Adds the series hide listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(SeriesHideListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesHideListeners.containsKey(seriesType)) {
seriesHideListeners.get(seriesType).add(listener);
} else {
Set<SeriesHideListerner> listeners = new HashSet<SeriesHideListerner>();
listeners.add(listener);
seriesHideListeners.put(seriesType, listeners);
}
}
addListener(SeriesHideEvent.class, listener, SERIES_HIDE_METHOD);
}
/**
* Removes the series hide listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(SeriesHideListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesHideListeners.containsKey(seriesType)) {
seriesHideListeners.get(seriesType).remove(listener);
}
}
removeListener(SeriesHideEvent.class, listener, SERIES_HIDE_METHOD);
}
/**
* Series show event. This event is thrown, when any series of this chart is
* displayed after a chart is created.
*
* @author Invient
*/
public class SeriesShowEvent extends Component.Event {
private Series series;
private InvientCharts chart;
/**
* New instance of the series show event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param series
* the series which got displayed
*/
public SeriesShowEvent(Component source, InvientCharts chart,
Series series) {
super(source);
this.chart = chart;
this.series = series;
}
/**
* Returns the chart object associated with the series
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* the series which got displayed
*
* @return
*/
public Series getSeries() {
return this.series;
}
}
/**
* Interface for listening for a {@link SeriesShowEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface SeriesShowListerner extends Serializable {
public void seriesShow(SeriesShowEvent seriesShowEvent);
}
private Map<SeriesType, Set<SeriesShowListerner>> seriesShowListeners = new HashMap<SeriesType, Set<SeriesShowListerner>>();
/**
* Adds the series show listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(SeriesShowListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesShowListeners.containsKey(seriesType)) {
seriesShowListeners.get(seriesType).add(listener);
} else {
Set<SeriesShowListerner> listeners = new HashSet<SeriesShowListerner>();
listeners.add(listener);
seriesShowListeners.put(seriesType, listeners);
}
}
addListener(SeriesShowEvent.class, listener, SERIES_SHOW_METHOD);
}
/**
* Removes the series show listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(SeriesShowListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesShowListeners.containsKey(seriesType)) {
seriesShowListeners.get(seriesType).remove(listener);
}
}
removeListener(SeriesShowEvent.class, listener, SERIES_SHOW_METHOD);
}
// LEGENDITEMCLICK
// This event occurs when a series is clicked in the legend.
// This event is not applicable for PieChart instead use
// LegendItemClickEvent/LegendItemClickListener
/**
* Series legend item click event. This event is thrown, when legend item is
* clicked. This event is not applicable for PieChart instead use
* {@link LegendItemClickEvent}
*
* @author Invient
*/
public class SeriesLegendItemClickEvent extends Component.Event {
private Series series;
private InvientCharts chart;
/**
* New instance of the point click event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param series
* the series associated with the legend item
*/
public SeriesLegendItemClickEvent(Component source, InvientCharts chart,
Series series) {
super(source);
this.chart = chart;
this.series = series;
}
/**
* Returns the chart object associated with the series
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the series associated with the legend item
*
* @return
*/
public Series getSeries() {
return this.series;
}
}
/**
* Interface for listening for a {@link SeriesLegendItemClickEvent}
* triggered by {@link InvientCharts}
*
* @author Invient
*
*/
public interface SeriesLegendItemClickListerner extends Serializable {
public void seriesLegendItemClick(
SeriesLegendItemClickEvent seriesLegendItemClickEvent);
}
private Map<SeriesType, Set<SeriesLegendItemClickListerner>> seriesLegendItemClickListeners = new HashMap<SeriesType, Set<SeriesLegendItemClickListerner>>();
/**
* Adds the series legend item click listener. If the argument seriesTypes
* is not specified then the listener will be added for all series type
* otherwise it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(SeriesLegendItemClickListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesLegendItemClickListeners.containsKey(seriesType)) {
seriesLegendItemClickListeners.get(seriesType).add(listener);
} else {
Set<SeriesLegendItemClickListerner> listeners = new HashSet<SeriesLegendItemClickListerner>();
listeners.add(listener);
seriesLegendItemClickListeners.put(seriesType, listeners);
}
}
addListener(SeriesLegendItemClickEvent.class, listener,
SERIES_LEGENDITEM_CLICK_METHOD);
}
/**
* Removes the series legend item click listener. If the argument
* seriesTypes is not specified then the listener will be removed only for a
* series type SeriesType.COMMONSERIES otherwise the listener will be
* removed for all specified series types.
*
* @param listener
* the listener to be removed
* @param seriesTypes
* one or more series types as defined by (@link SeriesType}
*/
public void removeListener(SeriesLegendItemClickListerner listener,
SeriesType... seriesTypes) {
if (seriesTypes.length == 0) {
seriesTypes = new SeriesType[] { SeriesType.COMMONSERIES };
}
for (SeriesType seriesType : seriesTypes) {
if (seriesLegendItemClickListeners.containsKey(seriesType)) {
seriesLegendItemClickListeners.get(seriesType).remove(listener);
}
}
removeListener(SeriesLegendItemClickEvent.class, listener,
SERIES_LEGENDITEM_CLICK_METHOD);
}
private static final Method SERIES_CLICK_METHOD;
// private static final Method SERIES_CHECKBOX_CLICK_METHOD;
private static final Method SERIES_HIDE_METHOD;
private static final Method SERIES_SHOW_METHOD;
private static final Method SERIES_LEGENDITEM_CLICK_METHOD;
static {
try {
SERIES_CLICK_METHOD = SeriesClickListerner.class.getDeclaredMethod(
"seriesClick", new Class[] { SeriesClickEvent.class });
// SERIES_CHECKBOX_CLICK_METHOD = SeriesCheckboxClickListerner.class
// .getDeclaredMethod("seriesCheckboxClick",
// new Class[] { SeriesCheckboxClickEvent.class });
SERIES_HIDE_METHOD = SeriesHideListerner.class.getDeclaredMethod(
"seriesHide", new Class[] { SeriesHideEvent.class });
SERIES_SHOW_METHOD = SeriesShowListerner.class.getDeclaredMethod(
"seriesShow", new Class[] { SeriesShowEvent.class });
SERIES_LEGENDITEM_CLICK_METHOD = SeriesLegendItemClickListerner.class
.getDeclaredMethod("seriesLegendItemClick",
new Class[] { SeriesLegendItemClickEvent.class });
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException(
"Internal error finding methods in Button");
}
}
/**************************** PieChart related events ****************************/
// PieChart LEGENDITEMCLICK
// This event occurs when a point of a PieChart is clicked
/**
* PieChart legend item click event. This event is thrown, when the legend
* item belonging to the pie point (slice) is clicked.
*
* @author Invient
*/
public class PieChartLegendItemClickEvent extends Component.Event {
private InvientCharts chart;
private Point point;
/**
* New instance of the piechart legend item click event
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param point
* the pie point (slice) associated with the legend item
*/
public PieChartLegendItemClickEvent(Component source,
InvientCharts chart, Point point) {
super(source);
this.chart = chart;
this.point = point;
}
/**
* Returns the chart object associated with the point
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the pie point (slice) associated with the legend item
*
* @return
*/
public Point getPoint() {
return this.point;
}
}
/**
* Interface for listening for a {@link PieChartLegendItemClickEvent}
* triggered by {@link InvientCharts}
*
* @author Invient
*
*/
public interface PieChartLegendItemClickListener extends Serializable {
public void legendItemClick(
PieChartLegendItemClickEvent legendItemClickEvent);
}
private Set<PieChartLegendItemClickListener> pieChartLegendItemClickListener = new HashSet<PieChartLegendItemClickListener>();
/**
* Adds the piechart legend item click listener. If the argument seriesTypes
* is not specified then the listener will be added for all series type
* otherwise it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(PieChartLegendItemClickListener listener) {
pieChartLegendItemClickListener.add(listener);
addListener(PieChartLegendItemClickEvent.class, listener,
LEGENDITEM_CLICK_METHOD);
}
/**
* Removes the piechart legend item click listener. If the argument
* seriesTypes is not specified then the listener will be removed only for a
* series type SeriesType.COMMONSERIES otherwise the listener will be
* removed for all specified series types.
*
* @param listener
* the listener to be removed
*/
public void removeListener(PieChartLegendItemClickListener listener) {
pieChartLegendItemClickListener.remove(listener);
removeListener(PieChartLegendItemClickEvent.class, listener,
LEGENDITEM_CLICK_METHOD);
}
private static final Method LEGENDITEM_CLICK_METHOD;
static {
try {
LEGENDITEM_CLICK_METHOD = PieChartLegendItemClickListener.class
.getDeclaredMethod("legendItemClick",
new Class[] { PieChartLegendItemClickEvent.class });
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException(
"Internal error finding methods in Button");
}
}
/***************************** Chart Events *****************************/
/**
* Chart Click event. This event is thrown, when this chart is clicked.
*
* @author Invient
*/
public class ChartClickEvent extends Component.Event {
private InvientCharts chart;
private Point point;
private MousePosition mousePosition;
/**
* New instance of the chart click event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param point
* the position where the click event occurred in axes units
* @param mousePosition
* the coordinate of mouse where the click event occurred in
* pixels
*/
public ChartClickEvent(Component source, InvientCharts chart,
Point point, MousePosition mousePosition) {
super(source);
this.chart = chart;
this.point = point;
this.mousePosition = mousePosition;
}
/**
* Returns the chart object on which the click event occurred
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the point representing the position where the click event
* occurred in axes units
*
* @return
*/
public Point getPoint() {
return this.point;
}
/**
* Returns the position of a mouse when the click event occurred
*
* @return
*/
public MousePosition getMousePosition() {
return mousePosition;
}
@Override
public String toString() {
return "ChartClickEvent [point=" + point + ", mousePosition="
+ mousePosition + "]";
}
}
/**
* Interface for listening for a {@link ChartClickEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface ChartClickListener extends Serializable {
public void chartClick(ChartClickEvent chartClickEvent);
}
private Set<ChartClickListener> chartClickListener = new HashSet<ChartClickListener>();
/**
* Adds the chart click listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(ChartClickListener listener) {
chartClickListener.add(listener);
addListener(ChartClickEvent.class, listener, CHART_CLICK_METHOD);
}
/**
* Removes the chart click listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
*/
public void removeListener(ChartClickListener listener) {
chartClickListener.remove(listener);
removeListener(ChartClickEvent.class, listener, CHART_CLICK_METHOD);
}
/**
* Add series event. This event is thrown, when a series is added to the
* chart.
*
* @author Invient
*/
public class ChartAddSeriesEvent extends Component.Event {
private InvientCharts chart;
/**
* New instance of the chart add series event.
*
* @param source
* @param chart
*/
public ChartAddSeriesEvent(Component source, InvientCharts chart) {
super(source);
this.chart = chart;
}
/**
* Returns the chart object to which a series is added
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
}
/**
* Interface for listening for a {@link ChartAddSeriesEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface ChartAddSeriesListener extends Serializable {
public void chartAddSeries(ChartAddSeriesEvent chartAddSeriesEvent);
}
private Set<ChartAddSeriesListener> chartAddSeriesListener = new HashSet<ChartAddSeriesListener>();
/**
* Adds the series add listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(ChartAddSeriesListener listener) {
chartAddSeriesListener.add(listener);
addListener(ChartAddSeriesEvent.class, listener,
CHART_ADD_SERIES_METHOD);
}
/**
* Removes the series add listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
*/
public void removeListener(ChartAddSeriesListener listener) {
chartAddSeriesListener.remove(listener);
removeListener(ChartAddSeriesEvent.class, listener,
CHART_ADD_SERIES_METHOD);
}
/**
* Defines information on the selected area.
*
* @author Invient
*
*/
public final class ChartArea implements Serializable {
private double xAxisMin;
private double xAxisMax;
private double yAxisMin;
private double yAxisMax;
public ChartArea(double xAxisMin, double xAxisMax, double yAxisMin,
double yAxisMax) {
this.xAxisMin = xAxisMin;
this.xAxisMax = xAxisMax;
this.yAxisMin = yAxisMin;
this.yAxisMax = yAxisMax;
}
public double getxAxisMin() {
return xAxisMin;
}
public double getxAxisMax() {
return xAxisMax;
}
public double getyAxisMin() {
return yAxisMin;
}
public double getyAxisMax() {
return yAxisMax;
}
@Override
public String toString() {
return "ChartSelectedArea [xAxisMin=" + xAxisMin + ", xAxisMax="
+ xAxisMax + ", yAxisMin=" + yAxisMin + ", yAxisMax="
+ yAxisMax + "]";
}
}
/**
* Chart zoom event. This event is thrown, when an area of the chart has
* been selected.
*
* @author Invient
*/
public class ChartZoomEvent extends Component.Event {
private InvientCharts chart;
private ChartArea chartArea;
/**
* New instance of the chart zoom event.
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
* @param chartArea
* the chartArea object containing dimensions of zoomed area
* of the chart
*/
public ChartZoomEvent(Component source, InvientCharts chart,
ChartArea chartArea) {
super(source);
this.chart = chart;
this.chartArea = chartArea;
}
/**
* Returns the chart object for which the zoom event has occurred
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
/**
* Returns the chartArea object containing dimensions of zoomed area of
* the chart
*
* @return
*/
public ChartArea getChartArea() {
return this.chartArea;
}
}
/**
* Interface for listening for a {@link ChartZoomEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface ChartZoomListener extends Serializable {
public void chartZoom(ChartZoomEvent chartZoomEvent);
}
private Set<ChartZoomListener> chartZoomListener = new HashSet<ChartZoomListener>();
/**
* Adds the chart zoom listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(ChartZoomListener listener) {
chartZoomListener.add(listener);
addListener(ChartZoomEvent.class, listener, CHART_ZOOM_METHOD);
}
/**
* Removes the chart zoom listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
*/
public void removeListener(ChartZoomListener listener) {
chartZoomListener.remove(listener);
removeListener(ChartZoomEvent.class, listener, CHART_ZOOM_METHOD);
}
/**
* Chart reset zoom event. This event is thrown, when a chart is reset by
* setting its zoom level to normal.
*
* @author Invient
*/
public class ChartResetZoomEvent extends Component.Event {
private InvientCharts chart;
/**
* New instance of the chart reset zoom event
*
* @param source
* the chart object itself
* @param chart
* the chart object itself
*/
public ChartResetZoomEvent(Component source, InvientCharts chart) {
super(source);
this.chart = chart;
}
/**
* Returns the chart object for which zoom has been reset to normal
*
* @return
*/
public InvientCharts getChart() {
return this.chart;
}
}
/**
* Interface for listening for a {@link ChartResetZoomEvent} triggered by
* {@link InvientCharts}
*
* @author Invient
*
*/
public interface ChartResetZoomListener extends Serializable {
public void chartResetZoom(ChartResetZoomEvent chartResetZoomEvent);
}
private Set<ChartResetZoomListener> chartResetZoomListener = new HashSet<ChartResetZoomListener>();
/**
* Adds the chart reset zoom listener. If the argument seriesTypes is not
* specified then the listener will be added for all series type otherwise
* it will be added for a specific series type
*
* @param listener
* the Listener to be added.
*/
public void addListener(ChartResetZoomListener listener) {
chartResetZoomListener.add(listener);
addListener(ChartResetZoomEvent.class, listener,
CHART_RESET_ZOOM_METHOD);
}
/**
* Removes the chart reset zoom listener. If the argument seriesTypes is not
* specified then the listener will be removed only for a series type
* SeriesType.COMMONSERIES otherwise the listener will be removed for all
* specified series types.
*
* @param listener
* the listener to be removed
*/
public void removeListener(ChartResetZoomListener listener) {
chartResetZoomListener.remove(listener);
removeListener(ChartResetZoomEvent.class, listener,
CHART_RESET_ZOOM_METHOD);
}
private static final Method CHART_CLICK_METHOD;
private static final Method CHART_ADD_SERIES_METHOD;
private static final Method CHART_ZOOM_METHOD;
private static final Method CHART_RESET_ZOOM_METHOD;
static {
try {
CHART_CLICK_METHOD = ChartClickListener.class.getDeclaredMethod(
"chartClick", new Class[] { ChartClickEvent.class });
CHART_ADD_SERIES_METHOD = ChartAddSeriesListener.class
.getDeclaredMethod("chartAddSeries",
new Class[] { ChartAddSeriesEvent.class });
CHART_ZOOM_METHOD = ChartZoomListener.class.getDeclaredMethod(
"chartZoom", new Class[] { ChartZoomEvent.class });
CHART_RESET_ZOOM_METHOD = ChartResetZoomListener.class
.getDeclaredMethod("chartResetZoom",
new Class[] { ChartResetZoomEvent.class });
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException(
"Internal error finding methods in Button");
}
}
// *************************************************************************//
// **************************** Chart Container
// ****************************//
// *************************************************************************//
private LinkedHashSet<Series> chartSeries = new LinkedHashSet<Series>();
private boolean reloadChartSeries = false;
/**
* The data of a chart is defined in terms of {@link Series}. This method
* removes all previously set series of this chart and adds the argument
* series. If the argument series is null then no actions are taken.
*
* @param series
* A collection of series to set as chart's data
*/
public void setSeries(LinkedHashSet<Series> series) {
if (series != null) {
reloadChartSeries = true;
this.chartSeries.clear();
this.seriesCURSet.clear();
for (Series seriesData : series) {
addSeries(seriesData);
}
}
}
/**
* Returns a series whose name matches the argument name.
*
* @param name
* the name of the series
* @return
*/
public Series getSeries(String name) {
for (Series series : this.chartSeries) {
if (series.getName().equals(name)) {
return series;
}
}
return null;
}
/**
* Adds the argument series to this chart.
*
* @param seriesData
* the series to be added
*/
public void addSeries(Series seriesData) {
if (this.chartSeries.add(seriesData)) {
addSeriesCUROperation(new SeriesCUR(SeriesCURType.ADD,
seriesData.getName()));
requestRepaint();
}
}
/**
* Removes a series whose name matches the argument name.
*
* @param name
* the name of the series
*/
public void removeSeries(String name) {
for (Iterator<Series> seriesItr = this.chartSeries.iterator(); seriesItr
.hasNext();) {
Series series = seriesItr.next();
if (series.getName().equals(name)) {
seriesItr.remove();
addSeriesCUROperation(new SeriesCUR(SeriesCURType.REMOVE,
series.getName()));
requestRepaint();
}
}
}
/**
* Removes the argument seriesData from this chart.
*
* @param seriesData
* the series object to be removed
*/
public void removeSeries(Series seriesData) {
if (this.chartSeries.remove(seriesData)) {
addSeriesCUROperation(new SeriesCUR(SeriesCURType.REMOVE,
seriesData.getName()));
requestRepaint();
}
}
/**
* This class represents a point of the chart's series. A series can have
* one or more points. A point has (X, Y) coordinates. None of the
* coordinates are mandatory. The name of a point can be displayed in a
* tooltip.
*
* To represent no activity or missing points in the chart, create a point
* with both X and Y as null or just Y as null.
*
* It is possible to specify custom configuration for each point. e.g. If a
* highest point can be marked in a chart with a different color using this
* configuration.
*
* A point cannot be created without a series. It must belong to a series.
* However, the point must be added to a series by calling Series.addPoint()
* or Series.setPoints() to permanently add point to the series.
*
* @author Invient
*
* @see DecimalPoint
* @see DateTimePoint
* @see PointConfig
*
*/
public static abstract class Point implements Serializable {
private String id;
private String name;
private Series series;
private PointConfig config;
private boolean isAutosetX;
/**
* Creates a point with given arguments.
*
* @param series
* The series to which the point must be associated.
* @exception IllegalArgumentException
* If the argument series is null
*
*/
public Point(Series series) {
if (series == null) {
throw new IllegalArgumentException(
"A point cannot be created without a series.");
}
this.series = series;
}
/**
* To allow creation of a point from inside of InvientCharts component
*/
private Point() {
// FIXME this is not a correct way of doing it.
}
/**
* Creates a point with given arguments.
*
* @param series
* The series to which the point must be associated.
* @param config
* The configuration for this point, if any
* @exception IllegalArgumentException
* If the argument series is null
*/
public Point(Series series, PointConfig config) {
this(series);
this.config = config;
}
/**
* Creates a point with given arguments.
*
* @param series
* The series to which the point must be associated.
* @param name
* name of this point
* @exception IllegalArgumentException
* If the argument series is null
*/
public Point(Series series, String name) {
this(series);
this.name = name;
}
/**
* Creates a point with given arguments.
*
* @param series
* The series to which the point must be associated.
* @param name
* name of this point
* @param config
* The configuration for this point, if any
* @exception IllegalArgumentException
* If the argument series is null
*/
public Point(Series series, String name, PointConfig config) {
this(series, name);
this.config = config;
}
String getId() {
return id;
}
/**
* Returns name of this point
*
* @return
*/
public String getName() {
return name;
}
/**
* Sets name of this point
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns {@link Series} associated with this point
* @return
*/
public Series getSeries() {
return series;
}
/**
* Returns {@link PointConfig} for this point
*
* @return
*/
public PointConfig getConfig() {
return config;
}
/**
* Sets {@link PointConfig} for this point
*
*/
public void setConfig(PointConfig config) {
this.config = config;
}
/**
* Returns true if X value of this point is set programmatically
*
* @return
*/
boolean isAutosetX() {
return isAutosetX;
}
/**
* If the argument is true it indicates that the X value of this point
* is set programmatically and user has not specified it.
*
* @return
*/
void setAutosetX(boolean isAutosetX) {
this.isAutosetX = isAutosetX;
}
/**
* Returns X value of this point
*
* @return
*/
public abstract Object getX();
/**
* Returns Y value of this point
*
* @return
*/
public abstract Object getY();
@Override
public String toString() {
return "Point [id=" + id + ", name=" + name + ", series="
+ series.getName() + ", config=" + config + "]";
}
}
/**
* This class represent a point with (X, Y) both as number. It should be
* used to add points to {@link XYSeries}
*
* @author Invient
*
*/
public static final class DecimalPoint extends Point {
private Double x;
private Double y;
/**
* @param series
* the series to which this belongs to
*/
public DecimalPoint(Series series) {
super(series);
}
/**
* @param series
* the series to which this point belongs to
* @param y
* the y value of this point
*/
public DecimalPoint(Series series, double y) {
super(series);
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param name
* the name of this point
* @param y
* the y value of this point
*/
public DecimalPoint(Series series, String name, double y) {
super(series, name);
this.y = y;
}
/**
* To allow creation of a point within the InvientChart.
* @param x
* @param y
*/
private DecimalPoint(double x, double y) {
// FIXME this is not a correct way of doing it.
super();
this.x = x;
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param name
* the name for this point
* @param y
* the y value of this point
* @param config
*/
public DecimalPoint(Series series, String name, double y,
PointConfig config) {
super(series, name, config);
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param y
* the y value of this point
* @param config
* the configuration for this point
*/
public DecimalPoint(Series series, double y, PointConfig config) {
super(series, config);
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param x
* the x value of this point
* @param y
* the y value of this point
*/
public DecimalPoint(Series series, double x, double y) {
this(series, x, y, null);
}
/**
* @param series
* the series to which this belongs to
* @param x
* the x value of this point
* @param y
* the y value of this point
* @param config
* the configuration of this point
*/
public DecimalPoint(Series series, double x, double y,
PointConfig config) {
super(series, config);
this.x = x;
this.y = y;
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Point#getX()
*/
@Override
public Double getX() {
return x;
}
/**
* Sets the x value of this point
*
* @param x
*/
public void setX(Double x) {
this.x = x;
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Point#getY()
*/
@Override
public Double getY() {
return y;
}
/**
* Sets the y value of this point
*
* @param y
*/
public void setY(Double y) {
this.y = y;
}
@Override
public String toString() {
return "DecimalPoint [x=" + x + ", y=" + y + ", id=" + getId()
+ ", name=" + getName() + ", seriesName="
+ (getSeries() != null ? getSeries().getName() : "") + "]";
}
}
/**
* This class represent a point with (X, Y) both as number. It should be
* used to add points to {@link DateTimeSeries}
*
* @author Invient
*
*/
public static final class DateTimePoint extends Point {
private Date x;
private Double y;
/**
* @param series
* the series to which this belongs to
*/
public DateTimePoint(Series series) {
super(series);
}
/**
* @param series
* the series to which this belongs to
* @param y
* the y value of this point
*/
public DateTimePoint(Series series, double y) {
this(series, "", y);
}
/**
* @param series
* the series to which this belongs to
* @param name
* the name of this point
* @param y
* the y value of this point
*/
public DateTimePoint(Series series, String name, double y) {
super(series, name);
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param name
* the name of this point
* @param y
* the y value of this point
* @param config
*/
public DateTimePoint(Series series, String name, double y,
PointConfig config) {
super(series, name, config);
this.y = y;
}
/**
* @param series
* the series to which this belongs to
* @param x
* the x value of this point
* @param y
* the y value of this point
*/
public DateTimePoint(Series series, Date x, double y) {
this(series, y);
this.x = x;
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Point#getX()
*/
public Date getX() {
return x;
}
/**
* Sets the x value of this point
*
* @param x
*/
public void setX(Date x) {
this.x = x;
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Point#getY()
*/
public Double getY() {
return y;
}
/**
* Sets the y value of this point
*
* @param y
*/
public void setY(Double y) {
this.y = y;
}
@Override
public String toString() {
return "DateTimePoint [x=" + getDateInMilliseconds(x, true)
+ ", y=" + y + ", id=" + getId() + ", name=" + getName()
+ ", seriesName="
+ (getSeries() != null ? getSeries().getName() : "") + "]";
}
}
/**
* This class defines a series of the chart. A series contains a collection
* of points. Series can be one of types defined by {@link SeriesType}.
*
* Each series must have unique name. If an attempt is made to add two
* series with same then only the first added series will be in effect.
*
* If the series type is not specified, it defaults to chart type and the
* default chart type is SeriesType.LINE. A series has unique xAxis and
* yAxis object associated with it. There is no need to set xAxis and yAxis
* unless the chart has more than one one axis of any type and the series
* must belong to any of the secondary axis.
*
* It is also possible to specify configuration for individual series and
* not just series type.
*
* @author Invient
*
*/
public static abstract class Series implements Serializable {
private LinkedHashSet points = new LinkedHashSet();
private String name = "";
private SeriesType type;
private String stack;
private XAxis xAxis;
private YAxis yAxis;
private SeriesConfig config;
/**
* Creates a series with given name
*
* @param name
* the name of this series
*/
public Series(String name) {
this.name = name;
}
/**
* Creates a series with given name and type
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
*/
public Series(String name, SeriesType seriesType) {
this(name);
this.type = seriesType;
}
/**
* Creates a series with given name and configuration
*
* @param name
* the name of this series
* @param config
* the configuration for this series
*/
public Series(String name, SeriesConfig config) {
this(name);
this.config = config;
}
/**
* Creates a series with given name, type and configuration
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
* @param config
* the configuration for this series
*/
public Series(String name, SeriesType seriesType, SeriesConfig config) {
this(name, config);
this.type = seriesType;
}
/**
* @return
*/
public SeriesConfig getConfig() {
return config;
}
/**
* @return
*/
public String getName() {
return name;
}
/**
* Sets name of this series
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return
*/
public SeriesType getType() {
return type;
}
/**
* Sets type of this series
*
* @param type
*/
public void setType(SeriesType type) {
this.type = type;
}
/**
* @return
*/
public String getStack() {
return stack;
}
/**
* By using this stack property, it is possible to group series in a
* stacked chart. Sets stack for this series. If two series belongs to
* the same stack then the resultant chart will be stacked chart
*
* @param stack
*/
public void setStack(String stack) {
this.stack = stack;
}
/**
* @return
*/
public XAxis getXAxis() {
return xAxis;
}
/**
* Sets xAxis of this series
*
* @param xAxis
*/
public void setXAxis(XAxis xAxis) {
this.xAxis = xAxis;
}
/**
* @return
*/
public YAxis getYAxis() {
return yAxis;
}
/**
* Sets yAxis of this series
*
* @param yAxis
*/
public void setYAxis(YAxis yAxis) {
this.yAxis = yAxis;
}
/**
* @param points
*/
protected void removePoint(Point... points) {
for (Point point : points) {
this.points.remove(point);
}
}
/**
* Removes all points in this series
*/
protected void removeAllPoints() {
this.points.clear();
}
/**
* Adds one or more points into this series, specified as an argument to
* this method
*
* @param points
*/
protected void addPoint(Point... points) {
for (Point point : points) {
this.points.add(point);
}
}
/**
* Returns all points of this series
*
* @return
*/
protected LinkedHashSet getPoints() {
return this.points;
}
/**
* Sets points into this series
*
* @param points
*/
protected void setPoints(LinkedHashSet points) {
if (points != null) {
this.points = points;
}
}
/**
* Show this series
*/
public void show() {
this.config = (this.config == null ? new SeriesConfig()
: this.config);
this.config.setVisible(true);
}
/**
* Hide this series
*/
public void hide() {
this.config = (this.config == null ? new SeriesConfig()
: this.config);
this.config.setVisible(false);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Series other = (Series) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Series [points=" + points + ", name=" + name + ", type="
+ type + ", stack=" + stack + ", xAxis=" + xAxis
+ ", yAxis=" + yAxis + ", config=" + config + "]";
}
}
/**
* This class defines a number series. In this series both X and Y values
* must be number. To use date values, use {@link DateTimeSeries}
*
* @author Invient
*
* @see DateTimeSeries
*/
public static class XYSeries extends Series {
/**
* Creates a series with given name
*
* @param name
* the name of this series
*/
public XYSeries(String name) {
super(name);
}
/**
* Creates a series with given name and configuration
*
* @param name
* the name of this series
* @param config
* the configuration for this series
*/
public XYSeries(String name, SeriesConfig config) {
super(name, config);
}
/**
* Creates a series with given name and type
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
*/
public XYSeries(String name, SeriesType seriesType) {
super(name, seriesType);
}
/**
* Creates a series with given name, type and configuration
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
* @param config
* the configuration for this series
*/
public XYSeries(String name, SeriesType seriesType, SeriesConfig config) {
super(name, seriesType, config);
}
/**
* Removes the specified point from the series
*
* @param points
*/
public void removePoint(DecimalPoint... points) {
super.removePoint(points);
updatePointXValuesIfNotPresent();
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Series#removeAllPoints()
*/
public void removeAllPoints() {
super.removeAllPoints();
}
/**
* Adds the specified point into the series
*
* @param points
*/
public void addPoint(DecimalPoint... points) {
super.addPoint(points);
updatePointXValuesIfNotPresent();
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Series#getPoints()
*/
public LinkedHashSet<DecimalPoint> getPoints() {
return super.getPoints();
}
/**
* Sets points into this series. This method removes all of its points
* and then add points specified in the method argument. If the argument
* is null then no actions are taken.
*
* @param points
* the collection of points to set into this series.
*/
public void setSeriesPoints(LinkedHashSet<DecimalPoint> points) {
super.setPoints(points);
updatePointXValuesIfNotPresent();
}
/**
*
*/
private void updatePointXValuesIfNotPresent() {
double pointStart = 0;
double pointInterval = 1;
if (super.getConfig() instanceof BaseLineConfig) {
BaseLineConfig config = (BaseLineConfig) super.getConfig();
if (config.getPointStart() != null) {
pointStart = config.getPointStart();
}
if (config.getPointInterval() != null) {
pointInterval = config.getPointInterval();
}
}
int count = 0;
for (DecimalPoint point : getPoints()) {
if ((point.getX() == null || (point.getX() != null && point
.isAutosetX()))) {
point.setAutosetX(true);
if (count == 0) {
point.setX(pointStart);
count++;
} else {
pointStart = pointStart + pointInterval;
point.setX(pointStart);
}
}
}
}
}
/**
* This class defines a datetime series. In this series, the X value must be
* date and Y values must be number. To use number values, use
* {@link XYSeries}
*
* @author Invient
*
* @see XYSeries
*/
public static class DateTimeSeries extends Series {
private boolean includeTime;
/**
* Creates a series with given name
*
* @param name
* the name of this series
*/
public DateTimeSeries(String name) {
super(name);
}
/**
* Creates a series with given name and configuration
*
* @param name
* the name of this series
* @param config
* the configuration for this series
*/
public DateTimeSeries(String name, SeriesConfig config) {
super(name, config);
}
/**
* Creates a series with given name and type
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
*/
public DateTimeSeries(String name, SeriesType seriesType) {
super(name, seriesType);
}
/**
* Creates a series with given name, type and configuration
*
* @param name
* the name of this series
* @param seriesType
* the type of this series
* @param config
* the configuration for this series
*/
public DateTimeSeries(String name, SeriesType seriesType,
SeriesConfig config) {
super(name, seriesType, config);
}
/**
* Removes all points specified as method argument into this series
*
* @param points
*/
public void removePoint(DateTimePoint... points) {
super.removePoint(points);
updatePointXValuesIfNotPresent();
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Series#removeAllPoints()
*/
public void removeAllPoints() {
super.removeAllPoints();
}
/**
* Add all points specified as method argument into this series
*
* @param points
*/
public void addPoint(DateTimePoint... points) {
super.addPoint(points);
updatePointXValuesIfNotPresent();
}
/**
* Returns true if the time in the Y property of DateTimePoint will not be considered when drawing the chart.
* @return
*/
public boolean isIncludeTime() {
return includeTime;
}
/**
* If true then the time in the Y property of DateTimePoint will not be considered when drawing the chart.
* @param includeTime
*/
public void setIncludeTime(boolean includeTime) {
this.includeTime = includeTime;
}
/*
* (non-Javadoc)
*
* @see com.invient.vaadin.chart.InvientChart.Series#getPoints()
*/
public LinkedHashSet<DateTimePoint> getPoints() {
return super.getPoints();
}
/**
* Sets points into this series. This method removes all of its points and then add points specified in
* the method argument. If the argument is null then no actions are taken.
* @param points the collection of points to set into this series.
* @param points
*/
public void setSeriesPoints(LinkedHashSet<DateTimePoint> points) {
super.setPoints(points);
updatePointXValuesIfNotPresent();
}
/**
*
*/
private void updatePointXValuesIfNotPresent() {
double pointStart = (double) getDefPointStart();
double pointInterval = 3600000; // 1 hour
if (super.getConfig() instanceof BaseLineConfig) {
BaseLineConfig config = (BaseLineConfig) super.getConfig();
if (config.getPointStart() != null) {
pointStart = config.getPointStart();
}
if (config.getPointInterval() != null) {
pointInterval = config.getPointInterval();
}
}
Date prevDate = new Date((long) pointStart);
int count = 0;
for (DateTimePoint point : getPoints()) {
if ((point.getX() == null || (point.getX() != null && point
.isAutosetX()))) {
point.setAutosetX(true);
if (count == 0) {
point.setX(prevDate);
count++;
} else {
point.setX(getUpdatedDate(prevDate,
(long) pointInterval));
prevDate = point.getX();
}
}
}
}
private long getDefPointStart() {
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.YEAR, 1970);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTimeInMillis();
}
private Date getUpdatedDate(Date dt, long milliseconds) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dt.getTime() + milliseconds);
return cal.getTime();
}
@Override
public String toString() {
return "DateTimeSeries [includeTime=" + includeTime
+ ", getConfig()=" + getConfig() + ", getName()="
+ getName() + ", getType()=" + getType() + ", getStack()="
+ getStack() + ", getXAxis()=" + getXAxis()
+ ", getYAxis()=" + getYAxis() + "]";
}
}
// *******************************************************************//
// *************** Highcharts Configuration options ******************//
// *******************************************************************//
public static enum SeriesType {
COMMONSERIES("series"), LINE("line"), SPLINE("spline"), SCATTER(
"scatter"), AREA("area"), AREASPLINE("areaspline"), BAR("bar"), COLUMN(
"column"), PIE("pie");
private String type;
private SeriesType(String type) {
this.type = type;
}
public String getName() {
return this.type;
}
}
static class SeriesCUR implements Serializable {
private SeriesCURType type;
private String name;
public SeriesCURType getType() {
return type;
}
public String getName() {
return name;
}
public SeriesCUR(SeriesCURType type, String name) {
super();
this.type = type;
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SeriesCUR other = (SeriesCUR) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
@Override
public String toString() {
return "SeriesCUR [type=" + type + ", name=" + name + "]";
}
static enum SeriesCURType {
ADD("Add"), UPDATE("Update"), REMOVE("Remove");
private String name;
private SeriesCURType(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
}
private LinkedHashSet<SeriesCUR> seriesCURSet = new LinkedHashSet<InvientCharts.SeriesCUR>();
boolean addSeriesCUROperation(SeriesCUR newSeriesCUR) {
if (seriesCURSet.contains(newSeriesCUR)) {
return false;
}
Iterator<SeriesCUR> seriesCURItr = seriesCURSet.iterator();
while (seriesCURItr.hasNext()) {
SeriesCUR seriesCUR = seriesCURItr.next();
if (seriesCUR.getName().equals(newSeriesCUR.getName())) {
if (SeriesCURType.REMOVE.equals(newSeriesCUR.getType())
&& SeriesCURType.ADD.equals(seriesCUR.getType())) {
// Remove addition of a series as there is no reason to add
// a series and
// then remove it. E.g. If a new series is added and then
// removed then
// actually there is nothing to be done
seriesCURItr.remove();
return false;
}
if (SeriesCURType.UPDATE.equals(newSeriesCUR.getType())
&& SeriesCURType.ADD.equals(seriesCUR.getType())) {
// There is no need for update as adding a series will
// take care of applying any update to the series attributes
// specifically visibility
return false;
}
if (SeriesCURType.REMOVE.equals(newSeriesCUR.getType())
&& SeriesCURType.UPDATE.equals(seriesCUR.getType())) {
// Remove update of a series as there is no reason to update
// a series
// and then remove it. E.g. If an existing series was
// updated (for show/hide) and
// then removed then series need not be updated after all it
// is going to be
// removed. Hover, the remove operation must be captured.
seriesCURItr.remove();
break;
}
}
}
seriesCURSet.add(newSeriesCUR);
return true;
}
/**
* After a series is added or removed, there is no need to call this method
* as it is handled implicitly. This method will send updates to the client.
* This method should be called after adding/removing plotbands and
* plotlines. This inconsistency will be fixed in next revision.
*
*/
public void refresh() {
super.requestRepaint();
}
}