package com.ibm.nmon.gui.chart;
import com.ibm.nmon.gui.main.NMONVisualizerGui;
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.util.List;
import java.util.TimeZone;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.plot.Marker;
import org.jfree.chart.renderer.AbstractRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.annotations.Annotation;
import org.jfree.chart.annotations.XYAnnotation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.entity.LegendItemEntity;
import com.ibm.nmon.gui.chart.annotate.LineChartAnnotationDialog;
import com.ibm.nmon.gui.chart.annotate.DomainValueMarker;
import com.ibm.nmon.gui.chart.annotate.RangeValueMarker;
import com.ibm.nmon.gui.chart.builder.LineChartBuilder;
public class LineChartPanel extends BaseChartPanel implements ChartMouseListener {
private static final long serialVersionUID = 7999499157941027546L;
private final BasicStroke SELECTED_STROKE = new BasicStroke(5);
public LineChartPanel(NMONVisualizerGui gui, JFrame parent) {
super(gui, parent);
addChartMouseListener(this);
}
@Override
public void setEnabled(boolean enabled) {
if (isEnabled() != enabled) {
if (enabled) {
gui.addPropertyChangeListener("timeZone", this);
gui.addPropertyChangeListener("chartRelativeTime", this);
setAxisTimeZone(gui.getDisplayTimeZone());
setRelativeAxis(gui.getBooleanProperty("chartRelativeTime"));
}
else {
gui.removePropertyChangeListener("timeZone", this);
gui.removePropertyChangeListener("chartRelativeTime", this);
}
super.setEnabled(enabled);
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("chartRelativeTime".equals(evt.getPropertyName())) {
setRelativeAxis((Boolean) evt.getNewValue());
}
else if ("timeZone".equals(evt.getPropertyName())) {
setAxisTimeZone((TimeZone) evt.getNewValue());
}
else if ("annotation".equals(evt.getPropertyName())) {
// for LineChartAnnotationDialog
firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
}
// note that these methods assume the chart contains an XYPlot rendered by an XYItemRenderer
// these are the expected values for all charts created by LineChartBuilder
public final void highlightElement(int row, int column) {
if (getChart() != null) {
if ((row >= 0) && (row < getChart().getXYPlot().getDataset().getSeriesCount())) {
XYItemRenderer renderer = getChart().getXYPlot().getRenderer();
renderer.setSeriesStroke(row, SELECTED_STROKE);
}
}
}
@Override
public final void clearHighlightedElements() {
if (getChart() != null) {
((AbstractRenderer) getChart().getXYPlot().getRenderer()).clearSeriesStrokes(false);
}
}
@Override
public void setElementVisible(int row, int column, boolean visible) {
if (getChart() != null) {
if ((row >= 0) && (row < getChart().getXYPlot().getDataset().getSeriesCount())) {
getChart().getXYPlot().getRenderer().setSeriesVisible(row, visible);
}
}
}
@Override
public void addAnnotations(List<Annotation> annotations) {
if (getChart() != null) {
XYPlot plot = getChart().getXYPlot();
plot.clearAnnotations();
for (Annotation a : annotations) {
if (a instanceof XYAnnotation) {
XYAnnotation annotation = (XYAnnotation) a;
plot.addAnnotation(annotation);
firePropertyChange("annotation", null, annotation);
}
}
}
}
@Override
public void addMarkers(List<Marker> markers) {
if (getChart() != null) {
XYPlot plot = getChart().getXYPlot();
plot.clearDomainMarkers();
plot.clearRangeMarkers();
for (Marker marker : markers) {
if (marker instanceof RangeValueMarker) {
plot.addRangeMarker(marker);
}
else if (marker instanceof DomainValueMarker) {
plot.addDomainMarker(marker);
}
firePropertyChange("annotation", null, marker);
}
}
}
@Override
protected JPopupMenu createPopupMenu(boolean properties, boolean copy, boolean save, boolean print, boolean zoom) {
JPopupMenu popupMenu = super.createPopupMenu(properties, copy, save, print, zoom);
JMenuItem item = new JMenuItem("Annotate");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LineChartAnnotationDialog dialog = new LineChartAnnotationDialog(LineChartPanel.this, gui, parent,
clickLocation);
dialog.setVisible(true);
}
});
popupMenu.addSeparator();
popupMenu.add(item);
return popupMenu;
}
@Override
public final void chartMouseClicked(ChartMouseEvent event) {
int series = -1;
ChartEntity entity = event.getEntity();
if (entity == null) {
return;
}
// users can click on either the line or the legend
// regardless, figure out the series index
if (entity.getClass() == XYItemEntity.class) {
series = ((XYItemEntity) event.getEntity()).getSeriesIndex();
}
else if (entity.getClass() == LegendItemEntity.class) {
LegendItemEntity legendEntity = (LegendItemEntity) event.getEntity();
XYDataset dataset = (XYDataset) legendEntity.getDataset();
for (int i = 0; i < dataset.getSeriesCount(); i++) {
if (dataset.getSeriesKey(i).equals(legendEntity.getSeriesKey())) {
series = i;
break;
}
}
}
if (series != -1) {
XYItemRenderer renderer = getChart().getXYPlot().getRenderer();
Stroke oldHighlight = renderer.getSeriesStroke(series);
// clear existing highlights
((AbstractRenderer) getChart().getXYPlot().getRenderer()).clearSeriesStrokes(false);
// toggle series stroke
if (oldHighlight != SELECTED_STROKE) {
renderer.setSeriesStroke(series, SELECTED_STROKE);
firePropertyChange("highlightedLine", null, series);
}
else {
renderer.setSeriesStroke(series, null);
firePropertyChange("highlightedLine", series, null);
}
// assume whatever fired the event will repaint the chart
}
}
@Override
public final void chartMouseMoved(ChartMouseEvent event) {}
private void setAxisTimeZone(TimeZone timeZone) {
if (getChart() != null) {
XYPlot plot = getChart().getXYPlot();
if (plot.getDomainAxis() instanceof DateAxis) {
((DateAxis) plot.getDomainAxis()).setTimeZone(timeZone);
if (plot.getRenderer().getBaseToolTipGenerator().getClass() == TimeAndValueTooltipGenerator.class) {
((TimeAndValueTooltipGenerator) plot.getRenderer().getBaseToolTipGenerator()).setTimeZone(timeZone);
}
}
}
}
private void setRelativeAxis(boolean relative) {
if (relative) {
LineChartBuilder.setRelativeAxis(getChart(), gui.getMinSystemTime());
}
else {
LineChartBuilder.setAbsoluteAxis(getChart());
}
}
}