1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        treebase.cpp
3 // Purpose:     Base wxTreeCtrl classes
4 // Author:      Julian Smart
5 // Created:     01/02/97
6 // Modified:
7 // Id:          $Id: treebase.cpp 51356 2008-01-24 11:23:30Z VZ $
8 // Copyright:   (c) 1998 Robert Roebling, Julian Smart et al
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // =============================================================================
13 // declarations
14 // =============================================================================
15 
16 // -----------------------------------------------------------------------------
17 // headers
18 // -----------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #if wxUSE_TREECTRL
28 
29 #include "wx/treectrl.h"
30 #include "wx/imaglist.h"
31 
32 // ----------------------------------------------------------------------------
33 // events
34 // ----------------------------------------------------------------------------
35 
36 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)37 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SEL_CHANGED)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SEL_CHANGING)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_KEY_DOWN)
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
57 
58 // ----------------------------------------------------------------------------
59 // Tree event
60 // ----------------------------------------------------------------------------
61 
62 IMPLEMENT_ABSTRACT_CLASS(wxTreeEvent, wxNotifyEvent)
63 
64 
65 wxTreeEvent::wxTreeEvent(wxEventType commandType,
66                          wxTreeCtrlBase *tree,
67                          const wxTreeItemId& item)
68            : wxNotifyEvent(commandType, tree->GetId()),
69              m_item(item)
70 {
71     m_editCancelled = false;
72 
73     SetEventObject(tree);
74 
75     if ( item.IsOk() )
76         SetClientObject(tree->GetItemData(item));
77 }
78 
wxTreeEvent(wxEventType commandType,int id)79 wxTreeEvent::wxTreeEvent(wxEventType commandType, int id)
80            : wxNotifyEvent(commandType, id)
81 {
82     m_itemOld = 0l;
83     m_editCancelled = false;
84 }
85 
wxTreeEvent(const wxTreeEvent & event)86 wxTreeEvent::wxTreeEvent(const wxTreeEvent & event)
87            : wxNotifyEvent(event)
88 {
89     m_evtKey = event.m_evtKey;
90     m_item = event.m_item;
91     m_itemOld = event.m_itemOld;
92     m_pointDrag = event.m_pointDrag;
93     m_label = event.m_label;
94     m_editCancelled = event.m_editCancelled;
95 }
96 
97 // ----------------------------------------------------------------------------
98 // wxTreeCtrlBase
99 // ----------------------------------------------------------------------------
100 
~wxTreeCtrlBase()101 wxTreeCtrlBase::~wxTreeCtrlBase()
102 {
103     if (m_ownsImageListNormal)
104         delete m_imageListNormal;
105     if (m_ownsImageListState)
106         delete m_imageListState;
107 }
108 
109 static void
wxGetBestTreeSize(const wxTreeCtrlBase * treeCtrl,wxTreeItemId id,wxSize & size)110 wxGetBestTreeSize(const wxTreeCtrlBase* treeCtrl, wxTreeItemId id, wxSize& size)
111 {
112     wxRect rect;
113 
114     if ( treeCtrl->GetBoundingRect(id, rect, true /* just the item */) )
115     {
116         // Translate to logical position so we get the full extent
117 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
118         rect.x += treeCtrl->GetScrollPos(wxHORIZONTAL);
119         rect.y += treeCtrl->GetScrollPos(wxVERTICAL);
120 #endif
121 
122         size.IncTo(wxSize(rect.GetRight(), rect.GetBottom()));
123     }
124 
125     wxTreeItemIdValue cookie;
126     for ( wxTreeItemId item = treeCtrl->GetFirstChild(id, cookie);
127           item.IsOk();
128           item = treeCtrl->GetNextChild(id, cookie) )
129     {
130         wxGetBestTreeSize(treeCtrl, item, size);
131     }
132 }
133 
DoGetBestSize() const134 wxSize wxTreeCtrlBase::DoGetBestSize() const
135 {
136     wxSize size;
137 
138     // this doesn't really compute the total bounding rectangle of all items
139     // but a not too bad guess of it which has the advantage of not having to
140     // examine all (potentially hundreds or thousands) items in the control
141 
142     if (GetQuickBestSize())
143     {
144         for ( wxTreeItemId item = GetRootItem();
145               item.IsOk();
146               item = GetLastChild(item) )
147         {
148             wxRect rect;
149 
150             // last parameter is "true" to get only the dimensions of the text
151             // label, we don't want to get the entire item width as it's determined
152             // by the current size
153             if ( GetBoundingRect(item, rect, true) )
154             {
155                 if ( size.x < rect.x + rect.width )
156                     size.x = rect.x + rect.width;
157                 if ( size.y < rect.y + rect.height )
158                     size.y = rect.y + rect.height;
159             }
160         }
161     }
162     else // use precise, if potentially slow, size computation method
163     {
164         // iterate over all items recursively
165         wxTreeItemId idRoot = GetRootItem();
166         if ( idRoot.IsOk() )
167             wxGetBestTreeSize(this, idRoot, size);
168     }
169 
170     // need some minimal size even for empty tree
171     if ( !size.x || !size.y )
172         size = wxControl::DoGetBestSize();
173     else
174     {
175         // Add border size
176         size += GetWindowBorderSize();
177 
178         CacheBestSize(size);
179     }
180 
181     return size;
182 }
183 
ExpandAll()184 void wxTreeCtrlBase::ExpandAll()
185 {
186     if ( IsEmpty() )
187         return;
188 
189     ExpandAllChildren(GetRootItem());
190 }
191 
ExpandAllChildren(const wxTreeItemId & item)192 void wxTreeCtrlBase::ExpandAllChildren(const wxTreeItemId& item)
193 {
194     // expand this item first, this might result in its children being added on
195     // the fly
196     if ( item != GetRootItem() || !HasFlag(wxTR_HIDE_ROOT) )
197         Expand(item);
198     //else: expanding hidden root item is unsupported and unnecessary
199 
200     // then (recursively) expand all the children
201     wxTreeItemIdValue cookie;
202     for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
203           idCurr.IsOk();
204           idCurr = GetNextChild(item, cookie) )
205     {
206         ExpandAllChildren(idCurr);
207     }
208 }
209 
CollapseAll()210 void wxTreeCtrlBase::CollapseAll()
211 {
212     if ( IsEmpty() )
213         return;
214 
215     CollapseAllChildren(GetRootItem());
216 }
217 
CollapseAllChildren(const wxTreeItemId & item)218 void wxTreeCtrlBase::CollapseAllChildren(const wxTreeItemId& item)
219 {
220     // first (recursively) collapse all the children
221     wxTreeItemIdValue cookie;
222     for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
223           idCurr.IsOk();
224           idCurr = GetNextChild(item, cookie) )
225     {
226         CollapseAllChildren(idCurr);
227     }
228 
229     // then collapse this element too
230     Collapse(item);
231 }
232 
IsEmpty() const233 bool wxTreeCtrlBase::IsEmpty() const
234 {
235     return !GetRootItem().IsOk();
236 }
237 
238 #endif // wxUSE_TREECTRL
239 
240