improved zoom
This commit is contained in:
parent
5dd5b5ac43
commit
c7ef068f33
1 changed files with 175 additions and 103 deletions
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: TimeLine.java,v 1.24 2010/03/02 13:33:10 fros4943 Exp $
|
* $Id: TimeLine.java,v 1.25 2010/04/26 08:00:19 fros4943 Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.sics.cooja.plugins;
|
package se.sics.cooja.plugins;
|
||||||
|
@ -35,6 +35,7 @@ import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
@ -102,7 +103,7 @@ import se.sics.cooja.interfaces.Radio.RadioEvent;
|
||||||
@ClassDescription("Timeline")
|
@ClassDescription("Timeline")
|
||||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||||
public class TimeLine extends VisPlugin {
|
public class TimeLine extends VisPlugin {
|
||||||
|
private static final long serialVersionUID = -883154261246961973L;
|
||||||
public static final int LED_PIXEL_HEIGHT = 2;
|
public static final int LED_PIXEL_HEIGHT = 2;
|
||||||
public static final int EVENT_PIXEL_HEIGHT = 4;
|
public static final int EVENT_PIXEL_HEIGHT = 4;
|
||||||
public static final int TIME_MARKER_PIXEL_HEIGHT = 6;
|
public static final int TIME_MARKER_PIXEL_HEIGHT = 6;
|
||||||
|
@ -112,11 +113,11 @@ public class TimeLine extends VisPlugin {
|
||||||
private static final boolean PAINT_ZERO_WIDTH_EVENTS = true;
|
private static final boolean PAINT_ZERO_WIDTH_EVENTS = true;
|
||||||
private static final int TIMELINE_UPDATE_INTERVAL = 100;
|
private static final int TIMELINE_UPDATE_INTERVAL = 100;
|
||||||
|
|
||||||
private static long currentPixelDivisor = 200;
|
private double currentPixelDivisor = 200;
|
||||||
|
|
||||||
private static final long[] ZOOM_LEVELS = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000 };
|
private static final long[] ZOOM_LEVELS = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000 };
|
||||||
|
|
||||||
private int zoomLevel = 9;
|
private boolean needZoomOut = false;
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(TimeLine.class);
|
private static Logger logger = Logger.getLogger(TimeLine.class);
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@ public class TimeLine extends VisPlugin {
|
||||||
super("Timeline (Add motes to observe by clicking +)", gui);
|
super("Timeline (Add motes to observe by clicking +)", gui);
|
||||||
this.simulation = simulation;
|
this.simulation = simulation;
|
||||||
|
|
||||||
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
currentPixelDivisor = ZOOM_LEVELS[ZOOM_LEVELS.length/2];
|
||||||
|
|
||||||
/* Box: events to observe */
|
/* Box: events to observe */
|
||||||
eventCheckboxes = Box.createVerticalBox();
|
eventCheckboxes = Box.createVerticalBox();
|
||||||
|
@ -283,6 +284,7 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action removeMoteAction = new AbstractAction() {
|
private Action removeMoteAction = new AbstractAction() {
|
||||||
|
private static final long serialVersionUID = 2924285037480429045L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JComponent b = (JComponent) e.getSource();
|
JComponent b = (JComponent) e.getSource();
|
||||||
Mote m = (Mote) b.getClientProperty("mote");
|
Mote m = (Mote) b.getClientProperty("mote");
|
||||||
|
@ -290,6 +292,7 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private Action addMoteAction = new AbstractAction("Add motes to timeline") {
|
private Action addMoteAction = new AbstractAction("Add motes to timeline") {
|
||||||
|
private static final long serialVersionUID = 7546685285707302865L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
JComboBox source = new JComboBox();
|
JComboBox source = new JComboBox();
|
||||||
|
@ -323,48 +326,40 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Action zoomInAction = new AbstractAction("Zoom in (Ctrl+)") {
|
private void forceRepaintAndFocus(final long focusTime, final double focusCenter) {
|
||||||
public void actionPerformed(ActionEvent e) {
|
forceRepaintAndFocus(focusTime, focusCenter, true);
|
||||||
Rectangle r = timeline.getVisibleRect();
|
|
||||||
int pixelX = r.x + r.width/2;
|
|
||||||
if (popupLocation != null) {
|
|
||||||
pixelX = popupLocation.x;
|
|
||||||
popupLocation = null;
|
|
||||||
}
|
}
|
||||||
if (mousePixelPositionX > 0) {
|
|
||||||
pixelX = mousePixelPositionX;
|
|
||||||
}
|
|
||||||
final long centerTime = pixelX*currentPixelDivisor;
|
|
||||||
|
|
||||||
if (zoomLevel > 0) {
|
|
||||||
zoomLevel--;
|
|
||||||
}
|
|
||||||
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
|
||||||
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==0)?"(MIN)":""));
|
|
||||||
|
|
||||||
|
private void forceRepaintAndFocus(final long focusTime, final double focusCenter, final boolean mark) {
|
||||||
lastRepaintSimulationTime = -1; /* Force repaint */
|
lastRepaintSimulationTime = -1; /* Force repaint */
|
||||||
repaintTimelineTimer.getActionListeners()[0].actionPerformed(null); /* Force size update*/
|
repaintTimelineTimer.getActionListeners()[0].actionPerformed(null); /* Force size update*/
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
int w = timeline.getVisibleRect().width;
|
int w = timeline.getVisibleRect().width;
|
||||||
|
|
||||||
int centerPixel = (int)(centerTime/currentPixelDivisor);
|
/* centerPixel-leftPixel <=> focusCenter*w; */
|
||||||
|
int centerPixel = (int) (focusTime/currentPixelDivisor);
|
||||||
|
int leftPixel = (int) (focusTime/currentPixelDivisor - focusCenter*w);
|
||||||
|
|
||||||
Rectangle r = new Rectangle(
|
Rectangle r = new Rectangle(
|
||||||
centerPixel - w/2, 0,
|
leftPixel, 0,
|
||||||
w, 1
|
w, 1
|
||||||
);
|
);
|
||||||
|
|
||||||
timeline.scrollRectToVisible(r);
|
timeline.scrollRectToVisible(r);
|
||||||
|
|
||||||
/* Time ruler */
|
/* Time ruler */
|
||||||
|
if (mark) {
|
||||||
mousePixelPositionX = centerPixel;
|
mousePixelPositionX = centerPixel;
|
||||||
mouseDownPixelPositionX = centerPixel;
|
mouseDownPixelPositionX = centerPixel;
|
||||||
mousePixelPositionY = timeline.getHeight();
|
mousePixelPositionY = timeline.getHeight();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
private Action zoomOutAction = new AbstractAction("Zoom out (Ctrl-)") {
|
private Action zoomInAction = new AbstractAction("Zoom in (Ctrl+)") {
|
||||||
|
private static final long serialVersionUID = -2592452356547803615L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Rectangle r = timeline.getVisibleRect();
|
Rectangle r = timeline.getVisibleRect();
|
||||||
int pixelX = r.x + r.width/2;
|
int pixelX = r.x + r.width/2;
|
||||||
|
@ -372,74 +367,81 @@ public class TimeLine extends VisPlugin {
|
||||||
pixelX = popupLocation.x;
|
pixelX = popupLocation.x;
|
||||||
popupLocation = null;
|
popupLocation = null;
|
||||||
}
|
}
|
||||||
final long centerTime = pixelX*currentPixelDivisor;
|
if (mousePixelPositionX > 0) {
|
||||||
|
pixelX = mousePixelPositionX;
|
||||||
|
}
|
||||||
|
final long centerTime = (long) (pixelX*currentPixelDivisor);
|
||||||
|
|
||||||
|
int zoomLevel = 0;
|
||||||
|
while (zoomLevel < ZOOM_LEVELS.length) {
|
||||||
|
if (currentPixelDivisor <= ZOOM_LEVELS[zoomLevel]) break;
|
||||||
|
zoomLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoomLevel > 0) {
|
||||||
|
zoomLevel--; /* zoom in */
|
||||||
|
}
|
||||||
|
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
||||||
|
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==0)?"(MIN)":""));
|
||||||
|
|
||||||
|
forceRepaintAndFocus(centerTime, 0.5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private Action zoomOutAction = new AbstractAction("Zoom out (Ctrl-)") {
|
||||||
|
private static final long serialVersionUID = 6837091379835151725L;
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Rectangle r = timeline.getVisibleRect();
|
||||||
|
int pixelX = r.x + r.width/2;
|
||||||
|
if (popupLocation != null) {
|
||||||
|
pixelX = popupLocation.x;
|
||||||
|
popupLocation = null;
|
||||||
|
}
|
||||||
|
final long centerTime = (long) (pixelX*currentPixelDivisor);
|
||||||
if (mousePixelPositionX > 0) {
|
if (mousePixelPositionX > 0) {
|
||||||
pixelX = mousePixelPositionX;
|
pixelX = mousePixelPositionX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zoomLevel < ZOOM_LEVELS.length-1) {
|
int zoomLevel = 0;
|
||||||
|
while (zoomLevel < ZOOM_LEVELS.length) {
|
||||||
|
if (currentPixelDivisor <= ZOOM_LEVELS[zoomLevel]) break;
|
||||||
zoomLevel++;
|
zoomLevel++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zoomLevel < ZOOM_LEVELS.length-1) {
|
||||||
|
zoomLevel++; /* zoom out */
|
||||||
|
}
|
||||||
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
||||||
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==ZOOM_LEVELS.length-1)?"(MAX)":""));
|
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==ZOOM_LEVELS.length-1)?"(MAX)":""));
|
||||||
|
|
||||||
lastRepaintSimulationTime = -1; /* Force repaint */
|
forceRepaintAndFocus(centerTime, 0.5);
|
||||||
repaintTimelineTimer.getActionListeners()[0].actionPerformed(null); /* Force size update */
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
int w = timeline.getVisibleRect().width;
|
|
||||||
int centerPixel = (int)(centerTime/currentPixelDivisor);
|
|
||||||
Rectangle r = new Rectangle(
|
|
||||||
centerPixel - w/2, 0,
|
|
||||||
w, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Time ruler */
|
|
||||||
mousePixelPositionX = centerPixel;
|
|
||||||
mouseDownPixelPositionX = centerPixel;
|
|
||||||
mousePixelPositionY = timeline.getHeight();
|
|
||||||
|
|
||||||
timeline.scrollRectToVisible(r);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Action zoomSliderAction = new AbstractAction("Zoom slider") {
|
private Action zoomSliderAction = new AbstractAction("Zoom slider (Ctrl+Mouse)") {
|
||||||
|
private static final long serialVersionUID = -4288046377707363837L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
int zoomLevel = 0;
|
||||||
|
while (zoomLevel < ZOOM_LEVELS.length) {
|
||||||
|
if (currentPixelDivisor <= ZOOM_LEVELS[zoomLevel]) break;
|
||||||
|
zoomLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
final JSlider zoomSlider = new JSlider(JSlider.VERTICAL, 0, ZOOM_LEVELS.length-1, zoomLevel);
|
final JSlider zoomSlider = new JSlider(JSlider.VERTICAL, 0, ZOOM_LEVELS.length-1, zoomLevel);
|
||||||
zoomSlider.setInverted(true);
|
zoomSlider.setInverted(true);
|
||||||
zoomSlider.setPaintTicks(true);
|
zoomSlider.setPaintTicks(true);
|
||||||
zoomSlider.setPaintLabels(false);
|
zoomSlider.setPaintLabels(false);
|
||||||
|
|
||||||
final long centerTime = popupLocation.x*currentPixelDivisor;
|
final long centerTime = (long) (popupLocation.x*currentPixelDivisor);
|
||||||
|
|
||||||
zoomSlider.addChangeListener(new ChangeListener() {
|
zoomSlider.addChangeListener(new ChangeListener() {
|
||||||
public void stateChanged(ChangeEvent e) {
|
public void stateChanged(ChangeEvent e) {
|
||||||
zoomLevel = zoomSlider.getValue();
|
int zoomLevel = zoomSlider.getValue();
|
||||||
|
|
||||||
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
|
||||||
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==ZOOM_LEVELS.length-1)?"(MAX)":""));
|
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==ZOOM_LEVELS.length-1)?"(MAX)":""));
|
||||||
|
|
||||||
lastRepaintSimulationTime = -1; /* Force repaint */
|
forceRepaintAndFocus(centerTime, 0.5);
|
||||||
repaintTimelineTimer.getActionListeners()[0].actionPerformed(null); /* Force size update */
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
int w = timeline.getVisibleRect().width;
|
|
||||||
int centerPixel = (int)(centerTime/currentPixelDivisor);
|
|
||||||
Rectangle r = new Rectangle(
|
|
||||||
centerPixel - w/2, 0,
|
|
||||||
w, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Time ruler */
|
|
||||||
mousePixelPositionX = centerPixel;
|
|
||||||
mouseDownPixelPositionX = centerPixel;
|
|
||||||
mousePixelPositionY = timeline.getHeight();
|
|
||||||
|
|
||||||
timeline.scrollRectToVisible(r);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -454,6 +456,7 @@ public class TimeLine extends VisPlugin {
|
||||||
* Save logged raw data to file for post-processing.
|
* Save logged raw data to file for post-processing.
|
||||||
*/
|
*/
|
||||||
private Action saveDataAction = new AbstractAction("Save raw data to file") {
|
private Action saveDataAction = new AbstractAction("Save raw data to file") {
|
||||||
|
private static final long serialVersionUID = 975176793514425718L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
int returnVal = fc.showSaveDialog(GUI.getTopParentContainer());
|
int returnVal = fc.showSaveDialog(GUI.getTopParentContainer());
|
||||||
|
@ -552,6 +555,7 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Action statisticsAction = new AbstractAction("Print statistics to console") {
|
private Action statisticsAction = new AbstractAction("Print statistics to console") {
|
||||||
|
private static final long serialVersionUID = 8671605486913497397L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (simulation.isRunning()) {
|
if (simulation.isRunning()) {
|
||||||
simulation.stopSimulation();
|
simulation.stopSimulation();
|
||||||
|
@ -697,29 +701,29 @@ public class TimeLine extends VisPlugin {
|
||||||
return output.toString();
|
return output.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trySelectTime(final long time) {
|
public void trySelectTime(final long toTime) {
|
||||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
/* Visible rectangle */
|
/* Mark selected time in time ruler */
|
||||||
int newX = (int) (time / currentPixelDivisor);
|
final int toPixel = (int) (toTime / currentPixelDivisor);
|
||||||
int w = timeline.getVisibleRect().width;
|
mousePixelPositionX = toPixel;
|
||||||
w = 50;
|
mouseDownPixelPositionX = toPixel;
|
||||||
Rectangle r = new Rectangle(
|
|
||||||
newX - w/2, 0,
|
|
||||||
w, 1
|
|
||||||
);
|
|
||||||
timeline.scrollRectToVisible(r);
|
|
||||||
|
|
||||||
/* Time ruler */
|
|
||||||
mousePixelPositionX = newX;
|
|
||||||
mouseDownPixelPositionX = newX;
|
|
||||||
mousePixelPositionY = timeline.getHeight();
|
mousePixelPositionY = timeline.getHeight();
|
||||||
|
|
||||||
|
/* Check if time is already visible */
|
||||||
|
Rectangle vis = timeline.getVisibleRect();
|
||||||
|
if (toPixel >= vis.x && toPixel < vis.x + vis.width) {
|
||||||
repaint();
|
repaint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceRepaintAndFocus(toTime, 0.5, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action radioLoggerAction = new AbstractAction("to Radio Logger") {
|
private Action radioLoggerAction = new AbstractAction("to Radio Logger") {
|
||||||
|
private static final long serialVersionUID = 7690116136861949864L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
RadioLogger plugin = (RadioLogger) simulation.getGUI().getStartedPlugin(RadioLogger.class.getName());
|
RadioLogger plugin = (RadioLogger) simulation.getGUI().getStartedPlugin(RadioLogger.class.getName());
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
|
@ -731,10 +735,11 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select simulation time */
|
/* Select simulation time */
|
||||||
plugin.trySelectTime(popupLocation.x*currentPixelDivisor);
|
plugin.trySelectTime((long) (popupLocation.x*currentPixelDivisor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private Action logListenerAction = new AbstractAction("to Log Listener") {
|
private Action logListenerAction = new AbstractAction("to Log Listener") {
|
||||||
|
private static final long serialVersionUID = -8626118368774023257L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
LogListener plugin = (LogListener) simulation.getGUI().getStartedPlugin(LogListener.class.getName());
|
LogListener plugin = (LogListener) simulation.getGUI().getStartedPlugin(LogListener.class.getName());
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
|
@ -746,7 +751,7 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select simulation time */
|
/* Select simulation time */
|
||||||
plugin.trySelectTime(popupLocation.x*currentPixelDivisor);
|
plugin.trySelectTime((long) (popupLocation.x*currentPixelDivisor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1049,8 +1054,8 @@ public class TimeLine extends VisPlugin {
|
||||||
element.addContent("" + splitPane.getDividerLocation());
|
element.addContent("" + splitPane.getDividerLocation());
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
element = new Element("zoom");
|
element = new Element("zoomfactor");
|
||||||
element.addContent("" + zoomLevel);
|
element.addContent("" + currentPixelDivisor);
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
@ -1090,8 +1095,11 @@ public class TimeLine extends VisPlugin {
|
||||||
} else if ("split".equals(name)) {
|
} else if ("split".equals(name)) {
|
||||||
splitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
splitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
||||||
} else if ("zoom".equals(name)) {
|
} else if ("zoom".equals(name)) {
|
||||||
zoomLevel = Integer.parseInt(element.getText())-1;
|
currentPixelDivisor = ZOOM_LEVELS[Integer.parseInt(element.getText())-1];
|
||||||
zoomOutAction.actionPerformed(null);
|
forceRepaintAndFocus(0, 0);
|
||||||
|
} else if ("zoomfactor".equals(name)) {
|
||||||
|
currentPixelDivisor = Double.parseDouble(element.getText());
|
||||||
|
forceRepaintAndFocus(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,7 +1128,7 @@ public class TimeLine extends VisPlugin {
|
||||||
private int mousePixelPositionY = -1;
|
private int mousePixelPositionY = -1;
|
||||||
private int mouseDownPixelPositionX = -1;
|
private int mouseDownPixelPositionX = -1;
|
||||||
class Timeline extends JComponent {
|
class Timeline extends JComponent {
|
||||||
|
private static final long serialVersionUID = 2206491823778169359L;
|
||||||
public Timeline() {
|
public Timeline() {
|
||||||
setLayout(null);
|
setLayout(null);
|
||||||
setToolTipText(null);
|
setToolTipText(null);
|
||||||
|
@ -1174,8 +1182,32 @@ public class TimeLine extends VisPlugin {
|
||||||
|
|
||||||
private MouseAdapter mouseAdapter = new MouseAdapter() {
|
private MouseAdapter mouseAdapter = new MouseAdapter() {
|
||||||
private Popup popUpToolTip = null;
|
private Popup popUpToolTip = null;
|
||||||
|
private double zoomInitialPixelDivisor;
|
||||||
|
private int zoomInitialMouseY;
|
||||||
|
private long zoomCenterTime = -1;
|
||||||
|
private double zoomCenter = -1;
|
||||||
public void mouseDragged(MouseEvent e) {
|
public void mouseDragged(MouseEvent e) {
|
||||||
super.mouseDragged(e);
|
super.mouseDragged(e);
|
||||||
|
if (e.isControlDown()) {
|
||||||
|
/* Zoom with mouse */
|
||||||
|
if (zoomCenterTime < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double factor = 0.01*(e.getY() - zoomInitialMouseY);
|
||||||
|
factor = Math.exp(factor);
|
||||||
|
|
||||||
|
currentPixelDivisor = zoomInitialPixelDivisor * factor;
|
||||||
|
if (currentPixelDivisor < ZOOM_LEVELS[0]) {
|
||||||
|
currentPixelDivisor = ZOOM_LEVELS[0];
|
||||||
|
}
|
||||||
|
if (currentPixelDivisor > ZOOM_LEVELS[ZOOM_LEVELS.length-1]) {
|
||||||
|
currentPixelDivisor = ZOOM_LEVELS[ZOOM_LEVELS.length-1];
|
||||||
|
}
|
||||||
|
forceRepaintAndFocus(zoomCenterTime, zoomCenter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mousePixelPositionX >= 0) {
|
if (mousePixelPositionX >= 0) {
|
||||||
mousePixelPositionX = e.getX();
|
mousePixelPositionX = e.getX();
|
||||||
mousePixelPositionY = e.getY();
|
mousePixelPositionY = e.getY();
|
||||||
|
@ -1183,6 +1215,15 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
|
if (e.isControlDown()) {
|
||||||
|
/* Zoom with mouse */
|
||||||
|
zoomInitialMouseY = e.getY();
|
||||||
|
zoomInitialPixelDivisor = currentPixelDivisor;
|
||||||
|
zoomCenterTime = (long) (e.getX()*currentPixelDivisor);
|
||||||
|
zoomCenter = (double) (e.getX() - timeline.getVisibleRect().x) / timeline.getVisibleRect().width;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (popUpToolTip != null) {
|
if (popUpToolTip != null) {
|
||||||
popUpToolTip.hide();
|
popUpToolTip.hide();
|
||||||
popUpToolTip = null;
|
popUpToolTip = null;
|
||||||
|
@ -1204,6 +1245,7 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
zoomCenterTime = -1;
|
||||||
if (popUpToolTip != null) {
|
if (popUpToolTip != null) {
|
||||||
popUpToolTip.hide();
|
popUpToolTip.hide();
|
||||||
popUpToolTip = null;
|
popUpToolTip = null;
|
||||||
|
@ -1218,8 +1260,26 @@ public class TimeLine extends VisPlugin {
|
||||||
public void paintComponent(Graphics g) {
|
public void paintComponent(Graphics g) {
|
||||||
Rectangle bounds = g.getClipBounds();
|
Rectangle bounds = g.getClipBounds();
|
||||||
/*logger.info("Clip bounds: " + bounds);*/
|
/*logger.info("Clip bounds: " + bounds);*/
|
||||||
long intervalStart = (long)bounds.x*(long)currentPixelDivisor;
|
|
||||||
long intervalEnd = intervalStart + bounds.width*currentPixelDivisor;
|
if (needZoomOut) {
|
||||||
|
/* Need zoom out */
|
||||||
|
g.setColor(Color.RED);
|
||||||
|
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||||
|
|
||||||
|
Rectangle vis = timeline.getVisibleRect();
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
String msg = "Zoom out";
|
||||||
|
FontMetrics fm = g.getFontMetrics();
|
||||||
|
int msgWidth = fm.stringWidth(msg);
|
||||||
|
int msgHeight = fm.getHeight();
|
||||||
|
g.drawString(msg,
|
||||||
|
vis.x + vis.width/2 - msgWidth/2,
|
||||||
|
vis.y + vis.height/2 + msgHeight/2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long intervalStart = (long)(bounds.x*currentPixelDivisor);
|
||||||
|
long intervalEnd = (long) (intervalStart + bounds.width*currentPixelDivisor);
|
||||||
|
|
||||||
if (intervalEnd > simulation.getSimulationTime()) {
|
if (intervalEnd > simulation.getSimulationTime()) {
|
||||||
intervalEnd = simulation.getSimulationTime();
|
intervalEnd = simulation.getSimulationTime();
|
||||||
|
@ -1453,6 +1513,8 @@ public class TimeLine extends VisPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoteRuler extends JPanel {
|
class MoteRuler extends JPanel {
|
||||||
|
private static final long serialVersionUID = -5555627354526272220L;
|
||||||
|
|
||||||
public MoteRuler() {
|
public MoteRuler() {
|
||||||
setPreferredSize(new Dimension(35, 1));
|
setPreferredSize(new Dimension(35, 1));
|
||||||
setToolTipText(null);
|
setToolTipText(null);
|
||||||
|
@ -1883,17 +1945,27 @@ public class TimeLine extends VisPlugin {
|
||||||
private long lastRepaintSimulationTime = -1;
|
private long lastRepaintSimulationTime = -1;
|
||||||
private Timer repaintTimelineTimer = new Timer(TIMELINE_UPDATE_INTERVAL, new ActionListener() {
|
private Timer repaintTimelineTimer = new Timer(TIMELINE_UPDATE_INTERVAL, new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
/* Only set new size if simulation time has changed */
|
||||||
|
long now = simulation.getSimulationTime();
|
||||||
|
if (now == lastRepaintSimulationTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastRepaintSimulationTime = now;
|
||||||
|
|
||||||
|
/* Update timeline size */
|
||||||
|
int newWidth;
|
||||||
|
if (now/currentPixelDivisor > Integer.MAX_VALUE) {
|
||||||
|
/* Need zoom out */
|
||||||
|
newWidth = 1;
|
||||||
|
needZoomOut = true;
|
||||||
|
} else {
|
||||||
|
newWidth = (int) (now/currentPixelDivisor);
|
||||||
|
needZoomOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle visibleRectangle = timeline.getVisibleRect();
|
Rectangle visibleRectangle = timeline.getVisibleRect();
|
||||||
boolean isTracking = visibleRectangle.x + visibleRectangle.width >= timeline.getWidth();
|
boolean isTracking = visibleRectangle.x + visibleRectangle.width >= timeline.getWidth();
|
||||||
|
|
||||||
/* Only set new size if simulation time has changed */
|
|
||||||
if (simulation.getSimulationTime() == lastRepaintSimulationTime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastRepaintSimulationTime = simulation.getSimulationTime();
|
|
||||||
|
|
||||||
/* Update timeline size */
|
|
||||||
int newWidth = (int) (simulation.getSimulationTime()/currentPixelDivisor);
|
|
||||||
int newHeight = (int) (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size());
|
int newHeight = (int) (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size());
|
||||||
timeline.setPreferredSize(new Dimension(
|
timeline.setPreferredSize(new Dimension(
|
||||||
newWidth,
|
newWidth,
|
||||||
|
@ -1909,7 +1981,7 @@ public class TimeLine extends VisPlugin {
|
||||||
/* Update visible rectangle */
|
/* Update visible rectangle */
|
||||||
if (isTracking) {
|
if (isTracking) {
|
||||||
Rectangle r = new Rectangle(
|
Rectangle r = new Rectangle(
|
||||||
newWidth-1, 0,
|
newWidth-1, visibleRectangle.y,
|
||||||
1, 1);
|
1, 1);
|
||||||
timeline.scrollRectToVisible(r);
|
timeline.scrollRectToVisible(r);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue