So after basking in the turkey afterglow, what does any self-respecting programmer do?
He takes a nap.
What does he do after that though?
He gets soused on eggnog, with real nog in it.
But after that?
Well, dear reader, I took it upon myself to write a Tree View control in C# (.NET framework 2.0) from scratch.
A little proof... here it is in all its glory... well, how it stands right now anyway... Not that impressive looking, to be honest, but it's mine - all mine!
Now, you may be thinking to yourself... why on earth would he go ahead and do that? There's a perfectly good TreeView control right there! In the framework!
Well, there's a damn good reason for this. I like reinventing the wheel. No! Er... I mean, the existing TreeView control doesn't support a few things I needed.
What can't the existing control do?
- Variable size items
I needed a way to custom draw items which might or might not be more than one line of text high.
- Sub-item handling
I needed a way to implement sub-items within an item, while retaining proper focus handling. Which means I need to be able to pass all of the selection handling and keyboard focus traversal to the nodes themselves when rendered.
Somewhat like OneNote, I needed a way of adding flags to the left of items in the TreeView.
- Windowless Controls
I needed a way to implement this control so that it could be embedded within another control without a lot of heartache. For example, I want to be able to paint three trees in a row, while only having one scrollbar.
I also looked at using a ListView control for this, but unfortunately, that would only get me part of the way there.
(Some of you may be wondering why I didn't do it using the new Windows Foundation framework... yes, I agree, it would most likely be much easier. However, unfortunately, it won't install on my laptop until I lobotomize it [thank you, beta software]).
What I Ended Up With
So this is version 1 of my ComplexTreeControl, which frankly isn't architected in entirely the best manner, but should be pretty easily refactorable as I go on.
What do I have implemented so far?
- OneNote style flags to the left of the expand/collapse node.
- Full keyboard traversal of the tree (with the correct behavior), including Home and End keys.
- Context menus with Default menu item support, and auto-insertion of Collapse/Expand if it's a node with children.
- Variable height nodes.
- Rendered layout information separated from the node structure. (Basically, it builds a list of nodes with indent information by iterating over the tree).
- Selection of a single node based on the current location of keyboard focus.
- Tree Collapse/Expand icons stored in a resource on the control itself. All other icons come from a custom image list that can be set by the user.
It's not yet windowless, and the painting logic for nodes still leaves a lot to be desired (mainly because I need to pass around not only the clip rect, but the client rect, and the item rect as well).
- Implement Focus handling correctly. (Right now, I'm missing a piece of that puzzle, and the control doesn't end up with focus).
- Windowless painting & layout.
- DPI awareness (mainly so that I can print out the tree).
- Line-buttons (buttons which appear to the left or right of the item, for use in a visual merge app; kind of like the ones you get in Araxis Merge).
- SubItem focus traversal. (Not too hard to do - just need to pass handling of it through to the underlying node).
- Rendering info caching. (I should at least cache the extents of the visible items)
- Scrolling (yeah, I know, it's not exactly a big one... shouldn't be too hard though... the trick will be doing it in a way that I can still make the control windowless when I need to).
Of course, if I do my homework right, I should be able to wrap this all up in a rather nice bow and have it available for sale to interested parties. :-D
It's interesting coming back to writing .NET C# UI controls for the first time in, oh, I dunno, nearly 10 years since I worked on the .NET framework back in 1998. Its gotten easier. I've learned a lot since then.
Oh yeah... why am I doing this?
Well, frankly, I'm sick of having to handle Visual C++ project merges by hand. Sure, Visual Studio Team Server might have all kinds of wonderful support for this, but at work we're using VC++ 2005 Pro with Perforce, so we don't get that useful tool.
And merging project files - actually, merging any kind of XML - is a pain in the ass. Sure, I could use the XML Diff Patch tool that Microsoft has on their site, but that just gives me a hard to read DiffGram, and besides, I'd want a UI on the top of it anyway. (I like UI's ... they make life easier).
So screw that for a game of soldiers. I'm writing my own damn merge tool. It's going to be at least a Tree based view of the project, and I'll probably turn it into a generic VC++ 2005 project file editor. With support for solutions. Etc etc.
And its current title? VC Project Magic.
Unfortunately, it's not going to be finished in time for me to get out of merging one last set of 4 project files by hand. Grrrrrr. (more...)