|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.tasklist.usertasks; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TimerTask; import java.util.Vector; import javax.swing.SwingUtilities; import javax.swing.Timer; import org.netbeans.modules.tasklist.core.Task; import org.netbeans.modules.tasklist.core.TaskAnnotation; import org.netbeans.modules.tasklist.core.TaskList; import org.netbeans.modules.tasklist.core.translators.AbstractTranslator; import org.netbeans.modules.tasklist.core.translators.FormatTranslator; import org.netbeans.modules.tasklist.core.translators.UnknownFormatException; import org.netbeans.modules.tasklist.usertasks.translators.HTMLTranslator; import org.netbeans.modules.tasklist.usertasks.translators.UserTaskListXMLTranslator; import org.netbeans.modules.tasklist.usertasks.translators.iCalSupport; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.ErrorManager; import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor.Message; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; /** * This class represents the tasklist itself * @todo The tasks that had a due time while the IDE was shut down will not * store it's "alarm-sent-property" unless the tasklist is touched after * the file is beeing parsed... I'll fix this as soon as possible... * * @author Tor Norbye * @author Trond Norbye */ public class UserTaskList extends TaskList implements Timeout { // List category final static String USER_CATEGORY = "usertasks"; // NOI18N private static UserTaskList tasklist = null; private static final java.util.Timer TIMER = new java.util.Timer(true); /** * Currently working on this task */ private static UserTask started = null; /** * The running task was suspended. It means that after the user * touched the mouse it will be running again. */ private static boolean suspended = false; /** * Time as returned by System.currentMillis() when the task was started */ private static long startedAt; private static int initialDuration; /** * Old value of the duration attribute of the current task */ private static int lastDuration; /** * Returns the default task list * * @return default task list */ public static UserTaskList getDefault() { if (tasklist == null) { try { tasklist = new UserTaskList(); tasklist.readDocument(); } catch (IOException ioe) { DialogDisplayer.getDefault().notify(new Message( ioe, NotifyDescriptor.ERROR_MESSAGE)); } } return tasklist; } static { TIMER.scheduleAtFixedRate(new TimerTask() { public void run() { timer(); } }, 0, 1000 * 15); ActivityListener.init(); } /** * Executed once per minute */ private static void timer() { if (started == null) return; long now = System.currentTimeMillis(); if (lastDuration == started.getSpentTime()) { if ((System.currentTimeMillis() - ActivityListener.getLastActivityMillis()) > 10 * 60 * 1000) { suspended = true; } else { if (suspended) { startedAt = ActivityListener.getLastActivityMillis(); initialDuration = started.getSpentTime(); suspended = false; } int diff = (int) ((now - startedAt) / (60 * 1000)); started.setSpentTime(initialDuration + diff); lastDuration = started.getSpentTime(); } } else { lastDuration = started.getSpentTime(); } } /** * Returns started task * * @return started task or null */ public static UserTask getStarted() { return started; } /** * Starts another task * * @param task currently working on this task. May be null. */ public static void start(UserTask task) { if (started != null) { timer(); } started = task; if (started != null) { started.setSpentTimeComputed(false); startedAt = System.currentTimeMillis(); lastDuration = task.getSpentTime(); initialDuration = task.getSpentTime(); } } /** File being shown in this tasklist */ private FileObject file = null; /** String-path version of the file field */ private String path = null; /** The current timeout */ private long currentTimeout; private AbstractTranslator io = null; /** * During loading of a tasklist I may encounter items that have expired * while the IDE was shut down. Since the load-function turns off the * effect of markChanged, I need to store this information in another * variable, and save the tasklist when the load is finished.. */ private boolean expiredTask; /** Timer which keeps track of outstanding save requests - that way * deleting multiple items for example will not cause multiple saves. */ private Timer runTimer = null; // User can work on one task at time (simpliication) ~~~~~~~~~~~~~~~ /** * Creates a new instance of TaskList */ public UserTaskList() { expiredTask = false; currentTimeout = Long.MAX_VALUE; } /** * Creates a new instance of TaskList * * @deprecated, use readFile instead. * @see readFile */ public UserTaskList(FileObject file) { this(); readFile(file); } /** Location of the tasklist */ public FileObject getFile() { return file; } /** * Due to the fact that readDocument may return false (unknown file format * for example), this should not be done in an constructor (unless we * provide a good() function to test if the object state is good...). * @param file the file to read.. * @return true if success, false otherwise.. */ public boolean readFile(FileObject file) { this.file = file; File f = FileUtil.toFile(file); this.path = f.getPath(); boolean ret; try { ret = readDocument(); // the readDocument function will order the next timeout! } catch (IOException ioe) { DialogDisplayer.getDefault().notify(new Message( ioe, NotifyDescriptor.ERROR_MESSAGE)); ret = false; } return ret; } /** * Searches for categories through all tasks. * * @return all found categories */ public String[] getCategories() { Iterator it = this.getTasks().iterator(); Set cat = new java.util.HashSet(); while (it.hasNext()) { UserTask ut = (UserTask) it.next(); findCategories(ut, cat); } return (String[]) cat.toArray(new String[cat.size()]); } /** * Searches for categories * * @param task search for categories in this task and all of it's subtasks * recursively * @param cat container for found categories. String[] */ private static void findCategories(UserTask task, Set cat) { if (task.getCategory().length() != 0) cat.add(task.getCategory()); Iterator it = task.subtasksIterator(); while (it.hasNext()) { findCategories((UserTask) it.next(), cat); } } /** Write todo items out to disk */ public void save() { if (!needSave || dontSave) { return; } Iterator it = getTasks().iterator(); while (it.hasNext()) { UserTask task = (UserTask) it.next(); task.updateLineNumberRecursively(); } // Write out todo items to disk scheduleWrite(); } private boolean readDocument() throws IOException { String name = path; if (name == null) { name = Settings.getDefault().getExpandedFilename(); } File fname = new File(name); if (!fname.exists()) { // Not an error - you may not have saved tasks yet // Perhaps we have just upgraded? Look in the old place (temporary // migration) name = System.getProperty("netbeans.user") + // NOI18N File.separatorChar + "system" + File.separatorChar + // NOI18N "TaskList" + File.separatorChar + "tasklist.ics"; // NOI18N fname = new File(name); if (fname.exists()) { io = new iCalSupport(); dontSave = true; boolean success; try { success = io.read(this, null, fname, false); } catch (UnknownFormatException e) { // NOTE the exception text should be localized! DialogDisplayer.getDefault().notify(new Message(e.getMessage(), NotifyDescriptor.ERROR_MESSAGE)); success = false; } dontSave = false; if (success) { save(); fname.delete(); } needSave = false; return success; } return false; } io = new iCalSupport(); dontSave = true; boolean success; try { success = io.read(this, null, fname, false); orderNextTimeout(); /* if (root != null) { showAnnotations((UserTask)root); } */ } catch (UnknownFormatException e) { // NOTE the exception text should be localized! DialogDisplayer.getDefault().notify(new Message(e.getMessage(), NotifyDescriptor.ERROR_MESSAGE)); success = false; } needSave = false; dontSave = false; if (expiredTask) { // One (or more) tasks expired while the IDE was closed... // save the list as soon as possible... expiredTask = true; markChanged(); } return success; } /** Show all annotations in this tasklist in the editor */ void showAnnotations(Iterator tasks) { while (tasks.hasNext()) { UserTask task = (UserTask)tasks.next(); if (task.getLine() != null) { task.updateAnnotation(); } if (task.hasSubtasks()) { showAnnotations(task.getSubtasks().iterator()); } } } /** Remove all annotations in this tasklist from the editor */ void hideAnnotations(Iterator tasks) { while (tasks.hasNext()) { UserTask task = (UserTask)tasks.next(); if (task.getAnnotation() != null) { TaskAnnotation anno = task.getAnnotation(); anno.detach(); task.setAnnotation(null); } if (task.hasSubtasks()) { hideAnnotations(task.getSubtasks().iterator()); } } } // Look up a particular item by uid public UserTask findItem(Iterator tasks, String uid) { while (tasks.hasNext()) { UserTask task = (UserTask)tasks.next(); if (task.getUID().equals(uid)) { return task; } if (task.hasSubtasks()) { UserTask f = findItem(task.subtasksIterator(), uid); if (f != null) { return f; } } } return null; } /** Schedule a document save */ private void scheduleWrite() { // Stop our current timer; the previous node has not // yet been scanned; too brief an interval if (runTimer != null) { runTimer.stop(); runTimer = null; } runTimer = new Timer(300, // 0.3 second delay new ActionListener() { public void actionPerformed(ActionEvent evt) { runTimer = null; // Write out todo items to disk try { writeDocument(); } catch (IOException ioe) { DialogDisplayer.getDefault().notify(new Message( ioe, NotifyDescriptor.ERROR_MESSAGE)); } needSave = false; } }); runTimer.setRepeats(false); runTimer.setCoalesce(true); runTimer.start(); } /** * Write todolist to iCal. */ private void writeDocument() throws IOException { if (io == null) { io = new iCalSupport(); } String fname; if (path != null) { fname = path; } else { fname = Settings.getDefault().getExpandedFilename(); } File f = new File(fname); File pf = f.getParentFile(); String filename = f.getPath().substring(pf.getPath().length()+1); boolean saveBackup = Settings.getDefault().getBackups(); // Make sure we have the right IO, since the user may have // renamed the save-file if (!(io instanceof iCalSupport)) { io = new iCalSupport(); } io.write(this, null, filename, pf, false, saveBackup); // Remove permissions for others on the file when on Unix // varieties if (new File("/bin/chmod").exists()) { try { Runtime.getRuntime().exec( new String[] {"/bin/chmod", "go-rwx", // NOI18N fname }); } catch (Exception e) { // Silently accept ErrorManager.getDefault().notify( ErrorManager.INFORMATIONAL, e); } } needSave = false; } void purgeCompletedItems() { if (getTasks().size() == 0 ) { return; } dontSave = true; Iterator it = getTasks().iterator(); while (it.hasNext()) { UserTask task = (UserTask) it.next(); recursivePurge(task); } dontSave = false; save(); } /** Remove any completed items from the list. * Only works if started on the root node. * NOTE - if a task is marked done, it AND ALL ITS CHILDREN * are removed, even if the children haven't been marked done. */ private void recursivePurge(UserTask node) { if (node.getSubtasks() != null) { List l = new ArrayList(node.getSubtasks()); // I may have to repeat purges because once I delete an item from // the list, the iterator needs to be redone Iterator it = l.iterator(); while (it.hasNext()) { UserTask task = (UserTask)it.next(); if (task.isDone()) { Task pt = task.getParent(); int index = pt.indexOf(task); pt.removeSubtask(task); // Ensure that we're not showing any markers for this item fireRemoved(pt, task, index); } else if (task.hasSubtasks()) { recursivePurge(task); } } } } /** * Order a timeout for the next due date */ void orderNextTimeout() { long nextTimeout = Long.MAX_VALUE; long now = System.currentTimeMillis(); UserTask ref = null; Iterator i = getTasks().iterator(); while (i.hasNext()) { UserTask t = (UserTask)i.next(); long n = t.getDueTime(); if (n != Long.MAX_VALUE && !t.isDueAlarmSent()) { if (n <= now) { showExpiredTask(t); continue; } else if (n < nextTimeout) { nextTimeout = n; ref = t; } } } if (nextTimeout != currentTimeout) { // cancel the previous ordered timeout, and add the new one if (currentTimeout != Long.MAX_VALUE) { TimeoutProvider.getInstance().cancel(this, null); } TimeoutProvider.getInstance().add(this, ref, nextTimeout); currentTimeout = nextTimeout; } } /** Return the translators capable of handling this tasklist. * @return Array of translators that can read/write the tasklist */ public FormatTranslator[] getTranslators() { FormatTranslator[] translators = new FormatTranslator[] { new iCalSupport(), new UserTaskListXMLTranslator(), new HTMLTranslator("usertasks-tree-html.xsl"), new HTMLTranslator("usertasks-table-html.xsl") }; return translators; } public String toString() { return "UserTaskList(" + path + ")"; // NOI18N } /** * Callback function for the TimeoutProvider to call when the timeout * expired. This function will block the TimeoutProviders thread, so * it should be used for a timeconsuming task (one should probably * reschedule oneself with the SwingUtilities.invokeLater() ???) * @param o the object provided as a user reference */ public void timeoutExpired(Object o) { // Show the task... showExpiredTask((UserTask)o); // order the next timeout for this list orderNextTimeout(); } /** * Present the user with a dialog that shows information of the task that * expired... * * @todo Replace the UserTaskDuePanel with the EditTaskPanel???? * @param task the task to show */ private void showExpiredTask(UserTask task) { task.setDueAlarmSent(true); expiredTask = true; markChanged(); final UserTask t = task; SwingUtilities.invokeLater(new Runnable() { public void run() { UserTaskDuePanel panel = new UserTaskDuePanel(t); String title = NbBundle.getMessage(NewTaskAction.class, "TaskDueLabel"); // NOI18N DialogDescriptor d = new DialogDescriptor(panel, title); d.setModal(false); d.setMessageType(NotifyDescriptor.PLAIN_MESSAGE); d.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION); java.awt.Dialog dlg = DialogDisplayer.getDefault().createDialog(d); dlg.pack(); dlg.show(); } }); } /** Extract tasks recursivelly to given vector. */ void addAllTasks(Vector v) { if (getTasks().size() == 0) { return; } addAllTasks(getTasks().iterator(), v); } void addAllTasks(Iterator tasks, Vector v) { while (tasks.hasNext()) { UserTask t = (UserTask)tasks.next(); v.addElement(t); if (t.hasSubtasks()) { addAllTasks(t.getSubtasks().iterator(), v); } } } protected void fireAdded(Task task) { super.fireAdded(task); markChanged(); orderNextTimeout(); } protected void fireStructureChanged(Task task) { super.fireStructureChanged(task); markChanged(); } protected void fireRemoved(Task pt, Task task, int index) { super.fireRemoved(pt, task, index); if (getStarted() == task) started = null; markChanged(); orderNextTimeout(); } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.