improved zoom

This commit is contained in:
fros4943 2010-04-26 08:00:19 +00:00
parent 5dd5b5ac43
commit c7ef068f33

View file

@ -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,7 +326,40 @@ public class TimeLine extends VisPlugin {
} }
}; };
private void forceRepaintAndFocus(final long focusTime, final double focusCenter) {
forceRepaintAndFocus(focusTime, focusCenter, true);
}
private void forceRepaintAndFocus(final long focusTime, final double focusCenter, final boolean mark) {
lastRepaintSimulationTime = -1; /* Force repaint */
repaintTimelineTimer.getActionListeners()[0].actionPerformed(null); /* Force size update*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int w = timeline.getVisibleRect().width;
/* centerPixel-leftPixel <=> focusCenter*w; */
int centerPixel = (int) (focusTime/currentPixelDivisor);
int leftPixel = (int) (focusTime/currentPixelDivisor - focusCenter*w);
Rectangle r = new Rectangle(
leftPixel, 0,
w, 1
);
timeline.scrollRectToVisible(r);
/* Time ruler */
if (mark) {
mousePixelPositionX = centerPixel;
mouseDownPixelPositionX = centerPixel;
mousePixelPositionY = timeline.getHeight();
}
}
});
}
private Action zoomInAction = new AbstractAction("Zoom in (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;
@ -334,37 +370,26 @@ public class TimeLine extends VisPlugin {
if (mousePixelPositionX > 0) { if (mousePixelPositionX > 0) {
pixelX = mousePixelPositionX; pixelX = mousePixelPositionX;
} }
final long centerTime = pixelX*currentPixelDivisor; final long centerTime = (long) (pixelX*currentPixelDivisor);
int zoomLevel = 0;
while (zoomLevel < ZOOM_LEVELS.length) {
if (currentPixelDivisor <= ZOOM_LEVELS[zoomLevel]) break;
zoomLevel++;
}
if (zoomLevel > 0) { if (zoomLevel > 0) {
zoomLevel--; zoomLevel--; /* zoom in */
} }
currentPixelDivisor = ZOOM_LEVELS[zoomLevel]; currentPixelDivisor = ZOOM_LEVELS[zoomLevel];
logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==0)?"(MIN)":"")); logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==0)?"(MIN)":""));
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
);
timeline.scrollRectToVisible(r);
/* Time ruler */
mousePixelPositionX = centerPixel;
mouseDownPixelPositionX = centerPixel;
mousePixelPositionY = timeline.getHeight();
}
});
} }
}; };
private Action zoomOutAction = new AbstractAction("Zoom out (Ctrl-)") { private Action zoomOutAction = new AbstractAction("Zoom out (Ctrl-)") {
private static final long serialVersionUID = 6837091379835151725L;
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 +397,51 @@ public class TimeLine extends VisPlugin {
pixelX = popupLocation.x; pixelX = popupLocation.x;
popupLocation = null; popupLocation = null;
} }
final long centerTime = pixelX*currentPixelDivisor; 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);
} }