/* PlotScrollingCoordinator.java created 2007-11-08
*
*/
package org.signalml.app.view.signal;
import java.awt.Dimension;
import java.awt.Point;
import java.util.HashMap;
import java.util.LinkedList;
import javax.swing.JViewport;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/** PlotScrollingCoordinator
*
*
* @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o.
*/
public class PlotScrollingCoordinator implements ChangeListener {
private SignalPlot masterPlot;
private LinkedList<SignalPlot> plots;
private HashMap<JViewport,SignalPlot> plotsByViewports;
private boolean lock = false;
public PlotScrollingCoordinator(SignalPlot masterPlot) {
this.masterPlot = masterPlot;
masterPlot.getViewport().addChangeListener(this);
plots = new LinkedList<SignalPlot>();
plotsByViewports = new HashMap<JViewport, SignalPlot>();
}
public void addPlot(SignalPlot plot) {
JViewport viewport = plot.getViewport();
viewport.addChangeListener(this);
plotsByViewports.put(viewport, plot);
plots.add(plot);
}
public void removePlot(SignalPlot plot) {
JViewport viewport = plot.getViewport();
viewport.removeChangeListener(this);
plotsByViewports.remove(viewport);
plots.remove(plot);
}
@Override
public void stateChanged(ChangeEvent e) {
if (lock) {
return;
}
try {
lock = true;
JViewport viewport = (JViewport) e.getSource();
SignalPlot plot;
boolean masterChanged = false;
if (viewport != masterPlot.getViewport()) {
plot = plotsByViewports.get(viewport);
if (plot == null) {
throw new NullPointerException("Plot not in the map");
}
masterChanged = synchronizeMaster(plot);
} else {
plot = masterPlot;
masterChanged = true;
}
if (masterChanged) {
synchronizeToMaster(viewport);
}
plot.updateSignalPlotSynchronizationLabel();
} finally {
lock = false;
}
}
private void synchronizeToMaster(JViewport originator) {
Point masterPosition = masterPlot.getViewport().getViewPosition();
Point slavePosition;
Dimension slaveSize;
Dimension slaveViewportSize;
JViewport viewport;
for (SignalPlot plot : plots) {
viewport = plot.getViewport();
if (viewport == originator) {
continue;
}
if (plot.getMasterPlot() == masterPlot) {
if (plot.isHorizontalLock() || plot.isVerticalLock()) {
slavePosition = viewport.getViewPosition();
slaveViewportSize = viewport.getExtentSize();
slaveSize = plot.getSize();
if (plot.isHorizontalLock()) {
slavePosition.x = masterPosition.x + plot.getHorizontalPixelLead();
slavePosition.x = Math.max(0, Math.min(slaveSize.width-slaveViewportSize.width, slavePosition.x));
}
if (plot.isVerticalLock()) {
slavePosition.y = masterPosition.y + plot.getVerticalPixelLead();
slavePosition.y = Math.max(0, Math.min(slaveSize.height-slaveViewportSize.height, slavePosition.y));
}
viewport.setViewPosition(slavePosition);
}
plot.updateSignalPlotSynchronizationLabel();
}
}
}
private boolean synchronizeMaster(SignalPlot plot) {
boolean changed = false;
if (plot.isHorizontalLock() || plot.isVerticalLock()) {
Point slavePosition = plot.getViewport().getViewPosition();
JViewport viewport = masterPlot.getViewport();
Point masterPosition = viewport.getViewPosition();;
Dimension masterSize = masterPlot.getSize();
Dimension masterViewportSize = viewport.getExtentSize();
int oldPosition;
if (plot.isHorizontalLock()) {
oldPosition = masterPosition.x;
masterPosition.x = slavePosition.x - plot.getHorizontalPixelLead();
masterPosition.x = Math.max(0, Math.min(masterSize.width-masterViewportSize.width, masterPosition.x));
if (masterPosition.x != oldPosition) {
changed = true;
}
}
if (plot.isVerticalLock()) {
oldPosition = masterPosition.y - plot.getVerticalPixelLead();
masterPosition.y = slavePosition.y;
masterPosition.y = Math.max(0, Math.min(masterSize.height-masterViewportSize.height, masterPosition.y));
if (masterPosition.y != oldPosition) {
changed = true;
}
}
if (changed) {
viewport.setViewPosition(masterPosition);
}
}
return changed;
}
}