/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2000-2013 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others. * *See COPYING for Details * *This program is free software; you can redistribute it and/or *modify it under the terms of the GNU General Public License *as published by the Free Software Foundation; either version 2 *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 General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package freemind.common; import java.awt.Component; import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.KeyAdapter; import java.awt.event.MouseAdapter; import java.awt.event.MouseMotionAdapter; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.RootPaneContainer; /** * Long running tasks inside FreeMind should derive from this class. * * @author foltin * @date 08.04.2013 */ public abstract class FreeMindTask extends Thread { private static final long TIME_TO_DISPLAY_PROGRESS_BAR_IN_MILLIS = 1000; private boolean mInterrupted = false; private boolean mFinished = false; private int mAmountOfSteps; private FreeMindProgressMonitor mProgressMonitor = null; private int mRounds; protected ProgressDescription mProgressDescription; private RootPaneContainer mFrame; private JPanel mGlass; private Component mOldGlassPane; protected class ProgressDescription { /** * @param pProgressString * @param pProgressParameters */ public ProgressDescription(String pProgressString, Object[] pProgressParameters) { super(); mProgressString = pProgressString; mProgressParameters = pProgressParameters; } public String mProgressString; /** * To be inserted into mProgressString; */ public Object[] mProgressParameters; } public FreeMindTask(RootPaneContainer pRootPaneContainer, int pAmountOfSteps, String pName) { super(pName); mFrame = pRootPaneContainer; mAmountOfSteps = pAmountOfSteps; mProgressMonitor = new FreeMindProgressMonitor(getName()); mGlass = new JPanel(new GridLayout(0, 1)); JLabel padding = new JLabel(); mGlass.setOpaque(false); mGlass.add(padding); // trap both mouse and key events. Could provide a smarter // key handler if you wanted to allow things like a keystroke // that would cancel the long-running operation. mGlass.addMouseListener(new MouseAdapter() { }); mGlass.addMouseMotionListener(new MouseMotionAdapter() { }); mGlass.addKeyListener(new KeyAdapter() { }); // make sure the focus won't leave the glass pane mGlass.setFocusCycleRoot(true); // 1.4 mOldGlassPane = pRootPaneContainer.getGlassPane(); pRootPaneContainer.setGlassPane(mGlass); mGlass.setVisible(true); padding.requestFocus(); // required to trap key events } /* * (non-Javadoc) * * @see java.lang.Thread#run() */ public void run() { long startTime = System.currentTimeMillis(); mRounds = 0; boolean again = true; while (again) { try { again = processAction(); mRounds++; if (!again) { // already ready!! mRounds = mAmountOfSteps; } if (mRounds == mAmountOfSteps) { again = false; } } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); again = false; } if (isInterrupted()) { again = false; } if (System.currentTimeMillis() - startTime > TIME_TO_DISPLAY_PROGRESS_BAR_IN_MILLIS) { // mProgressMonitor.setModal(true); EventQueue.invokeLater(new Runnable() { public void run() { mProgressMonitor.setVisible(true); }}); } if (mProgressMonitor.isVisible()) { ProgressDescription progressDescription = mProgressDescription; if (mProgressDescription == null) { progressDescription = new ProgressDescription( "FreeMindTask.Default", new Object[] { new Integer( mRounds) }); } boolean canceled = mProgressMonitor.showProgress(mRounds, mAmountOfSteps, progressDescription.mProgressString, progressDescription.mProgressParameters); if (canceled) { mInterrupted = true; again = false; } } } setFinished(true); EventQueue.invokeLater(new Runnable() { public void run() { mGlass.setVisible(false); mFrame.setGlassPane(mOldGlassPane); mProgressMonitor.dismiss(); } }); } /** * Subclasses should process one single action out of the set of its actions * and then return. The method is directly called again by the task * controller until it returns false. * * @return true, if further actions follow. False, if done. */ protected abstract boolean processAction() throws Exception; public boolean isInterrupted() { return mInterrupted; } public void setInterrupted(boolean pInterrupted) { mInterrupted = pInterrupted; } public boolean isFinished() { return mFinished; } public void setFinished(boolean pFinished) { mFinished = pFinished; } public int getAmountOfSteps() { return mAmountOfSteps; } public void setAmountOfSteps(int pAmountOfSteps) { mAmountOfSteps = pAmountOfSteps; } public int getRounds() { return mRounds; } }