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) |
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 |
|
79 |
wxTreeEvent::wxTreeEvent(wxEventType commandType, int id) |
80 |
: wxNotifyEvent(commandType, id) |
81 |
{ |
82 |
m_itemOld = 0l; |
83 |
m_editCancelled = false; |
84 |
} |
85 |
|
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 |
|
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 |
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 |
|
134 |
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 |
|
184 |
void wxTreeCtrlBase::ExpandAll() |
185 |
{ |
186 |
if ( IsEmpty() ) |
187 |
return; |
188 |
|
189 |
ExpandAllChildren(GetRootItem()); |
190 |
} |
191 |
|
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 |
|
210 |
void wxTreeCtrlBase::CollapseAll() |
211 |
{ |
212 |
if ( IsEmpty() ) |
213 |
return; |
214 |
|
215 |
CollapseAllChildren(GetRootItem()); |
216 |
} |
217 |
|
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 |
|
233 |
bool wxTreeCtrlBase::IsEmpty() const |
234 |
{ |
235 |
return !GetRootItem().IsOk(); |
236 |
} |
237 |
|
238 |
#endif // wxUSE_TREECTRL |
239 |
|