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