/** * Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org> * * This file is part of org.appwork.utils.swing * * This software is licensed under the Artistic License 2.0, * see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php * for details */ package org.appwork.utils.swing; import javax.swing.SwingUtilities; /** * This class should be used to run gui code in the edt and return the generic * datatype to the parent thread. * * Implement edtRun to asure Thread safe executio of this gui code. * * @author $Author: Thomas$ * * @param <T> */ public abstract class EDTHelper<T> implements Runnable { /** * flag. If Runnable has terminated yet */ private boolean done = false; /** * flag, has runnable already started, invoked in edt */ private boolean started = false; /** * lock used for EDT waiting */ private final Object lock = new Object(); /** * Stores The returnvalue. This Value if of the Generic Datatype T */ private T returnValue; /** * Implement this method. Gui code should be used ONLY in this Method. * * @return */ public abstract T edtRun(); /** * Call this method if you want to wait for the EDT to finish the runnable. * It is assured that the returnvalue is available after this methjod has * returned. * * @return */ public T getReturnValue() { this.waitForEDT(); return this.returnValue; } /** * Run the runnable */ public void run() { synchronized (this.lock) { this.started = true; } try { this.returnValue = this.edtRun(); } catch (final Exception e) { org.appwork.utils.logging.Log.exception(e); } synchronized (this.lock) { this.lock.notify(); } this.done = true; } public boolean start() { return this.start(false); } /** * starts the runnable * * returns true in case we are in EDT or false if it got invoked later */ public boolean start(final boolean invokeLater) { synchronized (this.lock) { this.started = true; } if (!invokeLater && SwingUtilities.isEventDispatchThread()) { this.run(); return true; } else { SwingUtilities.invokeLater(this); return false; } } /** * Wait until the runnable has been finished by the EDT. If the Runnable has * not started yet, it gets started. */ public void waitForEDT() { if (this.done) { return; } boolean waitForFinish = true; synchronized (this.lock) { if (this.started == false) { waitForFinish = !this.start(false); } } if (waitForFinish) { while (!this.done) { synchronized (this.lock) { try { this.lock.wait(1000); } catch (final InterruptedException e) { } } } } } }