A Windows Forms control that can visualize flat or hierarchical data as a treemap. Designed to be an easy to use, pseudo drop-in replacement for System.Windows.Forms.TreeView.
So, what can cmdwtf.Treemap look like?
demo.mp4
This is in a very 'new' state. There's bound to be tons of rough edges, bugs, or other issues. Feel free to open an issue or PR if you find anything.
- Keep API as close to System.Windows.Forms.TreeView & System.Windows.Forms.TreeNode as possible.
- Be effectively usable with minimal configuration and code.
- Provide an alternative to the commercial controls available, while still being feature rich.
I've long been impressed with the ability for tools like WinDirStat to easily and effectively show off the relative sizes of files in an immediately understandable and consumable way. However, the options for Treemap controls in Windows Forms came in two flavors: Those in expensive commercial control packs, or nonexistant. Searching around and coming across libraries like JIT and some helpful posts on StackOverflow, I decided to be what I wanted to see.
The WinForms TreeView has an interface close enough to what I'd consider acceptable as an API for a Treemap. I decided to model cmdwtf.Treemap after the TreeView, trying to mimic the API as closely as possible so that cmdwtf.Treemap could be a near drop-in replacement for TreeView.
This is not an exhaustive list of differences, but noted here are some of the larger intentional or unavoidable differences in which the TreemapView
differs from System.Windows.Forms.TreeView
. These are subject to change as design goals change or features are added or removed.
ShowPlusMinus
is false by default, because collapsing is odd forTreemapView
s. Though it is still somewhat supported for now.ShowLines
is marked obsolete. It has been re-routed to affect the newShowGrid
property, which it will warn you to use instead.LineColor
is marked obsolete. It has been re-routed to affect the newGridColor
property, which it will warn you to use instead.FullRowSelect
is marked obsolete. It has been re-routed to affect the newFullBranchSelect
property, which it will warn you to use instead.- This is a considerable departure from the behavior of
TreeView.FullRowSelect
. On theTreeView
, this would cause the entire horizontal area from a node, extending to both sides of the control, to be selected when a node was selected. If it was false, it would just show the actual node content as selected. ForTreemapView
, this behavior is instead to show decendant nodes of a selected node as selected, so that the entire 'branch' shows as selected. This doesn't affect the underlyingSelectedNode
property, but just effects the way the control is drawn.
- This is a considerable departure from the behavior of
Scrollable
is unsupported, and will always returnfalse
. ATreemapView
doesn't make sense to scroll like aTreeView
does.- If you need to have a larger than visible area
TreemapView
, you should be able to place it on a scrollable parent.
- If you need to have a larger than visible area
ItemHeight
is unsupported, and will always return0
. Since nodes in aTreemapView
are by design not uniform, having a setting that effects their height doesn't make sense.ShowRootLines
is unsupported, and will always returnfalse
. ATreemapView
doesn't have any concept of root lines.- The node's
FromHandle()
function isn't supported. There's no native representation of aTreemapNode
, so there's nothing to get from a handle. TreemapNode
does not implementISerializable
. I just haven't had a need for this, so it hasn't got done.- Arrow keys do not currently navigate the view. This is on the short list of things to implement.
cmdwtf.Treemap is licensed under the Zero-Clause BSD License (SPDX-License-Identifier: 0BSD). If you're interested in cmdwtf.Treemap under other terms, please contact the authors. cmdwtf.Treemap makes use of several open source packages. Those packages are each covered by their own copyrights and licenses, which are available via the tooling you use to restore the packages when building. As well, some portions of code are distributed under terms of other licenses, which are designated in comments. See copyright
for more details.
Copyright Β© 2021 Chris March Dailey
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
The Example application is licensed under the Zero-Clause BSD License (SPDX-License-Identifier: 0BSD).
cmdwtf.Treemap makes use of several licensed portions of code, each licensed under their own terms by their authors. In particular, some of those software licenses require the following notices. The packages themselves may reference other packages, each covered by their own license.
- Portions of the code are from or based on the work of the .NET Foundation. Those portions are marked as such in the source via comments. They are licensed under the MIT license.
- Copyright (c) .NET Foundation and Contributors
- NuGet package: cmdwtf.Toolkit.WinForms β GPL-3.0-only β Copyright Β© 2021 Chris Marc Dailey
- NuGet package: Lazy.Fody β MIT β Copyright (c) 2018 tom-englert
- NuGet package: MethodDecorator.Fody β MIT β Copyright (c) Contributors
- NuGet package: Microsoft.SourceLink.Git β MIT β Copyright (c) .NET Foundation and Contributors
- Icon: Treemap by Sam Smith from the Noun Project
Sample data in the Example application reproduced from JIT, under the MIT license.
- Unit Tests (!)
- Description attributes for designer info.
- Other Treemap algorithms besides Squarified (see also: Strip and SliceAndDice from JIT.)
- Handling of the
Control.Disabled
property. - Editing -
TreeView
optionally lets the user edit a label. It seems less useful for a control like this, but I do want to implement it for completeness anyways. - Dragging - Dragging nodes to other controls is likely a desireable feature. Dragging within the treemap itself doesn't make a to of sense, I don't think.
- Keyboard Input (Spacebar toggles check state, but arrow keys aren't implemented yet.)
- Automatic coloring of sorts. I'd like to have at least a mode where a color scale can be specified and nodes will automatically color themselves from smallest to largest as a gradient along that scale. Or perhaps a 'by type' automatic coloring, similar to how WinDirStat colors by file type.
- ???
This control isn't perfect by any means. What I've listed here are some of the things about the current implemetion's design bothers me. These aren't specific to affecting performance or anything such as that, just more akin to code architecture and behavior that I'm not completely satisfied with.
- Rendering look. I wanted to strike a balance between something that felt WinForms native, as well as well as being powerful and customizable. I'm not quite sure that I hit the mark there yet.
- Rendering performance. Drawing in GDI+ is a bit of a fool's erand as it is, but I definitely took a "get it workng" approach. There is likely a large amount of optimization that could be done here.
TreemapRenderer
orginazation. Specifically the tight coupling to the actualTreemapNode
drawing and layout, and how theTreemapNode
depends on specific parts of data that get calculated during rendering (due to DPI awareness) and the sort.- As well, the drawing functions themselves are messy and a bit unwieldy, especially with all the local variables at the top of each.
- Collapsing. I'm not sure it even really makes sense, but I included it because
TreeView
s collapse. Perhaps it's something that should go because it doesn't make sense at all in a Treemap. TreemapNode
's relationship withTreemapView
. The WinFormsTreeView
andTreeNode
are pretty tightly coupled, so I don't have an issue with that. However, becauseTreeView
is a managed interface for what is a control that lives mostly incomctl32
, the way the managed components interact is highly dependant on allowing the windows message pump to do the lifting for them.TreemapView
uses some of the similar concepts (see the functions that are MIT licensed from the WinForms source inTreeView.cs
), but has to handle some of it differently due to things likeTreemapNode
being entirely managed. I'm not sure if there's a real solution to cleaning up the coupling, but it's something I'd like to explore.- Documentation. I did a lot of reproduction from the comments from the
TreeView
andTreeNode
classes to try and keep them feeling the same, but there is a long way to go in order to generate truly usable documentation. - Naming. Several things have a mix of names that I never quite nailed down for consistancy. Such as: a node referring to itself as a branch or header. If something is called drawing or rendering. Referring to the checkbox or the
state
. These are all referring to the same bits respectively, but I missed instances where I'm still using one name or another. Sometimes because I could not decide which term to use, and other times because I failed to update them when switching names in some places (especially in comments.)
Things listed here are bits that I've implemented or started to implement, but haven't fully explored the designs to see if they work in a logical or proper way. They likely have bugs.
TopNode
- Owner Drawing
- Node traversal (
PrevNode
,NextNode
, etc.) - Collapsing
- RightToLeft
- Node serialization
- Node creation/editing via designer.