/* * Copyright (c) 2005 (Mike) Maurice Kienenberger (mkienenb@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.gamenet.util; import java.awt.EventQueue; import java.util.Timer; import java.util.TimerTask; import javax.swing.ProgressMonitor; import org.gamenet.application.mm8leveleditor.lod.ProgressDisplayer; public class MonitoredTaskThread implements TaskObserver { private static final int PROGRESS_MIN = -1; private static final int PROGRESS_MAX = 250; private volatile ProgressMonitor monitor = null; // TODO: probably should reduce this dependency private ProgressDisplayer progressDisplayer = null; private String title = null; private Object message = null; private Runnable monitoredTask = null; private Thread monitoredTaskThread = null; private Timer checkForCancelTimer = null; public MonitoredTaskThread(ProgressDisplayer progressDisplayer, Object message, String title, Runnable monitoredTask) { super(); this.monitoredTask = monitoredTask; this.title = title; this.message = message; this.progressDisplayer = progressDisplayer; } /** * @param oldLodFile original lod file * @param newLodFileToCreate new lod file based on old lod file + files to import. * @param filesToImportList list of File objects to update or add to new lod file. */ public void start() { monitor = progressDisplayer.getProgressMonitor(message, title, PROGRESS_MIN, PROGRESS_MAX); monitor.setProgress(PROGRESS_MIN); // force progress panel to pop up sooner Runnable wrappedMonitoredTask = new Runnable() { public void run() { Throwable caughtThrowable = null; try { monitoredTask.run(); } catch(Throwable throwable) { throwable.printStackTrace(); caughtThrowable = throwable; } monitoredTaskFinished(caughtThrowable); } }; monitoredTaskThread = new Thread(wrappedMonitoredTask); monitoredTaskThread.setPriority(monitoredTaskThread.getPriority() - 1); monitoredTaskThread.start(); TimerTask checkForCancelTimerTask = new TimerTask() { public void run() { if (monitor.isCanceled()) monitoredTaskThread.interrupt(); } }; checkForCancelTimer = new Timer(true); checkForCancelTimer.schedule(checkForCancelTimerTask, 200, 200); } protected void monitoredTaskFinished(Throwable throwable) { if (null != monitor) { EventQueue.invokeLater(new Runnable() { public void run() { monitor.close(); } }); } if (null != checkForCancelTimer) checkForCancelTimer.cancel(); if (null != throwable) { if (null != throwable.getMessage()) { progressDisplayer.displayErrorPanel("Error while running task: " + throwable.getLocalizedMessage()); } else if (throwable instanceof OutOfMemoryError) { progressDisplayer.displayErrorPanel("Error while running task: " + "\n" + "Not enough memory to load data." + "\n" + "Try starting program with more memory:" + "\n" + "for example, to specify 256Mb of memory, use 'java -Xms256M -Xmx256M ...'"); } else { progressDisplayer.displayErrorPanel("Error while running task: " + throwable); } } } private int lastProgressUpdate = PROGRESS_MIN - 1; public int getRange() { return PROGRESS_MAX - (PROGRESS_MIN + 1); } private void sendProgress(String identifier, int trackableProgress) { final String finalizedNote = identifier; final int finalizedProgress = trackableProgress; EventQueue.invokeLater(new Runnable() { public void run() { monitor.setNote(finalizedNote); monitor.setProgress(finalizedProgress); } }); } public void taskProgress(String identifier, float percentageDone) { int trackableProgress = Math.round(percentageDone * getRange()); if (trackableProgress > lastProgressUpdate) { sendProgress(identifier, trackableProgress); lastProgressUpdate = trackableProgress; } } }