// This file is part of AceWiki. // Copyright 2008-2013, AceWiki developers. // // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If // not, see http://www.gnu.org/licenses/. package ch.uzh.ifi.attempto.echocomp; import java.util.HashMap; import java.util.Map; import nextapp.echo.app.ApplicationInstance; import nextapp.echo.app.Column; import nextapp.echo.app.Component; import nextapp.echo.app.TaskQueueHandle; /** * This abstract class can be used to create components that are initialized asynchronously in the background. * This is makes sense for components that require some time to create themselves (e.g. because of time * expensive calculations). The possibly time consuming creation of the component can be done in a synchronized * way so that at most one such creation process (per application instance) is running at a time. * * @author Tobias Kuhn */ public abstract class DelayedComponent extends Column { private static final long serialVersionUID = -3479950976442367130L; private static Map<String, TaskQueueHandle> taskQueues = new HashMap<String, TaskQueueHandle>(); /** * Creates a new delayed component which shows the temporary component until the real component is * ready. * * @param tempComponent The temporary component. * @param synchronize Defines whether the calculation should be performed in a synchronized way. */ public DelayedComponent(Component tempComponent, boolean synchronize) { if (tempComponent != null) { add(tempComponent); } final ApplicationInstance application = EchoThread.getActiveApplication(); TaskQueueHandle taskQueueTemp = taskQueues.get(application.toString()); if (taskQueueTemp == null) { taskQueueTemp = application.createTaskQueue(); taskQueues.put(application.toString(), taskQueueTemp); } final TaskQueueHandle taskQueue = taskQueueTemp; if (synchronize) { EchoThread thread = new EchoThread() { public ApplicationInstance getApplication() { return application; } public void run() { synchronized (application) { final Component c = initComponent(); application.enqueueTask( taskQueue, new Runnable() { public void run() { DelayedComponent.this.removeAll(); DelayedComponent.this.add(c); finalizeAction(); } } ); try { sleep(500); } catch (InterruptedException ex) {} } } }; thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } else { EchoThread thread = new EchoThread() { public ApplicationInstance getApplication() { return application; } public void run() { final Component c = initComponent(); application.enqueueTask( taskQueue, new Runnable() { public void run() { DelayedComponent.this.removeAll(); DelayedComponent.this.add(c); finalizeAction(); } } ); } }; thread.start(); } } /** * Creates a new delayed component with the given temporary component. The calculation is * not synchronized. * * @param tempComponent The temporary component. */ public DelayedComponent(Component tempComponent) { this(tempComponent, false); } /** * Creates a new delayed component with no temporary component. * * @param synchronize Defines whether the calculation should be performed in a synchronized way. */ public DelayedComponent(boolean synchronize) { this(null, synchronize); } /** * Creates a new delayed component with no temporary component. The calculation is * not synchronized. */ public DelayedComponent() { this(null, false); } /** * This method should contain the (possibly time-consuming) operations to create the actual GUI * component. This operation will be performed asynchronously. As soon as it is finished, the * temporary component (if present) is replaced by the component this method returns. * * @return The GUI component. */ public abstract Component initComponent(); /** * Override this method to run code in the appliction context (e.g. for GUI changes) after the * asynchronous operation has finished. */ public void finalizeAction() { } }