This a Java Swing-based application that I made to manage my ToDo list. There are several ToDo List Manager applications available. However, they only give a Name and a Done checkbox for each item. This project gives each ToDo item a hierarchy, workflow and relative priority. This makes it much easier for the user to assess which item is most important at any given time, but also keep track of items that are important for the future.
Each ToDo item has a Workflow State. This state is determined explicitly by the user. Here is a list of available states:
- Open: The item needs to considered.
- Accept: The item is worth doing.
- Reject: The item is not worth doing.
- Close: The item is complete.
- Open Pending: The item needs to be considered only after another item changes state.
- Accept Pending: The item is worth doing only after another item changes state.
The item starts as Open then user determines if the item is really worth doing or not. This allows a brainstorming capability. It also retains the rejected items for later consideration. There is no need to delete an item. Many times, a Rejected item may be reconsidered. A Rejected item may have notes that explain why that item was not considered last time.
The two pending states, Open Pending and Accept Pending, delay the state on an item until other items change state. This is useful when more information will help a decision or if an item can’t be completed until another task is done.
Each item in the system must be placed within a tree structure hierarchy. Each task is a child of one other task. This allows for each task’s state to be conditional on its parents. Consider the following example:
- The user wants to install Linux.
- The user must buy a Linux book.
- The user must burn CD’s for Linux.
- The user must download the iso images.
- The user must buy blank CDR’s before burning the CD’s
That’s quite a complicated ToDo list. At first glance, it’s not obvious what the user should do first. However, he could put this information in a tree to make it more straightforward. For example:
Figure 1: Hierarchy of Items
See in Figure 1 how the the “Install Linux” item is broken down into “Buy Linux Book” and “Burn CD’s”. Then the “Burn CD’s” item is broken down into “Download iso images” and “Buy Blank CDR’s”. This makes the dependencies more obvious. Now, if the user happened to find a book that included the Linux disks he needed, he could Reject “Burn CD’s”. Then, “Download iso images” and “Buy Blank CDR’s” would automatically become Inactive.
There are a number of possible inherited states. They are:
- Active: If all parents are Accepted.
- New: If a parent is Open.
- Waiting: If a parent has a Pending state.
- Inactive: If a parent is Closed or Rejected.
A Filter focuses the user’s attention only on the relevant ToDo items. Filters tie together Inherited and Workflow status to determine the overall condition of the items. There are six filter states:
- Assign: Shows all the non-Inactive Open items. Useful for seeing which items need to be Rejected or Accepted.
- Work: Shows all the Active Accepted items that have no Active Accepted parents. Useful for seeing what to do today.
- Events: Shows all the non-Inactive Pending nodes. Useful for seeing dependencies between unrelated nodes.
- Review: Shows all the Closed nodes. Useful for seeing progress over time.
- Recycle: Shows all the Rejected nodes. Useful for finding previously rejected items.
- No filter: Shows all nodes.
The user will likely spend most of their time in the Assign and Work filters. The Assign filter is great for sifting through tasks after a brainstorm session. The Work filter shows only what needs to be completed right now.
Each item has a priority once it is Accepted. The priority is always relative to other items. The program has a table-view that is used for setting and viewing priority. In the table, the user simply clicks-and-drags to move the items to match their real priority. Then, the user can click the Status column to Close an item when completed.
Figure 2: Table View
Some items will not be children, but will be dependent on others. For example, if the user wants to learn how to use GnuCash after Linux is installed. It’s not necessary to make GnuCash the parent of the “Install Linux” item. Instead the user could simply set a prerequisite of “Install Linux” for the “Learn GnuCash” item. Then set the Workflow State of “Learn GnuCash” to “Accepted Pending”. In that case, when “Install Linux” is Closed, “Learn GnuCash” will be Accepted.
Now that we’ve discussed the pieces of the software. Take a look at the User Interface:
Figure 3: User Interface
The upper-left corner is the filter selection. The lower-left corner is the Tree. It has a tab to go between the Tree and Table. The right side is the details of the current item. In this case, it is the “Install Linux” item.
Class Model Diagram
The program consists of several classes, many of them subclasses of Swing classes. Here is the Class Model Diagram for the program:
Figure 4: Class Model Diagram
The Diligent class is the entry point of the program. It instantiates the DiligentFrame class. DiligentFrame is a container for all the Swing Components. It instantiates a table and tree model, DiligentTableModel and DiligentTreeModel respectively. DiligentTableModel gets its data from the DiligentTreeModel. DiligentTreeModel is a subclass of Swing’s DefaultTreeModel. DiligentTreeModel uses DiligentNode for all of its nodes.
DiligentNode is the main container for all the information of every ToDo item. It is a subclass of Swing’s DefaultMutableTreeNode. It has a static class member variable, filter, for filtering the entire tree. filter is of class DiligentFilter. DiligentFilter has parameters on its methods to filter for both the tree and the table views. Filtering for a tree allows the parents to not be filtered out if a child is not filtered out.
There are few classes that have a DiligentNode within them. DiligentDetails is responsible for showing the detailed information about each node. DiligentNodeSelector is a special dialog for choosing a single node. DiligentEvent analyzes the state of a node to trigger a change in state of another node.
There are four miscellaneous classes within the architecture. DateParse contains a static method to convert a String to a Date. The Period class contains static methods to convert interval dates to and from a number of milliseconds. For example, an interval date might be “2w1d” for two weeks and one day. The ResourceManager is responsible for loading the icons and can be optimized to read the icons only once from the disk. The DiligentNodeRenderer is used by the JTree to show the icons next to each ToDo item.
It’s easy to go use this architecture for many things. This program could become a full Project Management system. It currently saves all the information in a single file. It could be modified to save the information to a central database with several users. Each item could have an owning person or group assigned to it. For now, it works great for managing my own personal tasks.
This program works great for managing personal tasks. For a copy of this program download it here.