1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/treebase.cpp
3 // Purpose: Base wxTreeCtrl classes
4 // Author: Julian Smart
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart et al
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // =============================================================================
13 // =============================================================================
15 // -----------------------------------------------------------------------------
17 // -----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 #include "wx/treectrl.h"
29 #include "wx/imaglist.h"
31 extern WXDLLEXPORT_DATA(const char) wxTreeCtrlNameStr
[] = "treeCtrl";
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 wxDEFINE_EVENT( wxEVT_TREE_BEGIN_DRAG
, wxTreeEvent
);
38 wxDEFINE_EVENT( wxEVT_TREE_BEGIN_RDRAG
, wxTreeEvent
);
39 wxDEFINE_EVENT( wxEVT_TREE_BEGIN_LABEL_EDIT
, wxTreeEvent
);
40 wxDEFINE_EVENT( wxEVT_TREE_END_LABEL_EDIT
, wxTreeEvent
);
41 wxDEFINE_EVENT( wxEVT_TREE_DELETE_ITEM
, wxTreeEvent
);
42 wxDEFINE_EVENT( wxEVT_TREE_GET_INFO
, wxTreeEvent
);
43 wxDEFINE_EVENT( wxEVT_TREE_SET_INFO
, wxTreeEvent
);
44 wxDEFINE_EVENT( wxEVT_TREE_ITEM_EXPANDED
, wxTreeEvent
);
45 wxDEFINE_EVENT( wxEVT_TREE_ITEM_EXPANDING
, wxTreeEvent
);
46 wxDEFINE_EVENT( wxEVT_TREE_ITEM_COLLAPSED
, wxTreeEvent
);
47 wxDEFINE_EVENT( wxEVT_TREE_ITEM_COLLAPSING
, wxTreeEvent
);
48 wxDEFINE_EVENT( wxEVT_TREE_SEL_CHANGED
, wxTreeEvent
);
49 wxDEFINE_EVENT( wxEVT_TREE_SEL_CHANGING
, wxTreeEvent
);
50 wxDEFINE_EVENT( wxEVT_TREE_KEY_DOWN
, wxTreeEvent
);
51 wxDEFINE_EVENT( wxEVT_TREE_ITEM_ACTIVATED
, wxTreeEvent
);
52 wxDEFINE_EVENT( wxEVT_TREE_ITEM_RIGHT_CLICK
, wxTreeEvent
);
53 wxDEFINE_EVENT( wxEVT_TREE_ITEM_MIDDLE_CLICK
, wxTreeEvent
);
54 wxDEFINE_EVENT( wxEVT_TREE_END_DRAG
, wxTreeEvent
);
55 wxDEFINE_EVENT( wxEVT_TREE_STATE_IMAGE_CLICK
, wxTreeEvent
);
56 wxDEFINE_EVENT( wxEVT_TREE_ITEM_GETTOOLTIP
, wxTreeEvent
);
57 wxDEFINE_EVENT( wxEVT_TREE_ITEM_MENU
, wxTreeEvent
);
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 wxDEFINE_FLAGS( wxTreeCtrlStyle
)
64 wxBEGIN_FLAGS( wxTreeCtrlStyle
)
65 // new style border flags, we put them first to
66 // use them for streaming out
67 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
68 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
69 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
70 wxFLAGS_MEMBER(wxBORDER_RAISED
)
71 wxFLAGS_MEMBER(wxBORDER_STATIC
)
72 wxFLAGS_MEMBER(wxBORDER_NONE
)
74 // old style border flags
75 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
76 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
77 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
78 wxFLAGS_MEMBER(wxRAISED_BORDER
)
79 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
80 wxFLAGS_MEMBER(wxBORDER
)
82 // standard window styles
83 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
84 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
85 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
86 wxFLAGS_MEMBER(wxWANTS_CHARS
)
87 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
88 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
89 wxFLAGS_MEMBER(wxVSCROLL
)
90 wxFLAGS_MEMBER(wxHSCROLL
)
92 wxFLAGS_MEMBER(wxTR_EDIT_LABELS
)
93 wxFLAGS_MEMBER(wxTR_NO_BUTTONS
)
94 wxFLAGS_MEMBER(wxTR_HAS_BUTTONS
)
95 wxFLAGS_MEMBER(wxTR_TWIST_BUTTONS
)
96 wxFLAGS_MEMBER(wxTR_NO_LINES
)
97 wxFLAGS_MEMBER(wxTR_FULL_ROW_HIGHLIGHT
)
98 wxFLAGS_MEMBER(wxTR_LINES_AT_ROOT
)
99 wxFLAGS_MEMBER(wxTR_HIDE_ROOT
)
100 wxFLAGS_MEMBER(wxTR_ROW_LINES
)
101 wxFLAGS_MEMBER(wxTR_HAS_VARIABLE_ROW_HEIGHT
)
102 wxFLAGS_MEMBER(wxTR_SINGLE
)
103 wxFLAGS_MEMBER(wxTR_MULTIPLE
)
104 #if WXWIN_COMPATIBILITY_2_8
105 wxFLAGS_MEMBER(wxTR_EXTENDED
)
107 wxFLAGS_MEMBER(wxTR_DEFAULT_STYLE
)
108 wxEND_FLAGS( wxTreeCtrlStyle
)
110 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxTreeCtrl
, wxControl
, "wx/treectrl.h")
112 wxBEGIN_PROPERTIES_TABLE(wxTreeCtrl
)
113 wxEVENT_PROPERTY( TextUpdated
, wxEVT_TEXT
, wxCommandEvent
)
114 wxEVENT_RANGE_PROPERTY( TreeEvent
, wxEVT_TREE_BEGIN_DRAG
, \
115 wxEVT_TREE_STATE_IMAGE_CLICK
, wxTreeEvent
)
117 wxPROPERTY_FLAGS( WindowStyle
, wxTreeCtrlStyle
, long, SetWindowStyleFlag
, \
118 GetWindowStyleFlag
, wxEMPTY_PARAMETER_VALUE
, 0 /*flags*/, \
119 wxT("Helpstring"), wxT("group")) // style
120 wxEND_PROPERTIES_TABLE()
122 wxEMPTY_HANDLERS_TABLE(wxTreeCtrl
)
124 wxCONSTRUCTOR_5( wxTreeCtrl
, wxWindow
*, Parent
, wxWindowID
, Id
, \
125 wxPoint
, Position
, wxSize
, Size
, long, WindowStyle
)
127 // ----------------------------------------------------------------------------
129 // ----------------------------------------------------------------------------
131 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent
, wxNotifyEvent
)
133 wxTreeEvent::wxTreeEvent(wxEventType commandType
,
134 wxTreeCtrlBase
*tree
,
135 const wxTreeItemId
& item
)
136 : wxNotifyEvent(commandType
, tree
->GetId()),
139 m_editCancelled
= false;
141 SetEventObject(tree
);
144 SetClientObject(tree
->GetItemData(item
));
147 wxTreeEvent::wxTreeEvent(wxEventType commandType
, int id
)
148 : wxNotifyEvent(commandType
, id
)
151 m_editCancelled
= false;
154 wxTreeEvent::wxTreeEvent(const wxTreeEvent
& event
)
155 : wxNotifyEvent(event
)
157 m_evtKey
= event
.m_evtKey
;
158 m_item
= event
.m_item
;
159 m_itemOld
= event
.m_itemOld
;
160 m_pointDrag
= event
.m_pointDrag
;
161 m_label
= event
.m_label
;
162 m_editCancelled
= event
.m_editCancelled
;
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
169 wxTreeCtrlBase::wxTreeCtrlBase()
172 m_imageListState
= NULL
;
173 m_ownsImageListNormal
=
174 m_ownsImageListState
= false;
179 // quick DoGetBestSize calculation
180 m_quickBestSize
= true;
182 Connect(wxEVT_CHAR_HOOK
, wxKeyEventHandler(wxTreeCtrlBase::OnCharHook
));
185 wxTreeCtrlBase::~wxTreeCtrlBase()
187 if (m_ownsImageListNormal
)
188 delete m_imageListNormal
;
189 if (m_ownsImageListState
)
190 delete m_imageListState
;
193 void wxTreeCtrlBase::SetItemState(const wxTreeItemId
& item
, int state
)
195 if ( state
== wxTREE_ITEMSTATE_NEXT
)
197 int current
= GetItemState(item
);
198 if ( current
== wxTREE_ITEMSTATE_NONE
)
201 if ( m_imageListState
&& state
>= m_imageListState
->GetImageCount() )
204 else if ( state
== wxTREE_ITEMSTATE_PREV
)
206 int current
= GetItemState(item
);
207 if ( current
== wxTREE_ITEMSTATE_NONE
)
211 state
= m_imageListState
? m_imageListState
->GetImageCount() - 1 : 0;
213 // else: wxTREE_ITEMSTATE_NONE depending on platform
215 DoSetItemState(item
, state
);
219 wxGetBestTreeSize(const wxTreeCtrlBase
* treeCtrl
, wxTreeItemId id
, wxSize
& size
)
223 if ( treeCtrl
->GetBoundingRect(id
, rect
, true /* just the item */) )
225 // Translate to logical position so we get the full extent
226 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
227 rect
.x
+= treeCtrl
->GetScrollPos(wxHORIZONTAL
);
228 rect
.y
+= treeCtrl
->GetScrollPos(wxVERTICAL
);
231 size
.IncTo(wxSize(rect
.GetRight(), rect
.GetBottom()));
234 wxTreeItemIdValue cookie
;
235 for ( wxTreeItemId item
= treeCtrl
->GetFirstChild(id
, cookie
);
237 item
= treeCtrl
->GetNextChild(id
, cookie
) )
239 wxGetBestTreeSize(treeCtrl
, item
, size
);
243 wxSize
wxTreeCtrlBase::DoGetBestSize() const
247 // this doesn't really compute the total bounding rectangle of all items
248 // but a not too bad guess of it which has the advantage of not having to
249 // examine all (potentially hundreds or thousands) items in the control
251 if (GetQuickBestSize())
253 for ( wxTreeItemId item
= GetRootItem();
255 item
= GetLastChild(item
) )
259 // last parameter is "true" to get only the dimensions of the text
260 // label, we don't want to get the entire item width as it's determined
261 // by the current size
262 if ( GetBoundingRect(item
, rect
, true) )
264 if ( size
.x
< rect
.x
+ rect
.width
)
265 size
.x
= rect
.x
+ rect
.width
;
266 if ( size
.y
< rect
.y
+ rect
.height
)
267 size
.y
= rect
.y
+ rect
.height
;
271 else // use precise, if potentially slow, size computation method
273 // iterate over all items recursively
274 wxTreeItemId idRoot
= GetRootItem();
276 wxGetBestTreeSize(this, idRoot
, size
);
279 // need some minimal size even for empty tree
280 if ( !size
.x
|| !size
.y
)
281 size
= wxControl::DoGetBestSize();
285 size
+= GetWindowBorderSize();
293 void wxTreeCtrlBase::ExpandAll()
298 ExpandAllChildren(GetRootItem());
301 void wxTreeCtrlBase::ExpandAllChildren(const wxTreeItemId
& item
)
304 // expand this item first, this might result in its children being added on
306 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
308 //else: expanding hidden root item is unsupported and unnecessary
310 // then (recursively) expand all the children
311 wxTreeItemIdValue cookie
;
312 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
314 idCurr
= GetNextChild(item
, cookie
) )
316 ExpandAllChildren(idCurr
);
321 void wxTreeCtrlBase::CollapseAll()
326 CollapseAllChildren(GetRootItem());
329 void wxTreeCtrlBase::CollapseAllChildren(const wxTreeItemId
& item
)
332 // first (recursively) collapse all the children
333 wxTreeItemIdValue cookie
;
334 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
336 idCurr
= GetNextChild(item
, cookie
) )
338 CollapseAllChildren(idCurr
);
341 // then collapse this element too unless it's the hidden root which can't
343 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
348 bool wxTreeCtrlBase::IsEmpty() const
350 return !GetRootItem().IsOk();
353 void wxTreeCtrlBase::OnCharHook(wxKeyEvent
& event
)
355 if ( GetEditControl() )
357 bool discardChanges
= false;
358 switch ( event
.GetKeyCode() )
361 discardChanges
= true;
365 EndEditLabel(GetFocusedItem(), discardChanges
);
367 // Do not call Skip() below.
375 #endif // wxUSE_TREECTRL