/* * Open-Source tuning tools * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.vgi.mafscaling; import java.awt.Cursor; import java.awt.Insets; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.HashSet; import org.apache.log4j.Logger; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.XYItemEntity; import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; public class MafChartPanel implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener { private static final Logger logger = Logger.getLogger(MafChartPanel.class); private ChartPanel chartPanel = null; private IMafChartHolder chartHolder = null; private XYItemEntity xyItemEntity = null; private HashSet<Integer> pointDraggableSet = null; private boolean AllowPointMove = true; private boolean IsMovable = false; private double initialMovePointY = 0; public MafChartPanel(JFreeChart chart, IMafChartHolder holder) { pointDraggableSet = new HashSet<Integer>(); chartPanel = new ChartPanel(chart, true, true, true, true, true); chartHolder = holder; chartPanel.setFocusable(true); chartPanel.setAutoscrolls(true); chartPanel.setMouseZoomable(false); chartPanel.addMouseMotionListener(this); chartPanel.addMouseListener(this); chartPanel.addMouseWheelListener(this); chartPanel.addKeyListener(this); } public void enablePointsDrag(int seriesIndex) { pointDraggableSet.add(seriesIndex); } public ChartPanel getChartPanel() { return chartPanel; } public void movePoint(MouseEvent event) { try { if (IsMovable) { int itemIndex = xyItemEntity.getItem(); int seriesIndex = xyItemEntity.getSeriesIndex(); if (!pointDraggableSet.contains(seriesIndex)) return; XYSeries series = ((XYSeriesCollection)xyItemEntity.getDataset()).getSeries(seriesIndex); XYPlot plot = chartPanel.getChart().getXYPlot(); Rectangle2D dataArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea(); Point2D p = chartPanel.translateScreenToJava2D(event.getPoint()); double finalMovePointY = plot.getRangeAxis().java2DToValue(p.getY(), dataArea, plot.getRangeAxisEdge()); double difference = finalMovePointY - initialMovePointY; if (series.getY(itemIndex).doubleValue() + difference > plot.getRangeAxis().getRange().getLength() || series.getY(itemIndex).doubleValue() + difference < 0.0) initialMovePointY = finalMovePointY; series.updateByIndex(itemIndex, series.getY(itemIndex).doubleValue() + difference); chartHolder.onMovePoint(itemIndex, series.getX(itemIndex).doubleValue(), series.getY(itemIndex).doubleValue()); chartPanel.getChart().fireChartChanged(); chartPanel.updateUI(); initialMovePointY = finalMovePointY; } } catch (Exception e) { e.printStackTrace(); logger.error(e); } } private void zoomChartAxis(ChartPanel chart, boolean increase) { int width = chart.getMaximumDrawWidth() - chart.getMinimumDrawWidth(); int height = chart.getMaximumDrawHeight() - chart.getMinimumDrawWidth(); if (increase) chart.zoomInBoth(width/2, height/2); else chart.zoomOutBoth(width/2, height/2); } public void mouseWheelMoved(MouseWheelEvent e) { if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) return; if (e.getWheelRotation() < 0) zoomChartAxis(chartPanel, true); else zoomChartAxis(chartPanel, false); } public void mouseDragged(MouseEvent e) { if (AllowPointMove) movePoint(e); } public void mouseExited(MouseEvent e) { IsMovable = false; initialMovePointY = 0; chartPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } public void mousePressed(MouseEvent e) { chartPanel.requestFocusInWindow(); Insets insets = chartPanel.getInsets(); int x = (int) ((e.getX() - insets.left) / chartPanel.getScaleX()); int y = (int) ((e.getY() - insets.top) / chartPanel.getScaleY()); ChartEntity entity = chartPanel.getChartRenderingInfo().getEntityCollection().getEntity(x, y); if (entity == null || !(entity instanceof XYItemEntity)) return; IsMovable = true; chartPanel.setCursor(new Cursor(Cursor.HAND_CURSOR)); xyItemEntity = (XYItemEntity)entity; XYPlot plot = chartPanel.getChart().getXYPlot(); Rectangle2D dataArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea(); Point2D p = chartPanel.translateScreenToJava2D(e.getPoint()); initialMovePointY = plot.getRangeAxis().java2DToValue(p.getY(), dataArea, plot.getRangeAxisEdge()); } public void mouseReleased(MouseEvent arg0) { IsMovable = false; initialMovePointY = 0; chartPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } public void mouseClicked(MouseEvent arg0) { } public void mouseEntered(MouseEvent arg0) { } public void mouseMoved(MouseEvent arg0) { } @Override public void keyPressed(KeyEvent e) { if (!chartPanel.hasFocus()) return; int keyCode = e.getKeyCode(); if (keyCode < KeyEvent.VK_LEFT || keyCode > KeyEvent.VK_DOWN) return; ValueAxis axis = null; if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) axis = ((XYPlot)chartPanel.getChart().getXYPlot()).getDomainAxis(); else axis = ((XYPlot)chartPanel.getChart().getXYPlot()).getRangeAxis(); if (axis != null) { double delta = (axis.getUpperBound()- axis.getLowerBound()) / 100.0; if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_DOWN) axis.setRange(axis.getLowerBound()- delta, axis.getUpperBound() - delta); else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_RIGHT) axis.setRange(axis.getLowerBound() + delta, axis.getUpperBound() + delta); } } @Override public void keyReleased(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { } }