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 know it may not be convenient but IMO the best way to solve such issues is probably to only edit the translation files in GitHub. That ensures that we always see each other's changes and that I don't overwrite yours and vice versa.

To answer your question more seriously, there are 3 places the problem might occur:

1. In ToDoList.exe, which you can check by switching the language to English (no translation occurs) and viewing the About box
2. In YourLanguage.csv, which you can check on GitHub
3. In Francais (France).csv, which you can also check on GitHub

And the answer is 2., which contains two versions of that string: the correct one and the incorrect one. I'll let you edit the file to fix this and then after I get notified I will pull your changes for RC3.

Rather than saturating a single thread with a number of issues, with a subject simply "7.0RC2", etc, I propose (with Dan's approval) that all distinct issues should be posted here separately. A Subject of "7.x Issue summary" allows for finding issues much more readily for us to comment and for Dan to process.

Yes, the subject can be changed within a thread, but few people do this. And as threads start to get a little older we start to drift back a few pages in this forum UI.

Dan, as you encounter new issues and respond, might you want to tag the thread with your own TDL ID so that it's easier for you to link these discussions to your list?

The question has come up before about moving discussions from CodeProject to another more discussion-friendly environment. We can discuss that again another time. Recently[^] the question came up about discussing specific features/issues, which is more about issue tracking than general purpose discussion. Here are my thoughts on options for ToDoList.

GitHub allows for tagging Issues with a Label[^] to separate bugs from Enhancements, etc. If I were using GitHub for this I'd mirror Issues into my TDL and use the File Link to jump back to GitHub whenever progress is made. I believe Labels are assigned by managers, not those posting the Issue report.

Users contributing to such a discussion do need a GitHub login. The good news here is that individuals can Subscribe to an issue to monitor those of interest. As to asserting the popularity of a feature request, GitHub doesn't have a +1 feature. The only way to vote on a feature right now is to just put +1 into a comment which then gets emailed to all subscribers - that can be annoying.
UserVoice[^] would be ideal, but the price is prohibitive.

It is possible to extend GitHub, as seen with ZenHub[^]. That's a for-fee offering that only works with Chrome, so I wouldn't recommend it for TDL. But notice how they do Kanban.

Bitbucket.org[^] (by Atlassian) is free and does allow for voting and more features on Issues. I have a repo here and it works well.

Atlassian also offers free Jira[^] issue tracking for FOSS[^]. Also note how they do Kanban.

Personally, since we're only getting started with GitHub and already seeing limitations, I think it would be worthwhile to consider a more robust tracking environment, and right now I'm bending toward Jira as being full-featured and free.

Another option would be to host an issue tracker at Abstractspoon.com or elsewhere. I run a couple trackers like this for business clients and it works very well. I prefer the Mantis[^] tracker because it's PHP. Bugzilla is a fine standard but it's written in Perl which is rather old now and tougher to maintain.

My vote doesn't count, but personally I really dislike hosting a project as popular as ToDoList on this one page. The forum interface is primitive. Creating another article to support a different category of discussion is just buying into more of the same limitations.

Don't get me wrong, I like CodeProject, and I understand Dan's preference for staying here. But I believe the software has evolved far beyond the confines of this application. I wouldn't host an application here. I'd create a new website for it with a dedicated domain, issue tracker, downloads page, wiki, blog, etc etc. All of this can be done with AbstractSpoon if Dan is interested. I tried to do this a couple years ago but I simply ran out of time for this initiative.

LOL, no bud - I opened with that, meaning the topic has come up in months/years past. Then I led to the recent discussion.

Sure, if you just want Gantt and Kanban features to be discussed then Github would be a place to do it. As each new topic comes up people can be asked to create a new Issue. Issues can be closed if they are being discussed elsewhere. There are limited features for discussion, voting, etc, and there is no discussion threading. But to keep specific issues more concise and on-point that should be OK.

Or a Google Group can be created, for now specifically oriented toward Gantt and Kanban, where we can tag discussions with a TDL ID which you assign. This would also allow people to participate in discussions via email rather than this CP forum. People can also add images and files to a posting, discussions are threaded, and polls can be taken.

Since a lot of people have a Google account but not a Github account, the Google Group (GG) might be the easiest and most effective option. Github Issues should still be created for reference but the discussions can take place outside of that environment.

Of course the GG medium can be used for other discussions as well. The question this leads to is - after being with CP so long, isn't TDL bigger than the confines of this box now, rather than being a way of attracting new users? You can still keep this as a home for the software but with your community being distributed elsewhere like Github and Google Groups. If this page loses traffic, does it matter anymore?

If I'm able bring people back to CP just to visit this page then that is how I repay them for the free hosting and their support over the last 12 years. TDL will remain here for as long as they do.

iamstarbuck wrote:

Since a lot of people have a Google account but not a Github account, the Google Group (GG) might be the easiest and most effective option

Except that I really only want these discussions to happen between people who can be bothered to create a GitHub account. I don't want every 'man and his dog' chiming in simply because it's easy. I want people to take responsibility for what they say and suggest. Even here there are way too many 'drive-by' comments and requests that I follow up and the author never responds.

So my opinion is that we keep CP as the visible face of TDL and use GitHub for ongoing deeper, more technical debates.

I make a lot of suggestions but my ultimate goal is always to help you to do what you want with your software. So I'll be happy to help with a Issue tracker at GitHub. We can discard the other ideas.

So right now there are three repos: Old Wiki, New Wiki, and Resources for translation. I'm still thinking it would be best to have a single "ToDoList" repo for Issues, Wiki, and "sundry files" while CP remains the sole location for the source. That way we just have one link to Git and all info will be there to jump to the other pages. Or, the "ToDoList_Resources" repo can simply be re-purposed from "Repository for translating ToDoList resources" to "All resources related to ToDoList", and the translations will be just one set of files hosted there.

ToDoList_OldWiki will be deleted once the info has been moved across (which can happen fairly soon if only as 'hidden' pages).

ToDoList_Resources is only for those who are serious about getting involved. I don't want people heaping all sorts of anything into this area. These resources are packaged with the download, so I am effectively taking responsibility for them, something I don't take lightly.

New_Wiki will bring most of the traffic and most of those people I want to keep well clear of the Resources area for the reasons above.

Also, New_Wiki can easily be linked to ToDoList_Resources by a page specifically about helping translate TDL. Also, New_Wiki will have lots of its own resources (images, spell-check dictionaries, etc) that are not part of the Resource download and I think keeping the file groups apart will simplify my life when it comes to prepare a TDL update.

As I am partly responsible for starting this...
I don't have a clear idea of how this might happen, and which tools are the most suitable. As I see it, it would be useful to:
Be able to access an up to date list of features / functionality related to a given topic
- Ideally this is easily found/accessed from this forum - so new people can find
- Ideally the list of features is current, with some priority assigned, maybe by voting
- Most people can access, likely via a simple user account.
Be able to contribute to selected topics via discussion etc, along with other interested parties
- Discussion, images, video, links, etc for clarification and debate on how functionality might work
- Ideally some of these functionalities would be well clarified by the time Dan is ready to consider them.

I am however not clear how something like this will fit in with Dan's plans and work-list. It will of course remain Dan's prerogative as to when or if any feature is implemented. But it would be cool to understand which version a particular feature is penciled in for. As long as it is clear that this isn't a way to put pressure on Dan by asking him to make 'promises'.

While Codeproject has its failings, I like the fact that I can come to one place and find all the information. Maybe I am old-school but I don't really like having to monitor multiple places - time poor currently.

As an example, I am interested in the documentation initiative you are working on but a combination of limited time and it being somewhere else (Git-hub? whatever that is), has provided enough of a barrier that I haven't tried to get there.
[EDIT:] Actually, Dan has answered these last two paragraphs in another post. He doesn't want this for drive-bys etc. And this makes perfect sense. Going off to find a concrete pill...
zajchapp

I agree with your list of ideal options. However, it looks like the venue is going to be GitHub for focused discussion on specific features, and without the set of ideal forum features. Those features are desirable for a more diverse audience and general discussion but as Dan describes his intent I believe we can do without such fluff.

I understand the issue of time limits but as a technologist I need to learn about stuff like this whenever possible. This has forced me to compare sites like GitHub, BitBucket, CodePlex, and SourceForge. I compare content management systems like Drupal, Joomla, and WordPress. I compare forums like SimpleMachines, phpBB, Google Groups, and GooglePlus. I compare languages like Java, C#, and PHP. Etc etc. So I understand that all of this stuff is confusing if you're not into it.

Let's summarize:
GitHub and the others are a place for developers to post open source code. Each developer can create one or more repositories (repo) to support their software. Each repo gets an Issue tracker, a file space for downloads, and a wiki for documentation. Beyond that it's just a matter of features. People compare the issue tracker here with the one there. CodePlex has a Discussion area but GitHub doesn't. BitBucket supports different kinds of repos (like Mercurial) which GitHub does not. GitHub is a Very popular site for hosting software, so it's common to want to host a project there, even though they don't have a forum. So to make up for that, some project owners use Google Groups to fill in that blank. And because the Issue tracker is rather basic at GitHub, I propose Jira or Mantis as an alternative. The idea is to use best-of-class resources to create an overall solution.

If that seems like a lot of sites, but we're talking about just a few basic functions. The solution to the chaos is just to have a little dropdown set of links in your browser for ToDoList: Download, Issues, Wiki, and Discussion, and each resource would link to the others. That's not tough.

Now, in Dan's most recent note he's expressed preference for using the GitHub Issue tracker specifically for discussion of just a few features. So that's what we'll do. You should have a link to this page for Download/Discussion as always, one to Github for Issues, and one to the wiki. The wiki are still in flux, but right now the pages are here[^].

Where it was originally reported I suggested that this might be considered a feature. Since it's there, if the path can be removed from the grid via the attribute selector, then the text "List View Only" can simply be removed and the path becomes just another optional column.

Hi,
The Path (List View Only) was created on my request.
The reason was that in tree view, it is easy to see the tree structure and the list of ancestors of a given task.
In List view, only the path of current task was displayed in header of title column.
There was no easy way to see ancestors path, list wide. That it is the reason Path was created.

The reason to remove the "path in tree view" feature is that it is useless.

Patrice

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