Added history combo to 'Title' field of transform, print/preview dialogs

Added drag'n'drop support for re-ordering tabs

Added optional confirmation dialog to time tracking

Added close buttons to tasklist tabs

Added blank line to single-selection droplists

And much, much more.

Introduction

You know how it is - you start work on one project and halfway through, you find one or two side-projects crop up that have to be solved before you can continue on the original project.

This is one such project with the added twist that it too started its life as a side-project. Here's what happened:

<Cue wavy screen effect>

I can only imagine that the planets must have been in (mis-)alignment or something, because at one point a few months ago, I was suddenly fielding emails on four or five separate articles I had previously submitted to CodeProject, some asking for features and others for bug fixes.

Foolishly or otherwise, I largely agreed with all the points raised, and subsequently found myself with fourteen or fifteen separate issues to resolve.

The situation was also made worse because I was trying to use CodeProject to keep track of all the things I had agreed to do, meaning that I had to continuously trawl the comments section of each article to remind myself of what I was supposed to be working on.

It even got to the stage where I was worrying that I'd fail to deliver on something - silly I know, but there you are!

Keeping a list on paper was a definite step in the right direction, but since I do all my coding on the same machine, it seemed somewhat inelegant, and anyway, we all know what happens to crucial bits of paper left lying around on desks and such.

The next step was to hunt around on the web for a tool to meet the following requirements:

Simple interface

Support for hierarchical data

Numbered items/subitems

Open file format

Freeware

Simple, huh! not!

I will admit that I did not spend weeks searching, but I am still surprised at the general lack of software matching my needs.

On reflection, I think that the reason may be simple: people are so used to commercial software being 'feature-rich' that when they come to design software themselves, they (not unreasonably) think they too need to cram as much in as possible, often leading to software where a lot of essential functionality is hidden away in the menu bar.

So, surprise, surprise, I decided to write something myself.

However, it's fair to say that I did not originally intend to post it on CodeProject and am only really doing so because I had a heap of fun solving some very interesting problems and these are what I think make it worth it.

Using the Software

There's really very little I need to say here since every feature/function is explicitly visible in the interface.

Nevertheless, the following list of basic capabilities and omissions may go someway to answering any questions that arise:

Files are stored in XML format with .xml file extension.

Trying to load a non-tasklist file will generally fail (unless you read the code to see how to circumvent it).

The number of items/subitems is limited only by memory (although performance may be the deciding factor before you exhaust memory).

Marking a parent item as 'done' will also gray-out child items, but they are not disabled or automatically marked as 'done'.

An ellipsis (...) indicates that an item has sub-items.

All items can be expanded or collapsed (by double-clicking).

Top-level items and sub-items are created using different toolbar buttons.

There are task-specific context-menus.

The previously open tasklists are re-opened on startup.

The tasklist is automatically saved when closing the software or minimizing it to the system tray.

The priority of a task is shown as a grayscale box to the left of the item.

Points of Interest

Here's where we come to the side-projects I was talking about, the first two of which I intend to work up into follow-up articles.

They are:

The 'ordered' tree control, which incorporates a non-client gutter for displaying the item numbers.

The idea stemmed from research I did into alternative designs for a tree-list control, which did not solve it by creating a hybrid control incorporating a tree and a list.

The hybrid control seems such an obvious solution that I suspect few people have stopped to question it, but it has still always struck me as looking far too much like hard work to be truly elegant ('square pegs' and 'round holes' spring to mind).

One possible idea is to implement the 'list' portion entirely in the non-client area of the tree. I.e., shift the right hand client edge to the left and then render the list portion in the resulting non-client area.

Whilst I've yet to get round to building a proof of concept, it was nevertheless this ongoing mental debate which prompted me to try to solve the requirement for numbered items and subitems by rendering the item/subitem numbers in the non-client area.

Without going into too much detail (as this will subsequently be an article of its own), this is how I got it to work:

Handle TVM_INSERTITEM and TVM_DELETEITEM to know exactly when items are added and removed.

In these handlers recalculate the width of the gutter required to display the widest 'dotted' item/subitem number. (Note: this is not necessarily simply the deepest subitem.)

