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.

Hi all,
In order to facilitate contributions to documentation and translations, Dan have kindly setup a GitHub account with the resources of ToDoList https://github.com/abstractspoon/todolist[^]
To contribute, you need a GitHub account, fork the repository and submit you contribution to Dan approval when done.

So Dan, is this really how you'd like to see contributions to documentation? I'm a prolific writer, but I'm not fond of the AbstractSpoon wiki. So I'd feel right at home building a TDL wiki at Github. The fact that it's common Markdown makes it portable anywhere, including (pretty please) perhaps a MediaWiki at some point in the future.

If this Github wiki is the place for docs then I'll get cranking and will be happy to coordinate/integrate with anyone else who wants to work on this.

So Dan, is this really how you'd like to see contributions to documentation? I'm a prolific writer, but I'm not fond of the AbstractSpoon wiki. So I'd feel right at home building a TDL wiki at Github. The fact that it's common Markdown makes it portable anywhere, including (pretty please) perhaps a MediaWiki at some point in the future.

For GitHub account, it id how it is set actually, I guess the settings can evolve as things get on rail.

iamstarbuck wrote:

If this Github wiki is the place for docs then I'll get cranking and will be happy to coordinate/integrate with anyone else who wants to work on this.

I think things are open, and the one that will get something started will have the choice of the form it will take since he will be the one that get its hands dirty.
My thought was to do a call to communality. Imo, the main problem of TDL is that documentation is almost non existent and need to be created, whatever the format is, When documentation exist, switching from one format to another, depending on the particular use, should not be a problem.

Patrice

“Everything should be made as simple as possible, but no simpler.” Albert Einstein

So with reference back to prior discussions, it's easy to call others to action but who else here is interested in Writing docs? I mean, it's always easy to suggest that someone else should consume their time for our benefit, with no reward other than an occasional thanks. But I'm hoping to find people who really want to collaborate on docs.

That's not to say I don't want to take a shot at it. I will, gladly. And I hope people will like it, and will change or propose changes when they don't.

But other than a public call for someone else to write documentation for us, I'm wondering if anything has changed here. I'm just trying to keep the spirit of FOSS alive here...

I mean, it's always easy to suggest that someone else should consume their time for our benefit, with no reward other than an occasional thanks.

My only reward for my contribution to French translation is my name in About. But I guess you have only little interests in French TDL
I also contribute on a regular basis with Errors reports, Ideas to improve TDL usage (a few of them are in TDL)

iamstarbuck wrote:

So with reference back to prior discussions, it's easy to call others to action but who else here is interested in Writing docs?

The reasons why I didn't start it myself is a few handicaps:
- English is not my mother language.
- Never writed in English for things really longer than theses messages.
- I have never build a Wiki or a .CHM , I have no expertise with theses things.

I was hoping that someone more skilled than me would get things started.

I think that when we will have a "User Guide" in English, the French translation (task) will end up in my hands and this imply learning a translation software.

Patrice

“Everything should be made as simple as possible, but no simpler.” Albert Einstein

I just noticed that Import tasks for GanttProject doesn't seem to be working in v7. Works fine in v6.9.
I select the file to import, specify that TDL should create a new file, but nothing happens on pressing 'Import'.

Import from freemind works fine.

PS: I need to do this for fitting in with other people's tools - I am going to try to convince them to use TDL for their Gantt chart...

Good point. Although in this case, I am trying to get them to create a high level Gantt, so using a screenshot shouldn't be an issue (i.e. the Gantt shouldn't run off the page).

To provide some context. For managing some smaller projects in my team, I do the brainstorming in Freeplane (a Freemind fork), and Gantt charting in GanttProject (because that is the software the others have available currently). I use TDL to transfer the information between the two applications. I also do some editing in TDL, as it is easier there for some operations than in GanttProject. This is usually a one way transition, but at times I re-open the Ganttproject file in TDL.
I have been using the Gantt charting in TDL for work that doesn't require team input.
Now that the Gantt chart in TDL is at the stage it is, I am strongly considering getting the others to take up TDL. There is the issue of our IT department though...
zajchapp

