wxTreeCtrl with checkboxes

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

wxTreeCtrl with checkboxes

Post by New Pagodi »

Have you ever wanted a tree control with check boxes?

Probably not, but I recently needed to use many check boxes that had an obvious hierarchical structure. And so I decided to derive a class from wxTreeCtrl and use the tree control's state icons and a profusion of hittests to simulate check boxes. I decided to dump the code here in case anyone else would find it useful.

Image

I know that wxTreeListCtrl supports check boxes, but I didn't quite like that implementation because 1) the check boxes aren't as responsive as I'd like. I sometimes need to click a box twice to get it to check or uncheck. 2) I didn't want clicking a check box to select the corresponding tree item. And 3) in wxTreeListCtrl, it seems either every node has check boxes or none do. I wanted the ability to mix nodes with and without check boxes.

Description
The class has all of wxTreeCtrl methods and 5 extra methods:

bool EnableCheckBox(const wxTreeItemId &item, bool enable = true );
bool DisableCheckBox(const wxTreeItemId &item);
void Check(const wxTreeItemId &item,bool state=true);
void Uncheck(const wxTreeItemId &item);
void MakeCheckable(const wxTreeItemId &item,bool state=false);

Basically, to make a node have a check box, you call MakeCheckable on the node's ids. You can then use the other 4 functions to check, uncheck, enable, or disable the box respectivly.

Events
The class emits 2 kinds of wxTreeEvents:

1)wxEVT_CHECKTREE_CHOICE: these events are generated when a box is checked or unchecked. In an event handler, GetItem() will return the tree item to which the check box belongs. And GetExtraLong() will return 0 if the box is currently unchecked and 1 if it is checked. (I couldn't figure out how to set value returned by the events IsChecked() method.)

2) wxEVT_CHECKTREE_FOCUS: as I mentioned above, I didn't want checking a box to result in the corresponding tree item to be focused. Instead I wanted the tree's items to only be focusable due to keyboard navigation. This left a slight problem: if you're navigating the applications form with the tab keys, when the you reach the tree control, there is no indication that it has focus until you start navigating the tree's nodes with the up and down arrows. I decided that when the tree receives focus from the keyboard, this event will be thrown so that if the application wants to do anything to indicate that the tree has focus, it can. The sample included in the zip has an example.
Attachments
checktree.zip
Source code and sample application for the wxCheckTree class.
(11.46 KiB) Downloaded 683 times
Nunki
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 235
Joined: Fri Sep 14, 2012 8:26 am
Location: Kontich, Belgium
Contact:

Re: wxTreeCtrl with checkboxes

Post by Nunki »

Hi, I tried to add the h and cpp to my project but I get compiler errors. I'm using Microsoft Visual Studio Express 2010 and declared the WXUSINGDLL preprocessor definition. The errors that show up are:

