1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/treebase.cpp
3 // Purpose: Base wxTreeCtrl classes
4 // Author: Julian Smart
8 // Copyright: (c) 1998 Robert Roebling, Julian Smart et al
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // =============================================================================
14 // =============================================================================
16 // -----------------------------------------------------------------------------
18 // -----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/treectrl.h"
30 #include "wx/imaglist.h"
32 extern WXDLLEXPORT_DATA(const char) wxTreeCtrlNameStr
[] = "treeCtrl";
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_DRAG
, wxTreeEvent
);
39 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_RDRAG
, wxTreeEvent
);
40 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
, wxTreeEvent
);
41 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_END_LABEL_EDIT
, wxTreeEvent
);
42 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_DELETE_ITEM
, wxTreeEvent
);
43 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_GET_INFO
, wxTreeEvent
);
44 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SET_INFO
, wxTreeEvent
);
45 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_EXPANDED
, wxTreeEvent
);
46 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_EXPANDING
, wxTreeEvent
);
47 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_COLLAPSED
, wxTreeEvent
);
48 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, wxTreeEvent
);
49 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SEL_CHANGED
, wxTreeEvent
);
50 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_SEL_CHANGING
, wxTreeEvent
);
51 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_KEY_DOWN
, wxTreeEvent
);
52 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, wxTreeEvent
);
53 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
, wxTreeEvent
);
54 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK
, wxTreeEvent
);
55 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_END_DRAG
, wxTreeEvent
);
56 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
, wxTreeEvent
);
57 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
, wxTreeEvent
);
58 wxDEFINE_EVENT( wxEVT_COMMAND_TREE_ITEM_MENU
, wxTreeEvent
);
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 wxDEFINE_FLAGS( wxTreeCtrlStyle
)
65 wxBEGIN_FLAGS( wxTreeCtrlStyle
)
66 // new style border flags, we put them first to
67 // use them for streaming out
68 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
69 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
70 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
71 wxFLAGS_MEMBER(wxBORDER_RAISED
)
72 wxFLAGS_MEMBER(wxBORDER_STATIC
)
73 wxFLAGS_MEMBER(wxBORDER_NONE
)
75 // old style border flags
76 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
77 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
78 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
79 wxFLAGS_MEMBER(wxRAISED_BORDER
)
80 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
81 wxFLAGS_MEMBER(wxBORDER
)
83 // standard window styles
84 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
85 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
86 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
87 wxFLAGS_MEMBER(wxWANTS_CHARS
)
88 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
89 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
90 wxFLAGS_MEMBER(wxVSCROLL
)
91 wxFLAGS_MEMBER(wxHSCROLL
)
93 wxFLAGS_MEMBER(wxTR_EDIT_LABELS
)
94 wxFLAGS_MEMBER(wxTR_NO_BUTTONS
)
95 wxFLAGS_MEMBER(wxTR_HAS_BUTTONS
)
96 wxFLAGS_MEMBER(wxTR_TWIST_BUTTONS
)
97 wxFLAGS_MEMBER(wxTR_NO_LINES
)
98 wxFLAGS_MEMBER(wxTR_FULL_ROW_HIGHLIGHT
)
99 wxFLAGS_MEMBER(wxTR_LINES_AT_ROOT
)
100 wxFLAGS_MEMBER(wxTR_HIDE_ROOT
)
101 wxFLAGS_MEMBER(wxTR_ROW_LINES
)
102 wxFLAGS_MEMBER(wxTR_HAS_VARIABLE_ROW_HEIGHT
)
103 wxFLAGS_MEMBER(wxTR_SINGLE
)
104 wxFLAGS_MEMBER(wxTR_MULTIPLE
)
105 #if WXWIN_COMPATIBILITY_2_8
106 wxFLAGS_MEMBER(wxTR_EXTENDED
)
108 wxFLAGS_MEMBER(wxTR_DEFAULT_STYLE
)
109 wxEND_FLAGS( wxTreeCtrlStyle
)
111 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxTreeCtrl
, wxControl
, "wx/treectrl.h")
113 wxBEGIN_PROPERTIES_TABLE(wxTreeCtrl
)
114 wxEVENT_PROPERTY( TextUpdated
, wxEVT_COMMAND_TEXT_UPDATED
, wxCommandEvent
)
115 wxEVENT_RANGE_PROPERTY( TreeEvent
, wxEVT_COMMAND_TREE_BEGIN_DRAG
, \
116 wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
, wxTreeEvent
)
118 wxPROPERTY_FLAGS( WindowStyle
, wxTreeCtrlStyle
, long, SetWindowStyleFlag
, \
119 GetWindowStyleFlag
, wxEMPTY_PARAMETER_VALUE
, 0 /*flags*/, \
120 wxT("Helpstring"), wxT("group")) // style
121 wxEND_PROPERTIES_TABLE()
123 wxEMPTY_HANDLERS_TABLE(wxTreeCtrl
)
125 wxCONSTRUCTOR_5( wxTreeCtrl
, wxWindow
*, Parent
, wxWindowID
, Id
, \
126 wxPoint
, Position
, wxSize
, Size
, long, WindowStyle
)
128 // ----------------------------------------------------------------------------
130 // ----------------------------------------------------------------------------
132 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent
, wxNotifyEvent
)
134 wxTreeEvent
::wxTreeEvent(wxEventType commandType
,
135 wxTreeCtrlBase
*tree
,
136 const wxTreeItemId
& item
)
137 : wxNotifyEvent(commandType
, tree
->GetId()),
140 m_editCancelled
= false;
142 SetEventObject(tree
);
145 SetClientObject(tree
->GetItemData(item
));
148 wxTreeEvent
::wxTreeEvent(wxEventType commandType
, int id
)
149 : wxNotifyEvent(commandType
, id
)
152 m_editCancelled
= false;
155 wxTreeEvent
::wxTreeEvent(const wxTreeEvent
& event
)
156 : wxNotifyEvent(event
)
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
;
166 // ----------------------------------------------------------------------------
168 // ----------------------------------------------------------------------------
170 wxTreeCtrlBase
::wxTreeCtrlBase()
173 m_imageListState
= NULL
;
174 m_ownsImageListNormal
=
175 m_ownsImageListState
= false;
180 // quick DoGetBestSize calculation
181 m_quickBestSize
= true;
184 wxTreeCtrlBase
::~wxTreeCtrlBase()
186 if (m_ownsImageListNormal
)
187 delete m_imageListNormal
;
188 if (m_ownsImageListState
)
189 delete m_imageListState
;
192 void wxTreeCtrlBase
::SetItemState(const wxTreeItemId
& item
, int state
)
194 if ( state
== wxTREE_ITEMSTATE_NEXT
)
196 int current
= GetItemState(item
);
197 if ( current
== wxTREE_ITEMSTATE_NONE
)
200 if ( m_imageListState
&& state
>= m_imageListState
->GetImageCount() )
203 else if ( state
== wxTREE_ITEMSTATE_PREV
)
205 int current
= GetItemState(item
);
206 if ( current
== wxTREE_ITEMSTATE_NONE
)
210 state
= m_imageListState ? m_imageListState
->GetImageCount() - 1 : 0;
212 // else: wxTREE_ITEMSTATE_NONE depending on platform
214 DoSetItemState(item
, state
);
218 wxGetBestTreeSize(const wxTreeCtrlBase
* treeCtrl
, wxTreeItemId id
, wxSize
& size
)
222 if ( treeCtrl
->GetBoundingRect(id
, rect
, true /* just the item */) )
224 // Translate to logical position so we get the full extent
225 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
226 rect
.x
+= treeCtrl
->GetScrollPos(wxHORIZONTAL
);
227 rect
.y
+= treeCtrl
->GetScrollPos(wxVERTICAL
);
230 size
.IncTo(wxSize(rect
.GetRight(), rect
.GetBottom()));
233 wxTreeItemIdValue cookie
;
234 for ( wxTreeItemId item
= treeCtrl
->GetFirstChild(id
, cookie
);
236 item
= treeCtrl
->GetNextChild(id
, cookie
) )
238 wxGetBestTreeSize(treeCtrl
, item
, size
);
242 wxSize wxTreeCtrlBase
::DoGetBestSize() const
246 // this doesn't really compute the total bounding rectangle of all items
247 // but a not too bad guess of it which has the advantage of not having to
248 // examine all (potentially hundreds or thousands) items in the control
250 if (GetQuickBestSize())
252 for ( wxTreeItemId item
= GetRootItem();
254 item
= GetLastChild(item
) )
258 // last parameter is "true" to get only the dimensions of the text
259 // label, we don't want to get the entire item width as it's determined
260 // by the current size
261 if ( GetBoundingRect(item
, rect
, true) )
263 if ( size
.x
< rect
.x
+ rect
.width
)
264 size
.x
= rect
.x
+ rect
.width
;
265 if ( size
.y
< rect
.y
+ rect
.height
)
266 size
.y
= rect
.y
+ rect
.height
;
270 else // use precise, if potentially slow, size computation method
272 // iterate over all items recursively
273 wxTreeItemId idRoot
= GetRootItem();
275 wxGetBestTreeSize(this, idRoot
, size
);
278 // need some minimal size even for empty tree
279 if ( !size
.x
|| !size
.y
)
280 size
= wxControl
::DoGetBestSize();
284 size
+= GetWindowBorderSize();
292 void wxTreeCtrlBase
::ExpandAll()
297 ExpandAllChildren(GetRootItem());
300 void wxTreeCtrlBase
::ExpandAllChildren(const wxTreeItemId
& item
)
303 // expand this item first, this might result in its children being added on
305 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
307 //else: expanding hidden root item is unsupported and unnecessary
309 // then (recursively) expand all the children
310 wxTreeItemIdValue cookie
;
311 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
313 idCurr
= GetNextChild(item
, cookie
) )
315 ExpandAllChildren(idCurr
);
320 void wxTreeCtrlBase
::CollapseAll()
325 CollapseAllChildren(GetRootItem());
328 void wxTreeCtrlBase
::CollapseAllChildren(const wxTreeItemId
& item
)
331 // first (recursively) collapse all the children
332 wxTreeItemIdValue cookie
;
333 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
335 idCurr
= GetNextChild(item
, cookie
) )
337 CollapseAllChildren(idCurr
);
340 // then collapse this element too unless it's the hidden root which can't
342 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
347 bool wxTreeCtrlBase
::IsEmpty() const
349 return !GetRootItem().IsOk();
352 #endif // wxUSE_TREECTRL