]> git.saurik.com Git - wxWidgets.git/blame - src/common/treebase.cpp
set eol-style and keywords properties on new files
[wxWidgets.git] / src / common / treebase.cpp
CommitLineData
484523cf
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: treebase.cpp
3// Purpose: Base wxTreeCtrl classes
4// Author: Julian Smart
5// Created: 01/02/97
6// Modified:
7// Id: $Id$
8// Copyright: (c) 1998 Robert Roebling, Julian Smart et al
65571936 9// Licence: wxWindows licence
484523cf
JS
10/////////////////////////////////////////////////////////////////////////////
11
12// =============================================================================
13// declarations
14// =============================================================================
15
16// -----------------------------------------------------------------------------
17// headers
18// -----------------------------------------------------------------------------
19
484523cf
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
1e6feb95 24 #pragma hdrstop
484523cf
JS
25#endif
26
1e6feb95
VZ
27#if wxUSE_TREECTRL
28
8cee4a30 29#include "wx/treectrl.h"
42e53e77 30#include "wx/imaglist.h"
ed2ec17c
GT
31
32// ----------------------------------------------------------------------------
33// events
34// ----------------------------------------------------------------------------
35
9b11752c
VZ
36wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEvent );
37wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_RDRAG, wxTreeEvent );
38wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxTreeEvent );
39wxDEFINE_EVENT( wxEVT_COMMAND_TREE_END_LABEL_EDIT, wxTreeEvent );
40wxDEFINE_EVENT( wxEVT_COMMAND_TREE_DELETE_ITEM, wxTreeEvent );
41wxDEFINE_EVENT( wxEVT_COMMAND_TREE_GET_INFO, wxTreeEvent );
42wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SET_INFO, wxTreeEvent );
43wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEvent );
44wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_EXPANDING, wxTreeEvent );
45wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEvent );
46wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, wxTreeEvent );
47wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEvent );
48wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SEL_CHANGING, wxTreeEvent );
49wxDEFINE_EVENT( wxEVT_COMMAND_TREE_KEY_DOWN, wxTreeEvent );
50wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEvent );
51wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, wxTreeEvent );
52wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, wxTreeEvent );
53wxDEFINE_EVENT( wxEVT_COMMAND_TREE_END_DRAG, wxTreeEvent );
54wxDEFINE_EVENT( wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, wxTreeEvent );
55wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, wxTreeEvent );
56wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEvent );
ed2ec17c 57
28953245
SC
58// ----------------------------------------------------------------------------
59// XTI
60// ----------------------------------------------------------------------------
61
62wxDEFINE_FLAGS( wxTreeCtrlStyle )
63wxBEGIN_FLAGS( wxTreeCtrlStyle )
64// new style border flags, we put them first to
65// use them for streaming out
66wxFLAGS_MEMBER(wxBORDER_SIMPLE)
67wxFLAGS_MEMBER(wxBORDER_SUNKEN)
68wxFLAGS_MEMBER(wxBORDER_DOUBLE)
69wxFLAGS_MEMBER(wxBORDER_RAISED)
70wxFLAGS_MEMBER(wxBORDER_STATIC)
71wxFLAGS_MEMBER(wxBORDER_NONE)
72
73// old style border flags
74wxFLAGS_MEMBER(wxSIMPLE_BORDER)
75wxFLAGS_MEMBER(wxSUNKEN_BORDER)
76wxFLAGS_MEMBER(wxDOUBLE_BORDER)
77wxFLAGS_MEMBER(wxRAISED_BORDER)
78wxFLAGS_MEMBER(wxSTATIC_BORDER)
79wxFLAGS_MEMBER(wxBORDER)
80
81// standard window styles
82wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
83wxFLAGS_MEMBER(wxCLIP_CHILDREN)
84wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
85wxFLAGS_MEMBER(wxWANTS_CHARS)
86wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
87wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
88wxFLAGS_MEMBER(wxVSCROLL)
89wxFLAGS_MEMBER(wxHSCROLL)
90
91wxFLAGS_MEMBER(wxTR_EDIT_LABELS)
92wxFLAGS_MEMBER(wxTR_NO_BUTTONS)
93wxFLAGS_MEMBER(wxTR_HAS_BUTTONS)
94wxFLAGS_MEMBER(wxTR_TWIST_BUTTONS)
95wxFLAGS_MEMBER(wxTR_NO_LINES)
96wxFLAGS_MEMBER(wxTR_FULL_ROW_HIGHLIGHT)
97wxFLAGS_MEMBER(wxTR_LINES_AT_ROOT)
98wxFLAGS_MEMBER(wxTR_HIDE_ROOT)
99wxFLAGS_MEMBER(wxTR_ROW_LINES)
100wxFLAGS_MEMBER(wxTR_HAS_VARIABLE_ROW_HEIGHT)
101wxFLAGS_MEMBER(wxTR_SINGLE)
102wxFLAGS_MEMBER(wxTR_MULTIPLE)
103#if WXWIN_COMPATIBILITY_2_8
104wxFLAGS_MEMBER(wxTR_EXTENDED)
105#endif
106wxFLAGS_MEMBER(wxTR_DEFAULT_STYLE)
107wxEND_FLAGS( wxTreeCtrlStyle )
108
109wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxTreeCtrl, wxControl, "wx/treectrl.h")
110
111wxBEGIN_PROPERTIES_TABLE(wxTreeCtrl)
112wxEVENT_PROPERTY( TextUpdated, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEvent )
113wxEVENT_RANGE_PROPERTY( TreeEvent, wxEVT_COMMAND_TREE_BEGIN_DRAG, \
114 wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, wxTreeEvent )
115
116wxPROPERTY_FLAGS( WindowStyle, wxTreeCtrlStyle, long, SetWindowStyleFlag, \
117 GetWindowStyleFlag, wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, \
118 wxT("Helpstring"), wxT("group")) // style
119wxEND_PROPERTIES_TABLE()
120
121wxEMPTY_HANDLERS_TABLE(wxTreeCtrl)
122
123wxCONSTRUCTOR_5( wxTreeCtrl, wxWindow*, Parent, wxWindowID, Id, \
124 wxPoint, Position, wxSize, Size, long, WindowStyle )
125
484523cf
JS
126// ----------------------------------------------------------------------------
127// Tree event
128// ----------------------------------------------------------------------------
129
e47859da 130IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent)
b8fbf1a0 131
09f277d6
VZ
132wxTreeEvent::wxTreeEvent(wxEventType commandType,
133 wxTreeCtrlBase *tree,
134 const wxTreeItemId& item)
135 : wxNotifyEvent(commandType, tree->GetId()),
136 m_item(item)
484523cf 137{
cb719f2e 138 m_editCancelled = false;
09f277d6
VZ
139
140 SetEventObject(tree);
141
142 if ( item.IsOk() )
143 SetClientObject(tree->GetItemData(item));
484523cf
JS
144}
145
49b6ebb7
RD
146wxTreeEvent::wxTreeEvent(wxEventType commandType, int id)
147 : wxNotifyEvent(commandType, id)
148{
149 m_itemOld = 0l;
150 m_editCancelled = false;
151}
152
0cd936a4
WS
153wxTreeEvent::wxTreeEvent(const wxTreeEvent & event)
154 : wxNotifyEvent(event)
155{
156 m_evtKey = event.m_evtKey;
157 m_item = event.m_item;
158 m_itemOld = event.m_itemOld;
159 m_pointDrag = event.m_pointDrag;
160 m_label = event.m_label;
161 m_editCancelled = event.m_editCancelled;
162}
163
8cee4a30
VZ
164// ----------------------------------------------------------------------------
165// wxTreeCtrlBase
166// ----------------------------------------------------------------------------
167
168wxTreeCtrlBase::~wxTreeCtrlBase()
169{
170 if (m_ownsImageListNormal)
171 delete m_imageListNormal;
172 if (m_ownsImageListState)
173 delete m_imageListState;
174}
175
03966fcb
RR
176void wxTreeCtrlBase::SetItemState(const wxTreeItemId& item, int state)
177{
178 if ( state == wxTREE_ITEMSTATE_NEXT )
179 {
4754ab16
RR
180 int current = GetItemState(item);
181 if ( current == wxTREE_ITEMSTATE_NONE )
182 return;
183 state = current + 1;
03966fcb
RR
184 if ( m_imageListState && state >= m_imageListState->GetImageCount() )
185 state = 0;
186 }
187 else if ( state == wxTREE_ITEMSTATE_PREV )
188 {
4754ab16
RR
189 int current = GetItemState(item);
190 if ( current == wxTREE_ITEMSTATE_NONE )
191 return;
192 state = current - 1;
03966fcb
RR
193 if ( state == -1 )
194 state = m_imageListState ? m_imageListState->GetImageCount() - 1 : 0;
195 }
196 // else: wxTREE_ITEMSTATE_NONE depending on platform
197
198 DoSetItemState(item, state);
199}
200
fbf8436c
VZ
201static void
202wxGetBestTreeSize(const wxTreeCtrlBase* treeCtrl, wxTreeItemId id, wxSize& size)
7c384067
JS
203{
204 wxRect rect;
70934138 205
fbf8436c 206 if ( treeCtrl->GetBoundingRect(id, rect, true /* just the item */) )
7c384067 207 {
9e7642ae 208 // Translate to logical position so we get the full extent
9766efc3 209#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
9e7642ae
JS
210 rect.x += treeCtrl->GetScrollPos(wxHORIZONTAL);
211 rect.y += treeCtrl->GetScrollPos(wxVERTICAL);
9766efc3 212#endif
9e7642ae 213
fbf8436c 214 size.IncTo(wxSize(rect.GetRight(), rect.GetBottom()));
7c384067
JS
215 }
216
217 wxTreeItemIdValue cookie;
218 for ( wxTreeItemId item = treeCtrl->GetFirstChild(id, cookie);
219 item.IsOk();
3e748fca 220 item = treeCtrl->GetNextChild(id, cookie) )
7c384067
JS
221 {
222 wxGetBestTreeSize(treeCtrl, item, size);
223 }
224}
225
8cee4a30
VZ
226wxSize wxTreeCtrlBase::DoGetBestSize() const
227{
228 wxSize size;
229
230 // this doesn't really compute the total bounding rectangle of all items
231 // but a not too bad guess of it which has the advantage of not having to
232 // examine all (potentially hundreds or thousands) items in the control
70934138 233
7c384067 234 if (GetQuickBestSize())
8cee4a30 235 {
7c384067
JS
236 for ( wxTreeItemId item = GetRootItem();
237 item.IsOk();
238 item = GetLastChild(item) )
8cee4a30 239 {
7c384067
JS
240 wxRect rect;
241
242 // last parameter is "true" to get only the dimensions of the text
243 // label, we don't want to get the entire item width as it's determined
244 // by the current size
245 if ( GetBoundingRect(item, rect, true) )
246 {
247 if ( size.x < rect.x + rect.width )
248 size.x = rect.x + rect.width;
249 if ( size.y < rect.y + rect.height )
250 size.y = rect.y + rect.height;
251 }
8cee4a30
VZ
252 }
253 }
fbf8436c
VZ
254 else // use precise, if potentially slow, size computation method
255 {
256 // iterate over all items recursively
16f32ee7
VZ
257 wxTreeItemId idRoot = GetRootItem();
258 if ( idRoot.IsOk() )
259 wxGetBestTreeSize(this, idRoot, size);
fbf8436c
VZ
260 }
261
8cee4a30
VZ
262 // need some minimal size even for empty tree
263 if ( !size.x || !size.y )
264 size = wxControl::DoGetBestSize();
b24069f2 265 else
54a4121a
VZ
266 {
267 // Add border size
268 size += GetWindowBorderSize();
269
b24069f2 270 CacheBestSize(size);
54a4121a 271 }
8cee4a30
VZ
272
273 return size;
274}
275
70934138
VZ
276void wxTreeCtrlBase::ExpandAll()
277{
9248adc8
VZ
278 if ( IsEmpty() )
279 return;
280
70934138
VZ
281 ExpandAllChildren(GetRootItem());
282}
283
284void wxTreeCtrlBase::ExpandAllChildren(const wxTreeItemId& item)
285{
624f89c2 286 Freeze();
70934138
VZ
287 // expand this item first, this might result in its children being added on
288 // the fly
e660f922
VZ
289 if ( item != GetRootItem() || !HasFlag(wxTR_HIDE_ROOT) )
290 Expand(item);
291 //else: expanding hidden root item is unsupported and unnecessary
70934138
VZ
292
293 // then (recursively) expand all the children
294 wxTreeItemIdValue cookie;
295 for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
296 idCurr.IsOk();
297 idCurr = GetNextChild(item, cookie) )
298 {
299 ExpandAllChildren(idCurr);
300 }
624f89c2 301 Thaw();
70934138
VZ
302}
303
9248adc8
VZ
304void wxTreeCtrlBase::CollapseAll()
305{
306 if ( IsEmpty() )
307 return;
308
309 CollapseAllChildren(GetRootItem());
310}
311
312void wxTreeCtrlBase::CollapseAllChildren(const wxTreeItemId& item)
313{
624f89c2 314 Freeze();
9248adc8
VZ
315 // first (recursively) collapse all the children
316 wxTreeItemIdValue cookie;
317 for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
318 idCurr.IsOk();
319 idCurr = GetNextChild(item, cookie) )
320 {
321 CollapseAllChildren(idCurr);
322 }
323
324 // then collapse this element too
325 Collapse(item);
624f89c2 326 Thaw();
9248adc8
VZ
327}
328
329bool wxTreeCtrlBase::IsEmpty() const
330{
331 return !GetRootItem().IsOk();
332}
333
1e6feb95 334#endif // wxUSE_TREECTRL