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_TREE_BEGIN_DRAG
, wxTreeEvent
);
39 wxDEFINE_EVENT( wxEVT_TREE_BEGIN_RDRAG
, wxTreeEvent
);
40 wxDEFINE_EVENT( wxEVT_TREE_BEGIN_LABEL_EDIT
, wxTreeEvent
);
41 wxDEFINE_EVENT( wxEVT_TREE_END_LABEL_EDIT
, wxTreeEvent
);
42 wxDEFINE_EVENT( wxEVT_TREE_DELETE_ITEM
, wxTreeEvent
);
43 wxDEFINE_EVENT( wxEVT_TREE_GET_INFO
, wxTreeEvent
);
44 wxDEFINE_EVENT( wxEVT_TREE_SET_INFO
, wxTreeEvent
);
45 wxDEFINE_EVENT( wxEVT_TREE_ITEM_EXPANDED
, wxTreeEvent
);
46 wxDEFINE_EVENT( wxEVT_TREE_ITEM_EXPANDING
, wxTreeEvent
);
47 wxDEFINE_EVENT( wxEVT_TREE_ITEM_COLLAPSED
, wxTreeEvent
);
48 wxDEFINE_EVENT( wxEVT_TREE_ITEM_COLLAPSING
, wxTreeEvent
);
49 wxDEFINE_EVENT( wxEVT_TREE_SEL_CHANGED
, wxTreeEvent
);
50 wxDEFINE_EVENT( wxEVT_TREE_SEL_CHANGING
, wxTreeEvent
);
51 wxDEFINE_EVENT( wxEVT_TREE_KEY_DOWN
, wxTreeEvent
);
52 wxDEFINE_EVENT( wxEVT_TREE_ITEM_ACTIVATED
, wxTreeEvent
);
53 wxDEFINE_EVENT( wxEVT_TREE_ITEM_RIGHT_CLICK
, wxTreeEvent
);
54 wxDEFINE_EVENT( wxEVT_TREE_ITEM_MIDDLE_CLICK
, wxTreeEvent
);
55 wxDEFINE_EVENT( wxEVT_TREE_END_DRAG
, wxTreeEvent
);
56 wxDEFINE_EVENT( wxEVT_TREE_STATE_IMAGE_CLICK
, wxTreeEvent
);
57 wxDEFINE_EVENT( wxEVT_TREE_ITEM_GETTOOLTIP
, wxTreeEvent
);
58 wxDEFINE_EVENT( wxEVT_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_TEXT
, wxCommandEvent
)
115 wxEVENT_RANGE_PROPERTY( TreeEvent
, wxEVT_TREE_BEGIN_DRAG
, \
116 wxEVT_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;
183 Connect(wxEVT_CHAR_HOOK
, wxKeyEventHandler(wxTreeCtrlBase::OnCharHook
));
186 wxTreeCtrlBase::~wxTreeCtrlBase()
188 if (m_ownsImageListNormal
)
189 delete m_imageListNormal
;
190 if (m_ownsImageListState
)
191 delete m_imageListState
;
194 void wxTreeCtrlBase::SetItemState(const wxTreeItemId
& item
, int state
)
196 if ( state
== wxTREE_ITEMSTATE_NEXT
)
198 int current
= GetItemState(item
);
199 if ( current
== wxTREE_ITEMSTATE_NONE
)
202 if ( m_imageListState
&& state
>= m_imageListState
->GetImageCount() )
205 else if ( state
== wxTREE_ITEMSTATE_PREV
)
207 int current
= GetItemState(item
);
208 if ( current
== wxTREE_ITEMSTATE_NONE
)
212 state
= m_imageListState
? m_imageListState
->GetImageCount() - 1 : 0;
214 // else: wxTREE_ITEMSTATE_NONE depending on platform
216 DoSetItemState(item
, state
);
220 wxGetBestTreeSize(const wxTreeCtrlBase
* treeCtrl
, wxTreeItemId id
, wxSize
& size
)
224 if ( treeCtrl
->GetBoundingRect(id
, rect
, true /* just the item */) )
226 // Translate to logical position so we get the full extent
227 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
228 rect
.x
+= treeCtrl
->GetScrollPos(wxHORIZONTAL
);
229 rect
.y
+= treeCtrl
->GetScrollPos(wxVERTICAL
);
232 size
.IncTo(wxSize(rect
.GetRight(), rect
.GetBottom()));
235 wxTreeItemIdValue cookie
;
236 for ( wxTreeItemId item
= treeCtrl
->GetFirstChild(id
, cookie
);
238 item
= treeCtrl
->GetNextChild(id
, cookie
) )
240 wxGetBestTreeSize(treeCtrl
, item
, size
);
244 wxSize
wxTreeCtrlBase::DoGetBestSize() const
248 // this doesn't really compute the total bounding rectangle of all items
249 // but a not too bad guess of it which has the advantage of not having to
250 // examine all (potentially hundreds or thousands) items in the control
252 if (GetQuickBestSize())
254 for ( wxTreeItemId item
= GetRootItem();
256 item
= GetLastChild(item
) )
260 // last parameter is "true" to get only the dimensions of the text
261 // label, we don't want to get the entire item width as it's determined
262 // by the current size
263 if ( GetBoundingRect(item
, rect
, true) )
265 if ( size
.x
< rect
.x
+ rect
.width
)
266 size
.x
= rect
.x
+ rect
.width
;
267 if ( size
.y
< rect
.y
+ rect
.height
)
268 size
.y
= rect
.y
+ rect
.height
;
272 else // use precise, if potentially slow, size computation method
274 // iterate over all items recursively
275 wxTreeItemId idRoot
= GetRootItem();
277 wxGetBestTreeSize(this, idRoot
, size
);
280 // need some minimal size even for empty tree
281 if ( !size
.x
|| !size
.y
)
282 size
= wxControl::DoGetBestSize();
286 size
+= GetWindowBorderSize();
294 void wxTreeCtrlBase::ExpandAll()
299 ExpandAllChildren(GetRootItem());
302 void wxTreeCtrlBase::ExpandAllChildren(const wxTreeItemId
& item
)
305 // expand this item first, this might result in its children being added on
307 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
309 //else: expanding hidden root item is unsupported and unnecessary
311 // then (recursively) expand all the children
312 wxTreeItemIdValue cookie
;
313 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
315 idCurr
= GetNextChild(item
, cookie
) )
317 ExpandAllChildren(idCurr
);
322 void wxTreeCtrlBase::CollapseAll()
327 CollapseAllChildren(GetRootItem());
330 void wxTreeCtrlBase::CollapseAllChildren(const wxTreeItemId
& item
)
333 // first (recursively) collapse all the children
334 wxTreeItemIdValue cookie
;
335 for ( wxTreeItemId idCurr
= GetFirstChild(item
, cookie
);
337 idCurr
= GetNextChild(item
, cookie
) )
339 CollapseAllChildren(idCurr
);
342 // then collapse this element too unless it's the hidden root which can't
344 if ( item
!= GetRootItem() || !HasFlag(wxTR_HIDE_ROOT
) )
349 bool wxTreeCtrlBase::IsEmpty() const
351 return !GetRootItem().IsOk();
354 void wxTreeCtrlBase::OnCharHook(wxKeyEvent
& event
)
356 if ( GetEditControl() )
358 bool discardChanges
= false;
359 switch ( event
.GetKeyCode() )
362 discardChanges
= true;
366 EndEditLabel(GetFocusedItem(), discardChanges
);
368 // Do not call Skip() below.
376 #endif // wxUSE_TREECTRL