package com.ibm.nmon.gui.chart; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import org.jfree.chart.ChartMouseListener; import org.jfree.chart.ChartMouseEvent; import org.jfree.chart.annotations.Annotation; import org.jfree.chart.annotations.CategoryTextAnnotation; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.CategoryItemEntity; import org.jfree.chart.plot.CategoryPlot; import com.ibm.nmon.gui.Styles; import com.ibm.nmon.gui.chart.data.DataTupleCategoryDataset; import com.ibm.nmon.gui.main.NMONVisualizerGui; public final class BarChartPanel extends BaseChartPanel implements ChartMouseListener { private static final long serialVersionUID = -5854445408091165201L; private final JMenuItem annotateBar; private boolean canAnnotate = false; public BarChartPanel(NMONVisualizerGui gui, JFrame parent) { super(gui, parent); addChartMouseListener(this); annotateBar = new JMenuItem("Annotate Bar"); annotateBar.addActionListener(new AnnotateBarAction()); } @Override public void highlightElement(int row, int column) { if ((getChart() != null) && (getChart().getClass() == HighlightableBarChart.class)) { boolean highlightWholeBar = ((DataTupleCategoryDataset) getChart().getCategoryPlot().getDataset()) .categoriesHaveDifferentStats(); // find the CategoryItemEntity that matches the given row and column // assume there are not that many entities in the chart and this will be relatively fast @SuppressWarnings("rawtypes") java.util.Iterator i = getChartRenderingInfo().getEntityCollection().iterator(); while (i.hasNext()) { ChartEntity entity = (ChartEntity) i.next(); if (entity.getClass() == CategoryItemEntity.class) { CategoryItemEntity categoryEntity = (CategoryItemEntity) entity; int currentRow = categoryEntity.getDataset().getRowIndex(categoryEntity.getRowKey()); int currentColumn = categoryEntity.getDataset().getColumnIndex(categoryEntity.getColumnKey()); if (highlightWholeBar) { // match all categories if (currentColumn == column) { ((HighlightableBarChart) getChart()).highlightEntity(categoryEntity); } } else { // match only a single category if ((currentRow == row) && (currentColumn == column)) { ((HighlightableBarChart) getChart()).highlightEntity(categoryEntity); break; } } } } } } @Override public void clearHighlightedElements() { if ((getChart() != null) && (getChart().getClass() == HighlightableBarChart.class)) { ((HighlightableBarChart) getChart()).clearHighlights(); // force a repaint of the double buffered chart setRefreshBuffer(true); repaint(); } } @Override public void clearChart() { super.clearChart(); if (getChart() != null) { removeAnnotationMenu(); } } @Override public void addAnnotations(List<Annotation> annotations) { if (getChart() != null) { CategoryPlot plot = getChart().getCategoryPlot(); plot.clearAnnotations(); for (Annotation a : annotations) { if (a instanceof CategoryTextAnnotation) { CategoryTextAnnotation annotation = (CategoryTextAnnotation) a; if (plot.getCategories().contains(annotation.getCategory())) { plot.addAnnotation(annotation); firePropertyChange("annotation", null, annotation); } } } } } @Override protected void displayPopupMenu(int x, int y) { // only show annotation menu if the mouse if over an actual bar // find the CategoryItemEntity that matches the given x, y // assume there are not that many entities in the chart and this will be relatively // fast @SuppressWarnings("rawtypes") java.util.Iterator i = getChartRenderingInfo().getEntityCollection().iterator(); boolean valid = false; while (i.hasNext()) { ChartEntity entity = (ChartEntity) i.next(); if (entity.getClass() == CategoryItemEntity.class) { CategoryItemEntity categoryEntity = (CategoryItemEntity) entity; if (categoryEntity.getArea().contains(x, y)) { ((AnnotateBarAction) annotateBar.getActionListeners()[0]).categoryKey = (String) categoryEntity .getColumnKey(); valid = true; break; } } } if (valid) { if (!canAnnotate) { getPopupMenu().addSeparator(); getPopupMenu().add(annotateBar); canAnnotate = true; } // else menu already present } else { removeAnnotationMenu(); } super.displayPopupMenu(x, y); } protected final void removeAnnotationMenu() { if (!canAnnotate) { boolean removed = false; for (java.awt.Component c : getPopupMenu().getComponents()) { if (c == annotateBar) { getPopupMenu().remove(annotateBar); removed = true; break; } } if (removed) { // remove separator getPopupMenu().remove(getPopupMenu().getComponentCount() - 1); } } canAnnotate = false; } @Override public void chartMouseClicked(ChartMouseEvent event) { if (event.getEntity().getClass() == CategoryItemEntity.class) { if ((getChart() != null) && (getChart().getClass() == HighlightableBarChart.class)) { HighlightableBarChart chart = (HighlightableBarChart) getChart(); CategoryItemEntity entity = (CategoryItemEntity) event.getEntity(); // toggle highlight if already selected if (chart.isHighlighted(entity)) { chart.clearHighlights(); firePropertyChange("highlightedBar", getRowAndColumn(entity), null); } else { chart.clearHighlights(); chart.highlightEntity(entity); firePropertyChange("highlightedBar", null, getRowAndColumn(entity)); } // assume whatever fired the event will repaint the chart } } } @Override public void chartMouseMoved(ChartMouseEvent event) {} private int[] getRowAndColumn(CategoryItemEntity entity) { int[] toReturn = new int[2]; toReturn[0] = entity.getDataset().getRowIndex(entity.getRowKey()); toReturn[1] = entity.getDataset().getColumnIndex(entity.getColumnKey()); return toReturn; } private final class AnnotateBarAction implements ActionListener { String categoryKey = null; @Override public void actionPerformed(ActionEvent e) { if (categoryKey == null) { return; } String text = JOptionPane.showInputDialog(gui.getMainFrame(), "Annotation Text", "Annotate Bar Chart", JOptionPane.QUESTION_MESSAGE); if (text != null) { text = text.trim(); if ("".equals(text)) { return; } CategoryPlot categoryPlot = getChart().getCategoryPlot(); double y = categoryPlot.getRangeAxis().java2DToValue(clickLocation.getY(), getChartRenderingInfo().getPlotInfo().getDataArea(), categoryPlot.getRangeAxisEdge()); if (y < categoryPlot.getRangeAxis().getLowerBound()) { y = categoryPlot.getRangeAxis().getLowerBound(); } if (y > categoryPlot.getRangeAxis().getUpperBound()) { y = categoryPlot.getRangeAxis().getUpperBound(); } CategoryTextAnnotation annotation = new CategoryTextAnnotation(text, categoryKey, y); annotation.setFont(Styles.ANNOTATION_FONT); annotation.setPaint(Styles.ANNOTATION_COLOR); getChart().getCategoryPlot().addAnnotation(annotation); firePropertyChange("annotation", null, annotation); } } } }