Handle WM_NCCALCSIZE when it does, and offset the left border by the required gutter width.

Handle WM_NCPAINT for painting the numbers.

This is necessarily an over-simplification, but it captures the essence of the solution, and all that essentially remains is lots of fiddling about to ensure the non-client area gets redrawn at the the right times to stay synchronized with the client area.

Embedding .RC control definition data directly in a .cpp file to break the dependency on binary resources (a.k.a. 'Runtime Dialogs').

This is an idea that has been floating about for quite some time and which has only recently gelled into a workable solution.

The problem, put simply, is that if you want to take advantage of the resource editor in Visual Studio (and who doesn't), then you very quickly find yourself stuck with having to load dialog templates from resources compiled into the binary file.

This further means that if you want to make use of a dialog across multiple projects, then either you need to copy and paste the dialog template between project .RC files, or you need to build the dialog into a DLL from which it can be accessed.

'Runtime Dialogs' (a snappy title I coined myself) is a solution that neatly sidesteps both the nuisance of copying dialog resources between resource files and the extra work (and maintenance) involved in packaging dialogs in DLLs.

And it works like this:

First, you design your dialog template in the resource editor, create a CDialog derived class using class wizard, and wire up all the controls just as you normally would.

Next, you #include "runtimedlg.h" and change all instances of CDialog to CRuntimeDlg.

Then, you cut and paste the control definition section from the appropriate section in the .RC file and embed it directly in the dialog's .cpp file as a static string (with a bit of tweaking to handle double quotes and such like).

Finally, in the constructor of your dialog, you simply call CRuntimeDlg::AddRCControls(...) passing the control definitions as a string.

And CRuntimeDlg takes care of the rest including, if required, auto-sizing the dialog to suit the control layout.

I'm certainly not suggesting that this is a 'win-win' solution for all situations but it certainly has merits in its closer coupling of dialog template to dialog code which makes sharing dialogs across multiple projects a breeze.

P.S.: In case it's not clear here, I used CRuntimeDlg to create CToDoCtrl which encapsulates the ordered tree together with the priority, date and comments controls as a single simple-to-instantiate control.

This is possibly the most satisfying aspect of the whole project because it was completely unexpected.

What I mean is that, until recently, my knowledge of DOM and XMLDOM was virtually non-existent, as it's only since I've become more interested in the presentation of AbstractSpoon that I've been forced to get to grips with the various implementations of DOM and XMLDOM out there.

I'm pleased to say that the code on my site works under IE 6.0, Netscape 7.1, and Mozilla, although custom code was required to achieve this.

Generic MFC Classes that may prove Useful to You

The following table lists a wide range of utility classes written for this project. They can all be included in any MFC project provided you include any class dependencies too. Feel free to ask any questions relating to these specific classes and how to use them.

Adds support for recognizing urls, clicking them and setting custom url callbacks

CWinClasses

Encapsulates the ::GetClassName Win32 functions

CXmlFile, CXmlItem

Non-Unicode class for reading and writing xml files

CXmlFileEx

Adds encryption capabilities to CXmlFile

CXmlFile, IEncryption

* CSubclassWnd was originally written by Paul DiLascia for MSJ magazine. The version I use has been heavily extended to suit my specific needs. The classes that depend on it here need this extended version.

Further Work

Whilst this tool was originally intended for my personal use only, it is now a 'community' project, so if you find it useful and want to make suggestions for enhancements or bug fixes, then post below.

I researched a bit more. If you rename the icons in the Select icon-dialog or even directly in the ToDoList.ini via Notepad after closing TDL all iconames get sorted strictly alphabetically while the icons are not changing places !!

This leads to the wrong assignments and happens the moment TDL is closed. The settings in the todolist.ini and in the Select icon-dialog are congruent. What you see is what you get.

Hope this helps you Dan fixing it.

BTW. I was adding a second icon column to display informations. The column is about double size of the original iconcolumn. It should of course not be wider than an icon. Will it be possible in the future to define the width of custom columns? At the moment it looks like it the column width makes use of my settings in "Limit width of columns to..."

- custom icons which are deleted from the icons folder still are listed in the ini-file.
- the order of icons in the ToDoList.ini has nothing to do with the order shown.
- the given names get destroyed (moved to other icons) when new icons are added in the icons folder!!

I suggest that custom icons which are deleted from the icons folder should disappear in the ini-file. Added icons should appear in the ini-file and the Select Icon dialog with their original ".ico name" and at the proper alphabetical position. The already given names of "old" icons should of course not be altered.

It´s a bit tough to explain. I guess Dan you should just move some icons in/out of the folder and see what happens.

'combobox.5000' is the attribute droplist in the 'Find Tasks' dialog 'Rules' grid.

Now (6.6) that the contents of this droplist are being constructed dynamically, the second of the strings will no longer be used and instead the item will be constructed from 'Completed Date' + '(Relative).

The appearance of the German string needing translation is probably just because I forgot to turn off auto-translating of the droplist now that it's being done manually.

I'll also look into why there is no space between the elements of the manual string.

I am using ToDoList 6.5.10 with a task list so long that it takes more than one screen size (scroll bar). I am also using three different category items that I use for grouping tasks.

When setting the "Sort By" to "Unsorted" and using the Category Filter for one of the Categories, all works well. However, when selecting the other category, I only see task items from one of the main branches of my ToDoList-Tree. The list of visible items is now very short and does NOT span more than one screen size. No scroll bar is visible. Without any doubt several task entries are missing.
When I click on the Title Colum now (to select "Sort By Title"), all of a sudden the missing task items do appear.

This behavior is very repeatable with my task list on different computers also using slightly older versions of TDL.

Can you reproduce this behaviour? Do you need any additional information?

Yes, I can confirm that selecting the top item and pressing up, all the other main items scroll into place! Thank you for this workaround!

BTW: The visible main item starts with the letter "B" and is the least one in the "unsorted" list. After selecting this item and pressing the UP key, the other two main items (with their sub tasks) appear. These other main items start with the letters "P" and "S" and are now visible above the first item "B".

Regards,
Daniel

Update:
After your tip with using the Cursor keys for scrolling I just learned that actually with a lot of other filters I was not seeing all items neither (like filtering for "Allocated to" etc). Just that with these filters there were not so many tasks "invisible", so I was not aware of the issue. Actually I am now able to see if there are items missing by looking very closely at the dotted lines of the Titel tree view, because these dotted lines are often extending to the top out of the field of view. All this without any scroll bar indicating that there is more to see.

If the list is sorted by priority which may do several users and you change the priority the task automatically jumps to the new position. TDL keeps the task selected and so you automatically scroll some pages.

As you may did not want to work on this task anymore and just give him a new priority TDL could select the task above the priorized task without following the priorized one. Maybe this behaviour could be optional.

BTW renaming icons still don´t work. After closing the "Select Task Icon"-Window the new names get sorted alphabetically but not the icons which of course leads to wrong names.

I am not sure that is necessary.
The stylesheets still seems to run fine, unless it contains v2 functions, at which point it fails. There are one or two stylesheets that you distribute that have the version 2.0 header, so you wouldn't want to break them (e.g. Time_Spent_eng.xsl).

It was just confusing for me not being able to get the functions going, while it seems to accept the v2 header... Now that I know, and understand what is possible, its fine.

For what it is worth, the header contains xsl:stylesheet version="2.0" rather than xsl:stylesheet version="1.0" (amongst other things of course).
zajchap

In the Inheritable Attributes section of the options, there's the checkbox "Continue to update subtasks as parent changes". I set Category to be inheritable and then selected this option. Next, I created a task, and then created several subtasks. I then assigned a category to the parent task. In the tasklist, the category appeared in the Category column, but only for the parent task. I clicked on each subtask and saw in the edit field that the category has been assigned to them. However, the Category column was blank for those tasks in the tasklist. There was no way to cause the category to appear in the Category column, outside of closing and restarting TDL.

I think you may be right. End of year is crazier than ever.
This is in regard to a recent request that got me thinking. To do with the Sticky notes thing.
I found a great sticky note programme called 'Stickies' (freeware), which has a API that allows commands to be sent to it. I am just wondering whether an AHK script can pull out the title of the selected task and directly create a new sticky label on screen. Seems feasible.

Something I may play around with over the Christmas break, along with finishing the stylesheets I am half way through.

PS, any progress on determining the version of xsl TDL references? Can it handle xsl v2.0?

Thanks for the confirmation. It confirms what I already suspected, and saves me from further trying to work out what I'm doing wrong...
It just means that doing some things with dates in stylesheets won't be possible (as far as I know). Such as colouring tasks based on their due dates etc...

No worries.
Wasn't really intending to give you more work. I will probably still have a play if I have time.

My thought was to export the name of a task to create a sticky. Then deal with any reminders etc in the Sticky program if necessary. My main thought though was to be able to create a 'Do Today' list that can live in the corner of the screen. The AHK code I found seems to allow the serial pasting of text into a single sticky, which would allow the creation of a short list.

Thanks Jochen. I will see what is possible over Christmas, once the rush to the end of the year is over.
I was wondering whether I could do an F2 key press, then copy the resulting selected task title as an initial look-see, but that would be very ugly and would only work when a single task is selected. Other methodolgies would probably be much better.

The links on the thread you sent no longer seem to work (the ahk script anyway - the exe I can't get to at work because of IT policy). Will try at home later. Can exes be decompiled by AHK? Haven't played with that before.

[Edit]: The exe is no longer available either. You couldn't possibly email me copy of you have one could you?
zajchapp

Having just discovered that I can hide the task details pane, I like to suggest that it would be very handy to be able to edit all the task attributes that are shown in the task tree / task list directly there. As in Excel: Just click on any field in a column (e.g. Due date) and get the same editing widget as in the task details pane. Just as it works already for some attributes (task name, completed flag, flagged flag).

1. TDL is not a two-dimensional spreadsheet like Excel. The values in the 'cells' are often calculated from other tasks (eg. Earliest Due Date). This means that editing a 'cell' and pressing return could end up displaying a value other than the edited one which would be very confusing.

2. The current model better supports multiple task editing.

3. The current model supports attribute editing regardless of the 'active view' (tree/list/calendar/gantt).

4. I can add new views without having to implement 'in-place' editing which is a lot more complicated.

1. TDL is not a two-dimensional spreadsheet like Excel. The values in the 'cells' are often calculated from other tasks (eg. Earliest Due Date). This means that editing a 'cell' and pressing return could end up displaying a value other than the edited one which would be very confusing.

Well, of course it would be sufficient to allow editing the values that are not computed - just as in the details pane

.dan.g. wrote:

2. The current model better supports multiple task editing.

The inline editing should not replace the existing method, of course, so this would still be available for multi-task editing

.dan.g. wrote:

3. The current model supports attribute editing regardless of the 'active view' (tree/list/calendar/gantt).

If the inline editing is only available in tree and list view, that would make me even more happy using TDL

Quote:

4. I can add new views without having to implement 'in-place' editing which is a lot more complicated.

I can imagine that it's more commplicated. What about trying to add it only for a few selected things like dates and priority (if not computed) ...?

"Vollbild" (i.e. "full screen") suggests that the tdl window is set to full screen mode, e.g. fill the whole screen without decorations, which is not what happens.

Yes, you are right. Done in my CSV which will be sent soon to Dan.

ptandler wrote:

Or maybe use a different wording, such as "Hide task details and comment" ("Aufgabendetails und Kommentare ausblenden").

Yes, would be fine. But maybe this would be a big difference between the original text and the translations. If Dan would change it I will change it too (but he tries to avoid changes of existing strings ...)

The offset Task Dates function could be used to push the start of tasks in the future (Defering of Tasks)

To do this efficiently there should be a second checkbox like "calculate dates from today" added.

If you offset the startdate by two days which would be the day after tomorrow the task will otherwise not disappear (not be defered) if the startdate is e.g. a week old. The startdate will then just be 5 days old.

I often need to defer tasks to next monday which could maybe realized with a seperate checkbox. It would be nice if checkboxes in general would be accessable also via keyboard by ALT + Letter underlined (Start Date)