k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(12): warning C4273: 'wxEVT_CHECKTREE_FOCUS' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(84) : see previous definition of 'wxEVT_CHECKTREE_FOCUS'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(13): warning C4273: 'wxEVT_CHECKTREE_CHOICE' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(83) : see previous definition of 'wxEVT_CHECKTREE_CHOICE'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(83): warning C4273: 'wxCheckTree::wxCheckTree' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(19) : see previous definition of '{ctor}'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(88): error C2148: total size of array must not exceed 0x7fffffff bytes
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(88): error C2512: 'wxIcon' : no appropriate default constructor available
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(89): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(89): error C2440: '<function-style-cast>' : cannot convert from 'char *[35]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(90): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(90): error C2440: '<function-style-cast>' : cannot convert from 'char *[40]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(91): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(91): error C2440: '<function-style-cast>' : cannot convert from 'char *[35]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(92): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(92): error C2440: '<function-style-cast>' : cannot convert from 'char *[19]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(93): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(93): error C2440: '<function-style-cast>' : cannot convert from 'char *[36]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(94): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(94): error C2440: '<function-style-cast>' : cannot convert from 'char *[68]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(95): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(95): error C2440: '<function-style-cast>' : cannot convert from 'char *[42]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(96): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(96): error C2440: '<function-style-cast>' : cannot convert from 'char *[19]' to 'wxIcon'
1> Source or target has incomplete type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(98): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(98): error C2027: use of undefined type 'wxIcon'
1> k:\dbs1.7\wx300\include\wx\gdicmn.h(34) : see declaration of 'wxIcon'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(98): error C2228: left of '.GetWidth' must have class/struct/union
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(99): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(99): error C2027: use of undefined type 'wxIcon'
1> k:\dbs1.7\wx300\include\wx\gdicmn.h(34) : see declaration of 'wxIcon'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(99): error C2228: left of '.GetHeight' must have class/struct/union
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(102): error C2514: 'wxImageList' : class has no constructors
1> k:\dbs1.7\wx300\include\wx\treectrl.h(26) : see declaration of 'wxImageList'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(104): error C2070: 'wxIcon [8]': illegal sizeof operand
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(104): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(104): error C2027: use of undefined type 'wxIcon'
1> k:\dbs1.7\wx300\include\wx\gdicmn.h(34) : see declaration of 'wxIcon'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(105): error C2027: use of undefined type 'wxImageList'
1> k:\dbs1.7\wx300\include\wx\treectrl.h(26) : see declaration of 'wxImageList'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(105): error C2227: left of '->Add' must point to class/struct/union/generic type
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(105): error C2036: 'wxIcon *' : unknown size
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(128): warning C4273: 'wxCheckTree::~wxCheckTree' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(22) : see previous definition of '{dtor}'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(133): warning C4273: 'wxCheckTree::SetItemTextColour' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(26) : see previous definition of 'SetItemTextColour'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(149): warning C4273: 'wxCheckTree::EnableCheckBox' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(29) : see previous definition of 'EnableCheckBox'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(209): warning C4273: 'wxCheckTree::DisableCheckBox' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(30) : see previous definition of 'DisableCheckBox'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(214): warning C4273: 'wxCheckTree::MakeCheckable' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(33) : see previous definition of 'MakeCheckable'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(227): warning C4273: 'wxCheckTree::Check' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(31) : see previous definition of 'Check'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(248): warning C4273: 'wxCheckTree::Uncheck' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(32) : see previous definition of 'Uncheck'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(253): warning C4273: 'wxCheckTree::On_Tree_Sel_Changed' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(49) : see previous definition of 'On_Tree_Sel_Changed'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(265): warning C4273: 'wxCheckTree::On_Char' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(51) : see previous definition of 'On_Char'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(279): warning C4273: 'wxCheckTree::On_KeyDown' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(52) : see previous definition of 'On_KeyDown'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(289): warning C4273: 'wxCheckTree::On_KeyUp' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(53) : see previous definition of 'On_KeyUp'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(307): warning C4273: 'wxCheckTree::On_Mouse_Enter_Tree' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(55) : see previous definition of 'On_Mouse_Enter_Tree'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(315): warning C4273: 'wxCheckTree::On_Mouse_Leave_Tree' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(56) : see previous definition of 'On_Mouse_Leave_Tree'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(323): warning C4273: 'wxCheckTree::On_Left_DClick' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(57) : see previous definition of 'On_Left_DClick'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(340): warning C4273: 'wxCheckTree::On_Left_Down' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(58) : see previous definition of 'On_Left_Down'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(353): warning C4273: 'wxCheckTree::On_Left_Up' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(59) : see previous definition of 'On_Left_Up'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(418): warning C4273: 'wxCheckTree::On_Mouse_Motion' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(60) : see previous definition of 'On_Mouse_Motion'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(497): warning C4273: 'wxCheckTree::On_Mouse_Wheel' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(61) : see previous definition of 'On_Mouse_Wheel'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(502): warning C4273: 'wxCheckTree::On_Tree_Focus_Set' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(63) : see previous definition of 'On_Tree_Focus_Set'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(511): warning C4273: 'wxCheckTree::On_Tree_Focus_Lost' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(64) : see previous definition of 'On_Tree_Focus_Lost'
1>k:\dbs1.7\wxcheckboxtree\src\checktree.cpp(518): warning C4273: 'wxCheckTree::SetFocusFromKbd' : inconsistent dll linkage
1> k:\dbs1.7\wxcheckboxtree\src\checktree.h(25) : see previous definition of 'SetFocusFromKbd'

Hope you have a clear view on what's going wrong ?

Thanks,
Nunki
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: wxTreeCtrl with checkboxes

Post by New Pagodi »

When I made the zip, I was thinking the way to use it would be to compile the checktree.cpp as a library, and then that library could be linked in to use the check tree. I'm not sure why I considered such a convoluted process a good idea when there is only 1 file involved.

If you just want to include the source, in checktree.h change lines 7-14 from:

Code: Select all

#ifdef WXMAKINGDLL_CHECKTREE
    #define WXDLLIMPEXP_CHECKTREE WXEXPORT
#elif defined(WXUSINGDLL)
    #define WXDLLIMPEXP_CHECKTREE WXIMPORT
#else // not making nor using DLL
    #define WXDLLIMPEXP_CHECKTREE
#endif
to:

Code: Select all

// dll export macros
#ifdef WXMAKINGDLL_CHECKTREE
    #define WXDLLIMPEXP_CHECKTREE WXEXPORT
#elif defined(WXUSING_CHECKTREE_SOURCE)
    #define WXDLLIMPEXP_CHECKTREE
#elif defined(WXUSINGDLL)
    #define WXDLLIMPEXP_CHECKTREE WXIMPORT
#else // not making nor using DLL
    #define WXDLLIMPEXP_CHECKTREE
#endif
and then add WXUSING_CHECKTREE_SOURCE to your preprocessor definitions.