I am not sure you need one. As long as there is a way to pull in data from Freemind/Freeplane, this works well enough. Mind mapping is an infrequent thing for me, and tends to be done at the start of a project. Some of the other features are probably more important in my opinion. For example, a Kanban view would be more useful to me, as it will enable a different way of managing tasks day to day.

I am also not sure I can think of the absolute essential features. The fundamentals of mind-maps are relatively straight forward, although many applications try to expand the features to allow for other uses, such as task lists etc... I can't think of any functionality that a mind map needs that TDL doesn't already have (other than perhaps being able to represent attributes as icons)

Essentially the data structures of a mind map and an outline/tdl file are near enough the same as I understand it. One is a spatial diagram, the other a list. These different representations of the data promote different thinking modes. The challenge is one of representing the data.
So (if it isn't too general), a mind mapping module in my opinion needs to allow free dragging around and rearranging of tasks. The regular TDL functions such as collapsible nodes, filtering, etc should be available. Specifying which attributes are visible/represented would be nice (e.g. an icon for 'this node has a comment'). Although this last might not be so important if you can just flick between views. One of the real pains in some mind-mapping software is the way attributes are handled - this would be a snap in TDL.

At the risk of wittering on, he is an expansion of how I typically use mindmaps.
As stated, mind mapping is a visual way of representing ideas, highlighting relationships in a spatial way. It encourages me to think in a freer, less structured, more creative, associative way. It allows for non-task items to be added - notes and comments, intentions and outcomes, risks and benefits etc...
I then move this into TDL, to create a structured list. I move into a different, more structured mode of thinking (tasks & scheduling). I find a list is better for this than the mind map. This is focused on the actual tasks to do, the order in which they are done, who does them, and when. The final list / Gantt content is often different to that in the initial mind map. The projects are then run off the tasklist/Gantt, and other documents.

I have 2 main uses for the mind map:
1: Starting a project. Initial brainstorming and planning. I will keep the mind map, but am unlikely to refer to it much during the project, if at all.

2: Managing my portfolio. The mind map is useful here, as it is an easy way of seeing all the active and inactive projects, and their current status (there is no project detail in here). This is kept up to date on a monthly basis. It would be very useful to have this in TDL, as the mindmap and tasklist would be the same.

Whenever I see mention of "it would be nice to integrate ToDoList with Foo", I do a Google like ".NET API Foo". In the case of ".net api mind map" there are a wealth of tools. Similarly for Kanban, Gantt, and other complex features requested here.

This is where I come to the idea that if you are using ToDoList for business, then all of these other extensions can be obtained rather quickly, if your business is willing to spend money rather than time. If you have time, you can wait for Dan to implement some of these integrations, but you could wait for years, and it may never come up high on his priority list.

So for any of these requests, just note, you can get what you want, and fairly soon, but you won't get it for free. If you want free, do it yourself, or wait.

Please note, this is a general comment, not intended toward any individual or any specific request, and is not intended to be critical of anyone. I'm only advising users of ToDoList (and any other FOSS) that there are other options to achieve their goals, when the most common option, and usually accepted as the only one, is to ask Dan for a feature and then hope. And of course this is entirely from me as an individual, completely unrelated to Dan, and without any discussion with him.

Whenever I discuss options like this with clients, I refer to the Good/Fast/Cheap triangle[^]. Eventually all I need to do is to hold my hands into a triangle and they know I'm asking if they want their solution Good, Fast, or Cheap. Same applies here.

Agreed.
In my case, I am happy to wait, as TDL provides a function within an ecosystem of tools. Some functions are smoother/less effort if they are integrated with TDL (like Gantt or day to day task management activities), others it really doesn't matter so much. As mentioned, I have a system that works well enough for me in relation to mind-mapping.
At the end of the day, it all depends on what Dan wants TDL to be.

FWIW, I am an individual using TDL to help my work. TDL is not supported by the business I work for.

wait for Dan to implement some of these integrations, but you could wait for years

That is indeed the case.

However as the core app continues to mature and I modify it less and less, my time will instead be directed towards writing new 'View' plugins. And as the Kanban demo shows I can prototype these quite quickly in C++.

However, perhaps the mind map plugin can be the first C# plugin for which I provide the C++/CLI framework and you provide the implementation. Then, if you want, you can see whether there is a saleable market for it...

Mind mapping has been mentioned in the past but the question is about how many people actually know what it is and would want to use it. I've suffered from a delusion of "build it and they will come", where very cool products were created and then suddenly met very limited demand, only to be shelved. If I write a mind map interface or any other, we'll need to establish a real desire for the feature. I know from experience that this can be difficult too. Most people won't tell you what they want, they often don't know, but once something exists they may find they can't live without it. That leads to the "build it and they will come" theory. It's tough to know...

Yeah, this or anything like this would give us a good target to prototype the .NET plugin integration. I'd enjoy providing this as a more complex example of what we can do with FOSS.

That's a good attitude. In my professional industry people are always asking for specific things that should never be built into the core.

What I'm hoping to see here are more ideas for things that we can do with TDL "if only we had the ability to connect TDL data to ...". This gives Dan ideas (where he could as easily say 'yeah, I actually want to add that') and it helps me to ascertain what demand might be for a feature that will never make it into the core.

So don't let your perception of what's possible limit what you post here. An idea isn't necessarily a request - it doesn't put pressure on anyone to deliver, but a good idea can really bring out something that many of us would like to see.

And what about managing the Check-in/out in a separate file named MyTaskList.check.tdl ?

- Simply Checking the TaskList don't change time stamp.
- The Check file is ridiculously small and fast to update.
- the same Check file is used to secure the Archive.
- Checking your TaskList is instantaneous for the user, no GUI stuck for 2 seconds on network.
- The file can even be a constant that don't need to call all the XML stuff tobe generated.

The contain of the Check file is a simgle element with a single attribute:

<TODOLISTCHECKEDOUTTO="PATRICE-PC"></TODOLIST>

Or simply:

<TODOLISTCHECKEDOUTTO="PATRICE-PC"/>

I thought about it after the discussion about the unarchive function.

Still conflicting ?

Patrice

“Everything should be made as simple as possible, but no simpler.” Albert Einstein

Saving UI state/preferences to the tasklist will require the tasklist to be saved (and checked-out) every time these change. eg. every time you save the filter when the tasklist is unedited you will be required to also save the tasklist.

More precision is needed.
When I create a Tasklist, columns visibility and usage are the personality of the TaskList.
My first move is to want colleagues on network to see the same layout.

Layout:
- What about the possibility of a main layout recorded with the TaskList and a user's layout recorded locally ? With a button allowing to save actual layout as the new main layout with the TaskList, and a button allowing to switch between main and local layout. And when you play, nothing goes to the TaskList until you request it.

Filter;
-I see filters as local play to feed a user's ponctual needs. So if user don't take the pain to name a given filter and request a saving on the TaskList, it stay local.

Cursor
- I see the cursor position as user related and don't have to be recorded in the TaskList.

- -Z
I appreciate the -Z option because it is neat to have the TaskList opening the first with the right layout already. You can make it the default.

Patrice

“Everything should be made as simple as possible, but no simpler.” Albert Einstein

- remove the confusing Default columns visibility in preference.
It took me months to understand how to have a different layout per Tasklist.
and it never occured to me that the default layout was the one I needed when creating a new TaskList.

Patrice

“Everything should be made as simple as possible, but no simpler.” Albert Einstein

Hello,Dan.
I shared a todolist.xml to 10 members in my project through multiple users function.
the original data file (xml) was saved on my local PC(for example PC1),one of our members
used windows mapping remote network driver as local driver to access this xml file on his
computer(for example PC2).
when he open the xml file on PC2 ,it found that the original xml file which saved on PC1 was missed.
I think it is a serious bug,could you confirm it? thanks.

Thanks ppolymorphe.
I want to say the user has different operating,he mapping my shared xml file as his local network driver to use,the other people access the xml file from todlist file\open tasklist directly as \\172.24.4.110\shared\todolist.xml,they all got the right result.

We have a similar problem. We store our list file on a network drive and open it through ToDoList. Several times a week the TDL file will disappear from the network drive. When this happens the user that checked it out last has to do a "Save Tasklist As", save as a different filename then save as the original name before anyone else can check it out again. We get an error message if we try to save as the original name first(I'll post which message when it happens again).