/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util; import java.awt.AWTEvent; import java.awt.ActiveEvent; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.Window; import java.util.concurrent.Executor; /** * Helper class to wrap some swing related methods * @author jblok */ public class SwingHelper { private final Executor threadpool; private static SwingHelper memyselfandi; private static Object wailtLock = new Object(); private static final int sleepIntervals = 500; private SwingHelper(Executor a_threadpool) { threadpool = a_threadpool; } public static SwingHelper getSwingHelper(Executor a_threadpool) { if (memyselfandi == null) { memyselfandi = new SwingHelper(a_threadpool); } return memyselfandi; } public Object paintingWait(IUIBlocker blocker, String reason, int delayBeforeBlockUI_ms, BackgroundRunner backgroundRunner) throws Exception { threadpool.execute(backgroundRunner); synchronized (wailtLock) { wailtLock.wait(delayBeforeBlockUI_ms); } long startTime = System.currentTimeMillis(); boolean didBlock = false; try { while (!backgroundRunner.isFinished()) { if (!didBlock && (System.currentTimeMillis() - startTime) > delayBeforeBlockUI_ms) { didBlock = true; blocker.blockGUI(reason); } int time_spend_ms = dispatchEvents(sleepIntervals); if (!backgroundRunner.isFinished() && (sleepIntervals - time_spend_ms) > 0) { Thread.sleep((sleepIntervals - time_spend_ms)); } } } finally { if (didBlock) blocker.releaseGUI(); } return backgroundRunner.getReturnValue(); } public static abstract class BackgroundRunner implements Runnable { private Exception ex; private Object retval; private boolean isFinished; boolean isFinished() { return isFinished; } Object getReturnValue() throws Exception { if (ex != null) throw ex; return retval; } public final void run() { try { retval = doWork(); } catch (Exception e) { ex = e; } finally { isFinished = true; synchronized (wailtLock) { wailtLock.notify(); } } } public abstract Object doWork() throws Exception; } /** * It will dispatch AWT EventQueue events (if not already in a dispatchEvents call) as long as events are found, for maximum given "ms" time.<br/> * If ms > 0 it is guaranteed to dispatch at least one event. * * @param ms the maximum time to dispatch events for. If ms <= 0 no events will be dispatched. * @return the time events were dispatched from AWT EventQueue. Can be < "ms" when all available events have been dispatched. It will return 0 right away * if not currently running in event dispatch thread or we are already inside another dispatchEvents call. */ public static int dispatchEvents(int ms)//returns the actual time spend in ms { // dispatchEventsUntilNow(); // if (true) return; if (java.awt.EventQueue.isDispatchThread() && !isDispatching) { try { isDispatching = true; // int handled = 0; java.awt.EventQueue eventQ = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue(); long start_time = System.currentTimeMillis(); long currentTime = start_time; long end_time = start_time + ms; while (currentTime < end_time) { if (eventQ.peekEvent() == null) { break; //no more event ,leave } try { AWTEvent event = eventQ.getNextEvent(); if (event instanceof ActiveEvent) { ((ActiveEvent)event).dispatch(); } else { Object source = event.getSource(); if (source instanceof Component) { Component comp = (Component)source; comp.dispatchEvent(event); } } // handled++; } catch (InterruptedException e) { //hmm } currentTime = System.currentTimeMillis(); } return (int)(start_time - currentTime); } finally { isDispatching = false; } } return 0; } private static boolean isDispatching = false; private static void dispatchEventsUntilNow() { if (java.awt.EventQueue.isDispatchThread() && !isDispatching) { isDispatching = true; try { int handled = 0; java.awt.EventQueue eventQ = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue(); class StopEvent extends AWTEvent { StopEvent() { super(new Object(), 0); } } eventQ.postEvent(new StopEvent()); while (true) { try { AWTEvent event = eventQ.getNextEvent(); if (event instanceof StopEvent) { break; } if (event instanceof ActiveEvent) { ((ActiveEvent)event).dispatch(); } else { Object source = event.getSource(); if (source instanceof Component) { Component comp = (Component)source; comp.dispatchEvent(event); } } handled++; } catch (InterruptedException e) { //hmm } } // Debug.trace("####dispatchEventsUntilNow handeld "+(handled)+" events"); } finally { isDispatching = false; } } } public static void centerFrame(Window frame) { Dimension frameSize = frame.getSize(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2 - 10); } }