Last updated June 06, 2010 22:27, by kirillg
Multiple timelines in SWT applications
Trident supports running multiple independent timelines at the same time. This page shows the SWT application behind this video, where every cell rollover is implemented as a separate timeline.
We start with a class that implements a specific grid cell:
public static class SnakePanelRectangle {
private Color backgroundColor;
private boolean isRollover;
private Timeline rolloverTimeline;
private SWTRepaintTimeline repaintTimeline;
public SnakePanelRectangle(SWTRepaintTimeline repaintTimeline) {
this.backgroundColor = Display.getDefault().getSystemColor(
SWT.COLOR_BLACK);
this.isRollover = false;
this.rolloverTimeline = new Timeline(this);
this.rolloverTimeline.addPropertyToInterpolate("backgroundColor",
Display.getDefault().getSystemColor(SWT.COLOR_YELLOW),
Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
this.rolloverTimeline.setDuration(2500);
this.repaintTimeline = repaintTimeline;
}
public void setRollover(boolean isRollover) {
if (this.isRollover == isRollover)
return;
this.isRollover = isRollover;
if (this.isRollover) {
this.rolloverTimeline.replay();
}
}
public void setBackgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
this.repaintTimeline.forceRepaintOnNextPulse();
}
public Color getBackgroundColor() {
return backgroundColor;
}
}
A few major points in this class:
- The default background color of a cell is black (lines 11-12).
- The rollover timeline interpolates the background color from yellow to black over a period of 2.5 seconds (lines 13-17).
- The rollover timeline is replayed when
setRolloveris called withtrue. This restarts the timeline to interpolate the foreground color from yellow. - When
setBackgroundColoris called by the rollover timeline, we ask the repaint timeline to force the repaint of the window on the next pulse.
The next class implements a cell grid, tracing the mouse events and dispatching the rollover events to the relevant cells:
private static class SnakePanel extends Canvas {
private SnakePanelRectangle[][] grid;
private int ROWS = 10;
private int COLUMNS = 20;
private int DIM = 20;
public SnakePanel(Composite parent) {
super(parent, SWT.DOUBLE_BUFFERED);
SWTRepaintTimeline repaintTimeline = new SWTRepaintTimeline(this);
repaintTimeline.setAutoRepaintMode(false);
this.grid = new SnakePanelRectangle[COLUMNS][ROWS];
for (int i = 0; i < COLUMNS; i++) {
for (int j = 0; j < ROWS; j++) {
this.grid[i][j] = new SnakePanelRectangle(repaintTimeline);
}
}
repaintTimeline.playLoop(RepeatBehavior.LOOP);
this.addMouseMoveListener(new MouseMoveListener() {
int rowOld = -1;
int colOld = -1;
@Override
public void mouseMove(MouseEvent e) {
int x = e.x;
int y = e.y;
int column = x / (DIM + 1);
int row = y / (DIM + 1);
if ((column >= COLUMNS) || (row >= ROWS))
return;
if ((column != colOld) || (row != rowOld)) {
if ((colOld >= 0) && (rowOld >= 0))
grid[colOld][rowOld].setRollover(false);
grid[column][row].setRollover(true);
}
colOld = column;
rowOld = row;
}
});
this.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
GC gc = e.gc;
gc.setBackground(e.display.getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(e.x, e.y, e.width, e.height);
for (int i = 0; i < COLUMNS; i++) {
for (int j = 0; j < ROWS; j++) {
SnakePanelRectangle rect = grid[i][j];
Color backgr = rect.getBackgroundColor();
gc.setBackground(backgr);
gc.fillRectangle(i * (DIM + 1), j * (DIM + 1), DIM,
DIM);
}
}
}
});
}
}
A few major points in this class:
- A special type of timeline is created and played in a loop - lines 14-15/24. In this example, each cell rollover timeline changes the background color of that cell and asks the "master" repaint timeline to repaint the entire grid panel. While this repaint timeline loops forever, it only repaints the window when its
forceRepaintOnNextPulsehas been called. This way we decouple the updates of the model from the repaint, while still not repainting the entire window when the mouse is not moving and all rollover timelines are idle. - The mouse move listener (lines 31-49) tracks the mouse location, calling the
setRollovermethod on relevant cells. Since each cell rollover timeline runs for 2.5 seconds, quick mouse moves will result in multiple timelines running in parallel. - The painting of each cell respects the current background color of that cell - lines 61-64.
Finally, the main method that creates a host frame and adds the cell grid panel to it:
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(430, 240);
shell.setText("SWT Snake");
FillLayout layout = new FillLayout();
shell.setLayout(layout);
SnakePanel snake = new SnakePanel(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}