Alternately you could just change them to:

Code: Select all

#define WXDLLIMPEXP_CHECKTREE
This will not need any extra compiler defines.

On an unrelated note, it looks like in checktree.cpp, it's necessary to add:

Code: Select all

#include <wx/icon.h>
#include <wx/imaglist.h>
I think when I originally made the files, my IDE was inadvertently including those with a precompiled header. I probably should have tested things a little better before posting.
Nunki
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 235
Joined: Fri Sep 14, 2012 8:26 am
Location: Kontich, Belgium
Contact:

Re: wxTreeCtrl with checkboxes

Post by Nunki »

Hi,

I managed to compile the checktree source into my project, thanks for that but now I run into some runtime error. The fact is that I'm using XRC files instead of the' big' create method way of DialogBlocks. So I managed to state in DB to use a subclass wxCheckTree. As far as I can see is that it stops on line 172:
std::map<wxTreeItemId,wxColor>::iterator it=m_colors.find(item);
with a NULL pointer I guess (0xccccccccc)
So I think that the constructor of wxCheckTree does something more - like allocating the m_colors ??

What would you suggest me to do ?
I can either not add a wxTreeCtrl to XRC with subclass wxCheckTree but only a wxPanel, on which I will add with new wxCheckTree the actual one - which less prefer.
Or is there a way to make this work ?
btw I did read something about sublasses and xrc to work it has to comply to the wxWidgets RTTI mechanism. Not sure what that means ?

regards,
Nunki
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxTreeCtrl with checkboxes

Post by DavidHart »

Hi,
btw I did read something about sublasses and xrc to work it has to comply to the wxWidgets RTTI mechanism. Not sure what that means ?
See the subclassing section of the XRC overview for the details.

Regards,

David
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: wxTreeCtrl with checkboxes

Post by New Pagodi »

DavidHart wrote:Hi,
btw I did read something about sublasses and xrc to work it has to comply to the wxWidgets RTTI mechanism. Not sure what that means ?
See the subclassing section of the XRC overview for the details.

Regards,

David
Thanks. I keep meaning to learn XRC, but I never have the time to do it. If I'm reading that page right, my checktree fails 3 of those 4 things and I'm not sure how to fix them. (Although it looks like some code leftover from the tree control sample that I had commented would partly fix the second requirement).
Nunki wrote:So I think that the constructor of wxCheckTree does something more - like allocating the m_colors ??
Right. The constructor loads the icons needed to simulate the checkboxes and also connects several event handlers to make the clicks in the tree simulate clicks on the check boxes. But Requirement 4 in the page linked above says (again if I'm reading it correctly):

It cannot provide custom Create() method and must be constructible using base class' Create() method (this is because XRC will call Create() of class, not subclass). In other words, creation of the control must not be customized.

I don't see how it's possible to meet this requirement. Without those icons and event handlers, the tree won't do the simulation.

In short:
Nunki wrote:I can either not add a wxTreeCtrl to XRC with subclass wxCheckTree but only a wxPanel, on which I will add with new wxCheckTree the actual one - which less prefer.
If that will work, then I guess that's the only option. If not, then you're beyond my knowledge of wxWidgets and I'm not sure what to do. Sorry.
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxTreeCtrl with checkboxes

Post by DavidHart »

I'm not sure I fully understand the problem you're talking about, but there's no particular need to do things either in the ctor or in a method called Create(). When I use XRC, my code usually looks like:

Code: Select all

MySubclassedDlg dlg;
wxXmlResource::Get()->LoadDialog(&dlg, ...));
dlg.Init(...);
In other words, my subclasses have an Init() method which contains Connect() calls and similar. It shouldn't be hard to adapt the currect code in such a way.
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: wxTreeCtrl with checkboxes

Post by New Pagodi »

DavidHart wrote:In other words, my subclasses have an Init() method which contains Connect() calls and similar. It shouldn't be hard to adapt the currect code in such a way.
Thanks again.

I've attached a new version that:
1) allows the source to be included in another project by adding WXUSING_CHECKTREE_SOURCE to the preprocessor definitions,
2) includes all the headers that are needed (at least I hope), and
3) allows the checktree to be used as a subclass with XRC - provided the Init() function is called.

I've also included a really, really basic sample with a form loaded from an XRC file.

I still need to learn a lot more about XRC, so I hope I'm doing everything right; but I can't guarantee it.
Attachments
checktree.zip
(13.18 KiB) Downloaded 558 times
alohamora2
In need of some credit
In need of some credit
Posts: 1
Joined: Sat Sep 09, 2017 5:45 pm

Re: wxTreeCtrl with checkboxes

Post by alohamora2 »

If we select one node then does this code marks all the children of that node checked? Does it follows a tree like structure? i.e. If we check one node then all its children should be checked and if we uncheck one node then all its children should be unchecked. If not do you know where I can find such implementation?
Post Reply