JDiagram panning and scrolling (fixes #1)

JDiaAutoScaleFix
Harald Wolff 2018-02-07 09:57:32 +01:00
parent 1753db1ef9
commit f38b9ce93a
3 changed files with 300 additions and 7 deletions

View File

@ -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<DiagramListener> diagramListeners = new LinkedList<>();
private LinkedList<ChangeListener> 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);
}
}

View File

@ -0,0 +1,7 @@
package org.hwo.ui.diagram;
public interface DiagramListener {
void ViewWindowChanged(DiagramViewEvent e);
}

View File

@ -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;
}
}