/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.util;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.swt.widgets.Display;
/**
* This class should only be used in UI thread.
*
* @author Frank Shaka
*/
public class UITimer extends Cancelable {
private class InnerTask implements Runnable {
public void run() {
if (isCanceled())
return;
if (!isValid()) {
cancel();
return;
}
if (loops > 0) {
if (currentLoop >= loops) {
currentLoop = 0;
innerTask = null;
onFinished();
return;
} else {
currentLoop++;
}
}
long start = System.currentTimeMillis();
SafeRunner.run(task);
long end = System.currentTimeMillis();
if (isCanceled()) {
innerTask = null;
postCanceled();
} else {
Display display = Display.getCurrent();
if (display == null || display.isDisposed()) {
postCanceled();
} else if (innerTask != null) {
int taskDuration = (int) (end - start);
if (taskDuration >= interval) {
display.asyncExec(innerTask);
} else {
final int nextInterval = interval - taskDuration;
display.timerExec(nextInterval, innerTask);
}
}
}
}
}
private ISafeRunnable task;
private int delay;
private int interval;
private int loops = -1;
private int currentLoop = 0;
private Runnable innerTask = null;
private ITimerValidator validator = null;
/**
* @param task
* @param delay
* @param interval
*/
public UITimer(int delay, int interval, ISafeRunnable task) {
super();
this.task = task;
this.delay = delay;
this.interval = interval;
}
public UITimer(int delay, int interval, int loops, ISafeRunnable task) {
this(delay, interval, task);
this.loops = loops < 0 ? loops : Math.max(1, loops);
}
public void start() {
reinitialize();
run();
}
@Override
protected void doJob() {
if (!isValid()) {
cancel();
return;
}
innerTask = new InnerTask();
Display display = Display.getCurrent();
if (display != null && !display.isDisposed())
display.timerExec(delay, innerTask);
}
/**
*
*/
public void cancel() {
super.cancel();
innerTask = null;
onCanceled();
}
protected void onFinished() {
}
protected void onCanceled() {
}
protected void postCanceled() {
}
/**
* @return the delay
*/
public int getDelay() {
return delay;
}
/**
* @param delay
* the delay to set
*/
public void setDelay(int delay) {
this.delay = delay;
}
/**
* @return the interval
*/
public int getInterval() {
return interval;
}
/**
* @param interval
* the interval to set
*/
public void setInterval(int interval) {
this.interval = interval;
}
/**
* @return the task
*/
public ISafeRunnable getTask() {
return task;
}
/**
* @param task
* the task to set
*/
public void setTask(ISafeRunnable task) {
this.task = task;
}
/**
* @return the times
*/
public int getLoops() {
return loops;
}
/**
* @param times
* the times to set
*/
public void setLoops(int times) {
this.loops = times;
}
/**
* @return the currentTime
*/
public int getCurrentLoop() {
return currentLoop;
}
/**
* @param validator
* the validator to set
*/
public void setValidator(ITimerValidator validator) {
this.validator = validator;
}
/**
* @return the validator
*/
public ITimerValidator getValidator() {
return validator;
}
protected boolean isValid() {
return validator == null || validator.isRunnable();
}
}