From f38b9ce93a161712cc519d4ebece94c7848c31cb Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Wed, 7 Feb 2018 09:57:32 +0100 Subject: [PATCH] JDiagram panning and scrolling (fixes #1) --- src/org/hwo/ui/JDiagram.java | 283 ++++++++++++++++++- src/org/hwo/ui/diagram/DiagramListener.java | 7 + src/org/hwo/ui/diagram/DiagramViewEvent.java | 17 ++ 3 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 src/org/hwo/ui/diagram/DiagramListener.java create mode 100644 src/org/hwo/ui/diagram/DiagramViewEvent.java diff --git a/src/org/hwo/ui/JDiagram.java b/src/org/hwo/ui/JDiagram.java index a7b2148..897eef5 100644 --- a/src/org/hwo/ui/JDiagram.java +++ b/src/org/hwo/ui/JDiagram.java @@ -5,11 +5,24 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Toolkit; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.geom.Point2D; +import java.util.LinkedList; +import javax.swing.BoundedRangeModel; import javax.swing.JComponent; import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.hwo.ui.diagram.DiagramListener; +import org.hwo.ui.diagram.DiagramViewEvent; import org.hwo.ui.diagram.LinePlotPainter; import org.hwo.ui.diagram.LinearScaler; import org.hwo.ui.diagram.PlotLabeler; @@ -20,7 +33,12 @@ import org.hwo.ui.diagram.Scaler; import org.hwo.ui.diagram.SimplePlotLabeler; import org.hwo.ui.diagram.SimplePlotProvider; -public class JDiagram extends JComponent implements PlotProviderListener { +public class JDiagram extends JComponent implements PlotProviderListener, BoundedRangeModel { + + private enum DDragMode { NONE, PAN } + + private LinkedList diagramListeners = new LinkedList<>(); + private LinkedList changeListeners = new LinkedList<>(); private PlotProvider2 plotProvider; @@ -49,7 +67,6 @@ public class JDiagram extends JComponent implements PlotProviderListener { plotWidth; private double abszissMinimum, - abszissMaximum, abszissWindow; @@ -74,7 +91,15 @@ public class JDiagram extends JComponent implements PlotProviderListener { private Integer selectedPlot; - + private DDragMode dragMode; + private Point2D dragPoint; + private Point dragMousePoint; + + private double dragPanStart; + + private double mouseWheelZoom = 1.03; + + public JDiagram(){ setMinimumSize(new Dimension(80, 80)); setDoubleBuffered(true); @@ -93,10 +118,95 @@ public class JDiagram extends JComponent implements PlotProviderListener { drawHorizontalGrid = true; verticalGridColor = new Color(192, 192, 192); + setBackground(Color.black); + setForeground(Color.WHITE); setPlotProvider(new SimplePlotProvider(1, 0)); + + addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + switch (e.getButton()) { + case MouseEvent.BUTTON2: + dragMode = DDragMode.PAN; + dragMousePoint = e.getPoint(); + dragPoint = mapMouseToDiagram(dragMousePoint); + dragPanStart = getAbszissMinimum(); + break; + } + } + + @Override + public void mouseReleased(MouseEvent e) { + dragMode = DDragMode.NONE; + } + }); + + addMouseMotionListener(new MouseAdapter() { + @Override + public void mouseDragged(MouseEvent e) { + Point2D p = mapMouseToDiagram(dragMousePoint); + Point2D np = mapMouseToDiagram(e.getPoint()); + double dx = np.getX() - p.getX(); + + switch (dragMode) { + case PAN: + double nmin = dragPanStart - dx; + + nmin = limitAbszissMinimum(nmin); + + setAbszissMinimum(nmin); + repaint(); + break; + } + } + }); + + addMouseWheelListener(new MouseWheelListener() { + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + + double newwindow = getAbszissWindow() * Math.pow(mouseWheelZoom,e.getPreciseWheelRotation()); + Point2D mp = mapMouseToDiagram(e.getPoint()); + + double pmin = plotProvider.getPositionMinimum(); + double pmax = plotProvider.getPositionMaximum(); + + double maxwindow = pmax - pmin; + + newwindow = newwindow > maxwindow ? maxwindow : newwindow; + + setAbszissWindow(newwindow); + + Point2D mp2 = mapMouseToDiagram(e.getPoint()); + double nmin = getAbszissMinimum() + mp.getX() - mp2.getX(); + + nmin = limitAbszissMinimum(nmin); + setAbszissMinimum( nmin ); + + repaint(); + } + }); + } + private void fireViewWindowChanged(){ + for (DiagramListener l: diagramListeners) { + l.ViewWindowChanged(new DiagramViewEvent(this)); + } + for (ChangeListener l: changeListeners) { + l.stateChanged(new ChangeEvent(this)); + } + } + + public void addDiagramListener(DiagramListener l) { + this.diagramListeners.add(l); + } + public void removeDiagramListener(DiagramListener l) { + this.diagramListeners.remove(l); + } + public void setPlotProvider(PlotProvider2 plotProvider) { if (this.plotProvider != null) this.plotProvider.removePlotProviderListener(this); @@ -415,9 +525,10 @@ public class JDiagram extends JComponent implements PlotProviderListener { nMarker = plotWidth / (w*8/7); } - abszissMinimum = this.plotProvider.getPositionMinimum(); - abszissMaximum = this.plotProvider.getPositionMaximum(); - abszissWindow = abszissMaximum - abszissMinimum; + // TODO change for zoom + //abszissMinimum = this.plotProvider.getPositionMinimum(); + //abszissMaximum = this.plotProvider.getPositionMaximum(); + //abszissWindow = abszissMaximum - abszissMinimum; g.setColor(getForeground()); @@ -464,6 +575,8 @@ public class JDiagram extends JComponent implements PlotProviderListener { Color graphColor; Color[] graphColors = this.plotProvider.getColors(); + double amax = this.getAbszissMaximum(); + for (int graph=0; graph < this.plotProvider.getNumGraphs(); graph++){ boolean isSelected = ((selectedPlot != null) && selectedPlot.equals(graph)); @@ -483,19 +596,110 @@ public class JDiagram extends JComponent implements PlotProviderListener { Float value = this.plotProvider.getValue(n, graph); Float position = this.plotProvider.getPosition(n, graph); - if ((value != null) && (position != null) ) + if ((value != null) && (position != null) && (position >= this.abszissMinimum) && (position <= amax)) { x = getWidth() - bRight - plotWidth + (int)((position - abszissMinimum) * plotWidth / abszissWindow); y = bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(value); this.plotPainters[ graph ].paintPoint(g, graphColor, x, y, isSelected); }; + + } } } + /* + * Pan and Zoom + */ + + public double getAbszissWindow() { + return this.abszissWindow; + } + + public void setAbszissWindow(double width){ + setAbszissWindow(width, true); + } + private void setAbszissWindow(double width,boolean fireEvent){ + this.abszissWindow = width; + if (fireEvent) { + fireViewWindowChanged(); + } + repaint(); + } + + public double getAbszissMinimum() { + return this.abszissMinimum; + } + public void setAbszissMinimum(double x) { + this.abszissMinimum = x; + fireViewWindowChanged(); + repaint(); + } + + public double getAbszissMaximum() { + return this.abszissMinimum + this.abszissWindow; + } + public void setAbszissMaximum(double x) { + this.abszissWindow = x - this.abszissMinimum; + fireViewWindowChanged(); + repaint(); + } + + public double getMouseWheelZoom() { + return mouseWheelZoom; + } + public void setMouseWheelZoom(double mouseWheelZoom) { + this.mouseWheelZoom = mouseWheelZoom; + } + + /* + * Tool methods + */ + + public Point2D mapMouseToDiagram(Point p) { + return this.mapMouseToDiagram(p,0); + } + public Point2D mapMouseToDiagram(Point p,int ordinate) { + double x,y; + + int xl = (getWidth() - bRight - plotWidth); + + + x = this.abszissMinimum + (((p.getX() - xl) / plotWidth) * this.abszissWindow); + // TODO implement reverse mapping into scaler interface ??!! + y = this.ordinateViews[ ordinate ].scaler.getMinValue() - ((p.getY() - bTop - plotHeight) / plotHeight * this.ordinateViews[ ordinate ].scaler.getWindow()); + + return new Point2D.Double(x, y); + } + + public Point mapDiagramToMouse(Point2D p){ + return mapDiagramToMouse(p, 0); + } + public Point mapDiagramToMouse(Point2D p,int ordinate) { + int x,y; + + x = getWidth() - bRight - plotWidth + (int)((p.getX() - abszissMinimum) * plotWidth / abszissWindow); + y = bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(p.getY()); + + return new Point(x, y); + } + + public double limitAbszissMinimum(double nmin) { + double pmin,pmax; + + pmin = plotProvider.getPositionMinimum(); + pmax = plotProvider.getPositionMaximum(); + + nmin = nmin < pmin ? pmin : nmin; + nmin = (nmin + getAbszissWindow()) > pmax ? pmax - getAbszissWindow() : nmin; + + return nmin; + } + + class OrdinateView { @@ -533,4 +737,69 @@ public class JDiagram extends JComponent implements PlotProviderListener { fundamentalsChanged(); } + + @Override + public int getMinimum() { + return (int)(plotProvider.getPositionMinimum() * 1000.0f); + } + + @Override + public void setMinimum(int newMinimum) { + } + + @Override + public int getMaximum() { + return (int)(plotProvider.getPositionMaximum() * 1000.0f); + } + + @Override + public void setMaximum(int newMaximum) { + } + + @Override + public int getValue() { + return (int)(getAbszissMinimum() * 1000.0f); + } + + @Override + public void setValue(int newValue) { + setAbszissMinimum( ((double)newValue / 1000.0f) ); + } + + @Override + public void setValueIsAdjusting(boolean b) { + } + + @Override + public boolean getValueIsAdjusting() { + return false; + } + + @Override + public int getExtent() { + return (int)(getAbszissWindow() * 1000.0f); + } + + @Override + public void setExtent(int newExtent) { + setAbszissWindow( ((double)newExtent / 1000.0f) ); + } + + @Override + public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) { + setMinimum(min); + setMaximum(max); + setExtent(extent); + setValue(value); + } + + @Override + public void addChangeListener(ChangeListener x) { + this.changeListeners.add(x); + } + + @Override + public void removeChangeListener(ChangeListener x) { + this.changeListeners.remove(x); + } } diff --git a/src/org/hwo/ui/diagram/DiagramListener.java b/src/org/hwo/ui/diagram/DiagramListener.java new file mode 100644 index 0000000..5faf310 --- /dev/null +++ b/src/org/hwo/ui/diagram/DiagramListener.java @@ -0,0 +1,7 @@ +package org.hwo.ui.diagram; + +public interface DiagramListener { + + void ViewWindowChanged(DiagramViewEvent e); + +} diff --git a/src/org/hwo/ui/diagram/DiagramViewEvent.java b/src/org/hwo/ui/diagram/DiagramViewEvent.java new file mode 100644 index 0000000..38f9cb5 --- /dev/null +++ b/src/org/hwo/ui/diagram/DiagramViewEvent.java @@ -0,0 +1,17 @@ +package org.hwo.ui.diagram; + +import org.hwo.ui.JDiagram; + +public class DiagramViewEvent { + + private JDiagram diagram; + + public DiagramViewEvent(JDiagram d) { + this.diagram = d; + } + + public JDiagram getDiagram() { + return diagram; + } + +}