]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/treebase.cpp
floating pane now respects IsFixed pane status; indirect fix for #4044
[wxWidgets.git] / src / common / treebase.cpp
... / ...
CommitLineData
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
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
36DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
37DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
38DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
39DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
40DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
41DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
42DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
43DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
44DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
45DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
46DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
47DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SEL_CHANGED)
48DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SEL_CHANGING)
49DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_KEY_DOWN)
50DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
51DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
52DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
53DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
54DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
55DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
56DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
57
58// ----------------------------------------------------------------------------
59// Tree event
60// ----------------------------------------------------------------------------
61
62IMPLEMENT_ABSTRACT_CLASS(wxTreeEvent, wxNotifyEvent)
63
64
65wxTreeEvent::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
79wxTreeEvent::wxTreeEvent(wxEventType commandType, int id)
80 : wxNotifyEvent(commandType, id)
81{
82 m_itemOld = 0l;
83 m_editCancelled = false;
84}
85
86wxTreeEvent::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
101wxTreeCtrlBase::~wxTreeCtrlBase()
102{
103 if (m_ownsImageListNormal)
104 delete m_imageListNormal;
105 if (m_ownsImageListState)
106 delete m_imageListState;
107}
108
109void wxTreeCtrlBase::SetItemState(const wxTreeItemId& item, int state)
110{
111 if ( state == wxTREE_ITEMSTATE_NEXT )
112 {
113 int current = GetItemState(item);
114 if ( current == wxTREE_ITEMSTATE_NONE )
115 return;
116 state = current + 1;
117 if ( m_imageListState && state >= m_imageListState->GetImageCount() )
118 state = 0;
119 }
120 else if ( state == wxTREE_ITEMSTATE_PREV )
121 {
122 int current = GetItemState(item);
123 if ( current == wxTREE_ITEMSTATE_NONE )
124 return;
125 state = current - 1;
126 if ( state == -1 )
127 state = m_imageListState ? m_imageListState->GetImageCount() - 1 : 0;
128 }
129 // else: wxTREE_ITEMSTATE_NONE depending on platform
130
131 DoSetItemState(item, state);
132}
133
134static void
135wxGetBestTreeSize(const wxTreeCtrlBase* treeCtrl, wxTreeItemId id, wxSize& size)
136{
137 wxRect rect;
138
139 if ( treeCtrl->GetBoundingRect(id, rect, true /* just the item */) )
140 {
141 // Translate to logical position so we get the full extent
142#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
143 rect.x += treeCtrl->GetScrollPos(wxHORIZONTAL);
144 rect.y += treeCtrl->GetScrollPos(wxVERTICAL);
145#endif
146
147 size.IncTo(wxSize(rect.GetRight(), rect.GetBottom()));
148 }
149
150 wxTreeItemIdValue cookie;
151 for ( wxTreeItemId item = treeCtrl->GetFirstChild(id, cookie);
152 item.IsOk();
153 item = treeCtrl->GetNextChild(id, cookie) )
154 {
155 wxGetBestTreeSize(treeCtrl, item, size);
156 }
157}
158
159wxSize wxTreeCtrlBase::DoGetBestSize() const
160{
161 wxSize size;
162
163 // this doesn't really compute the total bounding rectangle of all items
164 // but a not too bad guess of it which has the advantage of not having to
165 // examine all (potentially hundreds or thousands) items in the control
166
167 if (GetQuickBestSize())
168 {
169 for ( wxTreeItemId item = GetRootItem();
170 item.IsOk();
171 item = GetLastChild(item) )
172 {
173 wxRect rect;
174
175 // last parameter is "true" to get only the dimensions of the text
176 // label, we don't want to get the entire item width as it's determined
177 // by the current size
178 if ( GetBoundingRect(item, rect, true) )
179 {
180 if ( size.x < rect.x + rect.width )
181 size.x = rect.x + rect.width;
182 if ( size.y < rect.y + rect.height )
183 size.y = rect.y + rect.height;
184 }
185 }
186 }
187 else // use precise, if potentially slow, size computation method
188 {
189 // iterate over all items recursively
190 wxTreeItemId idRoot = GetRootItem();
191 if ( idRoot.IsOk() )
192 wxGetBestTreeSize(this, idRoot, size);
193 }
194
195 // need some minimal size even for empty tree
196 if ( !size.x || !size.y )
197 size = wxControl::DoGetBestSize();
198 else
199 {
200 // Add border size
201 size += GetWindowBorderSize();
202
203 CacheBestSize(size);
204 }
205
206 return size;
207}
208
209void wxTreeCtrlBase::ExpandAll()
210{
211 if ( IsEmpty() )
212 return;
213
214 ExpandAllChildren(GetRootItem());
215}
216
217void wxTreeCtrlBase::ExpandAllChildren(const wxTreeItemId& item)
218{
219 Freeze();
220 // expand this item first, this might result in its children being added on
221 // the fly
222 if ( item != GetRootItem() || !HasFlag(wxTR_HIDE_ROOT) )
223 Expand(item);
224 //else: expanding hidden root item is unsupported and unnecessary
225
226 // then (recursively) expand all the children
227 wxTreeItemIdValue cookie;
228 for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
229 idCurr.IsOk();
230 idCurr = GetNextChild(item, cookie) )
231 {
232 ExpandAllChildren(idCurr);
233 }
234 Thaw();
235}
236
237void wxTreeCtrlBase::CollapseAll()
238{
239 if ( IsEmpty() )
240 return;
241
242 CollapseAllChildren(GetRootItem());
243}
244
245void wxTreeCtrlBase::CollapseAllChildren(const wxTreeItemId& item)
246{
247 Freeze();
248 // first (recursively) collapse all the children
249 wxTreeItemIdValue cookie;
250 for ( wxTreeItemId idCurr = GetFirstChild(item, cookie);
251 idCurr.IsOk();
252 idCurr = GetNextChild(item, cookie) )
253 {
254 CollapseAllChildren(idCurr);
255 }
256
257 // then collapse this element too
258 Collapse(item);
259 Thaw();
260}
261
262bool wxTreeCtrlBase::IsEmpty() const
263{
264 return !GetRootItem().IsOk();
265}
266
267#endif // wxUSE_TREECTRL