]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: treectrl.cpp | |
f135ff73 | 3 | // Purpose: generic tree control implementation |
c801d85f KB |
4 | // Author: Robert Roebling |
5 | // Created: 01/02/97 | |
f135ff73 | 6 | // Modified: 22/10/98 - almost total rewrite, simpler interface (VZ) |
389cdc7a | 7 | // Id: $Id$ |
c801d85f | 8 | // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem |
29d87bba | 9 | // Licence: wxWindows licence |
c801d85f KB |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
f135ff73 VZ |
12 | // ============================================================================= |
13 | // declarations | |
14 | // ============================================================================= | |
15 | ||
16 | // ----------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ----------------------------------------------------------------------------- | |
19 | ||
c801d85f | 20 | #ifdef __GNUG__ |
f135ff73 | 21 | #pragma implementation "treectrl.h" |
c801d85f KB |
22 | #endif |
23 | ||
24 | #include "wx/treectrl.h" | |
25 | #include "wx/settings.h" | |
389cdc7a | 26 | #include "wx/log.h" |
f135ff73 VZ |
27 | #include "wx/intl.h" |
28 | #include "wx/dynarray.h" | |
29 | #include "wx/dcclient.h" | |
df875e59 | 30 | #include "wx/imaglist.h" |
c801d85f | 31 | |
f135ff73 VZ |
32 | // ----------------------------------------------------------------------------- |
33 | // array types | |
34 | // ----------------------------------------------------------------------------- | |
c801d85f | 35 | |
f135ff73 | 36 | WX_DEFINE_ARRAY(wxGenericTreeItem *, wxArrayTreeItems); |
c801d85f | 37 | |
f135ff73 VZ |
38 | // ----------------------------------------------------------------------------- |
39 | // private classes | |
40 | // ----------------------------------------------------------------------------- | |
41 | ||
42 | // a tree item | |
43 | class WXDLLEXPORT wxGenericTreeItem | |
c801d85f | 44 | { |
f135ff73 VZ |
45 | public: |
46 | // ctors & dtor | |
47 | wxGenericTreeItem() { m_data = NULL; } | |
48 | wxGenericTreeItem( wxGenericTreeItem *parent, | |
49 | const wxString& text, | |
50 | wxDC& dc, | |
51 | int image, int selImage, | |
52 | wxTreeItemData *data ); | |
53 | ||
ff5bf259 | 54 | ~wxGenericTreeItem(); |
f135ff73 VZ |
55 | |
56 | // trivial accessors | |
57 | wxArrayTreeItems& GetChildren() { return m_children; } | |
58 | ||
59 | const wxString& GetText() const { return m_text; } | |
60 | int GetImage() const { return m_image; } | |
61 | int GetSelectedImage() const { return m_selImage; } | |
62 | wxTreeItemData *GetData() const { return m_data; } | |
63 | ||
64 | void SetText( const wxString &text, wxDC& dc ); | |
65 | void SetImage(int image) { m_image = image; } | |
66 | void SetSelectedImage(int image) { m_selImage = image; } | |
67 | void SetData(wxTreeItemData *data) { m_data = data; } | |
68 | ||
69 | void SetHasPlus(bool has = TRUE) { m_hasPlus = has; } | |
70 | ||
71 | int GetX() const { return m_x; } | |
72 | int GetY() const { return m_y; } | |
73 | ||
74 | void SetHeight(int h) { m_height = h; } | |
75 | ||
76 | void SetX(int x) { m_x = x; } | |
77 | void SetY(int y) { m_y = y; } | |
78 | ||
79 | wxGenericTreeItem *GetParent() const { return m_parent; } | |
c801d85f | 80 | |
f135ff73 VZ |
81 | // operations |
82 | void Reset(); | |
83 | ||
4832f7c0 VZ |
84 | // get count of all children (and grand children if 'recursively') |
85 | size_t GetChildrenCount(bool recursively = TRUE) const; | |
f135ff73 VZ |
86 | |
87 | void Insert(wxGenericTreeItem *child, size_t index) | |
88 | { m_children.Insert(child, index); } | |
89 | ||
90 | void SetCross( int x, int y ); | |
91 | void GetSize( int &x, int &y ); | |
92 | ||
93 | // return the item at given position (or NULL if no item), onButton is TRUE | |
94 | // if the point belongs to the item's button, otherwise it lies on the | |
95 | // button's label | |
96 | wxGenericTreeItem *HitTest( const wxPoint& point, bool &onButton ); | |
97 | ||
98 | void Expand() { m_isCollapsed = FALSE; } | |
99 | void Collapse() { m_isCollapsed = TRUE; } | |
100 | ||
101 | void SetHilight( bool set = TRUE ) { m_hasHilight = set; } | |
102 | ||
103 | // status inquiries | |
104 | bool HasChildren() const { return !m_children.IsEmpty(); } | |
105 | bool HasHilight() const { return m_hasHilight; } | |
106 | bool IsExpanded() const { return !m_isCollapsed; } | |
107 | bool HasPlus() const { return m_hasPlus || HasChildren(); } | |
108 | ||
109 | private: | |
110 | wxString m_text; | |
111 | ||
112 | int m_image, | |
113 | m_selImage; | |
114 | ||
115 | wxTreeItemData *m_data; | |
4832f7c0 | 116 | |
f135ff73 VZ |
117 | // @@ probably should use bitfields to save size |
118 | bool m_isCollapsed, | |
119 | m_hasHilight, // same as focused | |
120 | m_hasPlus; // used for item which doesn't have | |
121 | // children but still has a [+] button | |
122 | ||
123 | int m_x, m_y; | |
124 | long m_height, m_width; | |
125 | int m_xCross, m_yCross; | |
126 | int m_level; | |
127 | wxArrayTreeItems m_children; | |
128 | wxGenericTreeItem *m_parent; | |
129 | }; | |
130 | ||
131 | // ============================================================================= | |
132 | // implementation | |
133 | // ============================================================================= | |
134 | ||
135 | // ----------------------------------------------------------------------------- | |
c801d85f | 136 | // wxTreeEvent |
f135ff73 | 137 | // ----------------------------------------------------------------------------- |
c801d85f | 138 | |
f135ff73 | 139 | IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent) |
c801d85f | 140 | |
f135ff73 VZ |
141 | wxTreeEvent::wxTreeEvent( wxEventType commandType, int id ) |
142 | : wxCommandEvent( commandType, id ) | |
c801d85f KB |
143 | { |
144 | m_code = 0; | |
f135ff73 | 145 | m_itemOld = (wxGenericTreeItem *)NULL; |
edaa81ae | 146 | } |
c801d85f | 147 | |
f135ff73 | 148 | // ----------------------------------------------------------------------------- |
c801d85f | 149 | // wxGenericTreeItem |
f135ff73 | 150 | // ----------------------------------------------------------------------------- |
c801d85f | 151 | |
f135ff73 VZ |
152 | wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent, |
153 | const wxString& text, | |
154 | wxDC& dc, | |
155 | int image, int selImage, | |
156 | wxTreeItemData *data) | |
157 | : m_text(text) | |
c801d85f | 158 | { |
f135ff73 VZ |
159 | m_image = image; |
160 | m_selImage = selImage; | |
161 | m_data = data; | |
162 | m_x = m_y = 0; | |
163 | m_xCross = m_yCross = 0; | |
164 | ||
165 | m_level = 0; | |
166 | ||
167 | m_isCollapsed = TRUE; | |
c801d85f | 168 | m_hasHilight = FALSE; |
df875e59 | 169 | m_hasPlus = FALSE; |
c801d85f | 170 | |
c801d85f | 171 | m_parent = parent; |
f135ff73 VZ |
172 | |
173 | dc.GetTextExtent( m_text, &m_width, &m_height ); | |
edaa81ae | 174 | } |
c801d85f | 175 | |
f135ff73 | 176 | wxGenericTreeItem::~wxGenericTreeItem() |
c801d85f | 177 | { |
f135ff73 | 178 | delete m_data; |
4832f7c0 | 179 | |
f135ff73 VZ |
180 | size_t count = m_children.Count(); |
181 | for ( size_t n = 0; n < count; n++ ) | |
182 | delete m_children[n]; | |
edaa81ae | 183 | } |
c801d85f | 184 | |
f135ff73 | 185 | void wxGenericTreeItem::SetText( const wxString &text, wxDC& dc ) |
c801d85f KB |
186 | { |
187 | m_text = text; | |
f135ff73 VZ |
188 | |
189 | dc.GetTextExtent( m_text, &m_width, &m_height ); | |
edaa81ae | 190 | } |
c801d85f | 191 | |
74bedbeb | 192 | void wxGenericTreeItem::Reset() |
c801d85f | 193 | { |
f135ff73 VZ |
194 | m_text.Empty(); |
195 | m_image = | |
196 | m_selImage = -1; | |
197 | m_data = NULL; | |
198 | m_x = m_y = | |
199 | m_height = m_width = 0; | |
200 | m_xCross = | |
c801d85f | 201 | m_yCross = 0; |
74bedbeb | 202 | |
f135ff73 | 203 | m_level = 0; |
c801d85f | 204 | |
f135ff73 VZ |
205 | m_children.Empty(); |
206 | m_isCollapsed = TRUE; | |
c801d85f | 207 | |
f135ff73 | 208 | m_parent = (wxGenericTreeItem *)NULL; |
edaa81ae | 209 | } |
c801d85f | 210 | |
4832f7c0 | 211 | size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const |
c801d85f | 212 | { |
f135ff73 | 213 | size_t count = m_children.Count(); |
4832f7c0 VZ |
214 | if ( !recursively ) |
215 | return count; | |
216 | ||
f135ff73 VZ |
217 | size_t total = count; |
218 | for ( size_t n = 0; n < count; n++ ) | |
c801d85f | 219 | { |
4832f7c0 | 220 | total += m_children[n]->GetChildrenCount(); |
edaa81ae | 221 | } |
c801d85f | 222 | |
f135ff73 | 223 | return total; |
edaa81ae | 224 | } |
c801d85f KB |
225 | |
226 | void wxGenericTreeItem::SetCross( int x, int y ) | |
227 | { | |
228 | m_xCross = x; | |
229 | m_yCross = y; | |
edaa81ae | 230 | } |
c801d85f KB |
231 | |
232 | void wxGenericTreeItem::GetSize( int &x, int &y ) | |
233 | { | |
df875e59 | 234 | if ( y < m_y ) y = m_y; |
c801d85f KB |
235 | int width = m_x + m_width; |
236 | if (width > x) x = width; | |
f135ff73 | 237 | |
df875e59 | 238 | if (IsExpanded()) |
c801d85f | 239 | { |
df875e59 RR |
240 | size_t count = m_children.Count(); |
241 | for ( size_t n = 0; n < count; n++ ) | |
4832f7c0 | 242 | { |
df875e59 RR |
243 | m_children[n]->GetSize( x, y ); |
244 | } | |
edaa81ae RR |
245 | } |
246 | } | |
c801d85f | 247 | |
f135ff73 VZ |
248 | wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point, |
249 | bool &onButton ) | |
c801d85f | 250 | { |
f135ff73 | 251 | if ((point.y > m_y) && (point.y < m_y + m_height)) |
c801d85f | 252 | { |
f135ff73 VZ |
253 | // FIXME why +5? |
254 | if ((point.x > m_xCross-5) && (point.x < m_xCross+5) && | |
255 | (point.y > m_yCross-5) && (point.y < m_yCross+5) && | |
f9f950fc | 256 | (IsExpanded() || HasPlus())) |
c801d85f | 257 | { |
f135ff73 VZ |
258 | onButton = TRUE; |
259 | return this; | |
edaa81ae | 260 | } |
f135ff73 | 261 | |
c801d85f KB |
262 | if ((point.x > m_x) && (point.x < m_x+m_width)) |
263 | { | |
f135ff73 VZ |
264 | onButton = FALSE; |
265 | return this; | |
edaa81ae | 266 | } |
c801d85f KB |
267 | } |
268 | else | |
269 | { | |
e2414cbe | 270 | if (!m_isCollapsed) |
c801d85f | 271 | { |
f135ff73 VZ |
272 | size_t count = m_children.Count(); |
273 | for ( size_t n = 0; n < count; n++ ) | |
e2414cbe | 274 | { |
f135ff73 VZ |
275 | wxGenericTreeItem *res = m_children[n]->HitTest( point, onButton ); |
276 | if ( res != NULL ) | |
277 | return res; | |
edaa81ae RR |
278 | } |
279 | } | |
280 | } | |
f135ff73 VZ |
281 | |
282 | return NULL; | |
edaa81ae | 283 | } |
c801d85f | 284 | |
f135ff73 VZ |
285 | // ----------------------------------------------------------------------------- |
286 | // wxTreeCtrl implementation | |
287 | // ----------------------------------------------------------------------------- | |
288 | ||
289 | IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxScrolledWindow) | |
290 | ||
291 | BEGIN_EVENT_TABLE(wxTreeCtrl,wxScrolledWindow) | |
292 | EVT_PAINT (wxTreeCtrl::OnPaint) | |
293 | EVT_MOUSE_EVENTS (wxTreeCtrl::OnMouse) | |
294 | EVT_CHAR (wxTreeCtrl::OnChar) | |
295 | EVT_SET_FOCUS (wxTreeCtrl::OnSetFocus) | |
296 | EVT_KILL_FOCUS (wxTreeCtrl::OnKillFocus) | |
3db7be80 | 297 | EVT_IDLE (wxTreeCtrl::OnIdle) |
f135ff73 VZ |
298 | END_EVENT_TABLE() |
299 | ||
300 | // ----------------------------------------------------------------------------- | |
301 | // construction/destruction | |
302 | // ----------------------------------------------------------------------------- | |
303 | void wxTreeCtrl::Init() | |
c801d85f | 304 | { |
f135ff73 VZ |
305 | m_current = |
306 | m_anchor = (wxGenericTreeItem *) NULL; | |
307 | m_hasFocus = FALSE; | |
3db7be80 | 308 | m_dirty = FALSE; |
f135ff73 VZ |
309 | |
310 | m_xScroll = 0; | |
311 | m_yScroll = 0; | |
312 | m_lineHeight = 10; | |
313 | m_indent = 15; | |
314 | ||
315 | m_hilightBrush = new wxBrush | |
316 | ( | |
317 | wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), | |
318 | wxSOLID | |
319 | ); | |
320 | ||
321 | m_imageListNormal = | |
322 | m_imageListState = (wxImageList *) NULL; | |
edaa81ae | 323 | } |
c801d85f | 324 | |
f135ff73 VZ |
325 | bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id, |
326 | const wxPoint& pos, const wxSize& size, | |
327 | long style, const wxString& name ) | |
c801d85f | 328 | { |
f135ff73 VZ |
329 | Init(); |
330 | ||
331 | wxScrolledWindow::Create( parent, id, pos, size, style, name ); | |
332 | ||
333 | SetBackgroundColour( *wxWHITE ); | |
334 | m_dottedPen = wxPen( *wxBLACK, 0, 0 ); | |
335 | ||
336 | return TRUE; | |
edaa81ae | 337 | } |
c801d85f | 338 | |
f135ff73 | 339 | wxTreeCtrl::~wxTreeCtrl() |
c801d85f | 340 | { |
f135ff73 VZ |
341 | wxDELETE( m_hilightBrush ); |
342 | wxDELETE( m_anchor ); | |
edaa81ae | 343 | } |
c801d85f | 344 | |
f135ff73 VZ |
345 | // ----------------------------------------------------------------------------- |
346 | // accessors | |
347 | // ----------------------------------------------------------------------------- | |
348 | ||
349 | size_t wxTreeCtrl::GetCount() const | |
c801d85f | 350 | { |
4832f7c0 | 351 | return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount(); |
edaa81ae | 352 | } |
c801d85f | 353 | |
f135ff73 | 354 | void wxTreeCtrl::SetIndent(unsigned int indent) |
c801d85f | 355 | { |
f135ff73 VZ |
356 | m_indent = indent; |
357 | Refresh(); | |
358 | } | |
74bedbeb | 359 | |
4832f7c0 VZ |
360 | size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively) |
361 | { | |
362 | wxCHECK_MSG( item.IsOk(), 0u, "invalid tree item" ); | |
363 | ||
364 | return item.m_pItem->GetChildrenCount(recursively); | |
365 | } | |
366 | ||
f135ff73 VZ |
367 | // ----------------------------------------------------------------------------- |
368 | // functions to work with tree items | |
369 | // ----------------------------------------------------------------------------- | |
74bedbeb | 370 | |
f135ff73 VZ |
371 | wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const |
372 | { | |
4832f7c0 VZ |
373 | wxCHECK_MSG( item.IsOk(), "", "invalid tree item" ); |
374 | ||
f135ff73 | 375 | return item.m_pItem->GetText(); |
edaa81ae | 376 | } |
74bedbeb | 377 | |
f135ff73 | 378 | int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const |
74bedbeb | 379 | { |
4832f7c0 VZ |
380 | wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); |
381 | ||
f135ff73 | 382 | return item.m_pItem->GetImage(); |
edaa81ae | 383 | } |
c801d85f | 384 | |
f135ff73 | 385 | int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const |
c801d85f | 386 | { |
4832f7c0 VZ |
387 | wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); |
388 | ||
f135ff73 | 389 | return item.m_pItem->GetSelectedImage(); |
edaa81ae | 390 | } |
c801d85f | 391 | |
f135ff73 | 392 | wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const |
c801d85f | 393 | { |
4832f7c0 VZ |
394 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); |
395 | ||
f135ff73 | 396 | return item.m_pItem->GetData(); |
edaa81ae | 397 | } |
c801d85f | 398 | |
f135ff73 VZ |
399 | void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) |
400 | { | |
4832f7c0 VZ |
401 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
402 | ||
f135ff73 | 403 | wxClientDC dc(this); |
de646ed1 | 404 | item.m_pItem->SetText(text, dc); |
f135ff73 | 405 | } |
c801d85f | 406 | |
f135ff73 VZ |
407 | void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image) |
408 | { | |
4832f7c0 VZ |
409 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
410 | ||
de646ed1 | 411 | item.m_pItem->SetImage(image); |
f135ff73 | 412 | } |
c801d85f | 413 | |
f135ff73 | 414 | void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image) |
c801d85f | 415 | { |
4832f7c0 VZ |
416 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
417 | ||
de646ed1 | 418 | item.m_pItem->SetSelectedImage(image); |
edaa81ae | 419 | } |
c801d85f | 420 | |
f135ff73 | 421 | void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) |
c801d85f | 422 | { |
4832f7c0 VZ |
423 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
424 | ||
de646ed1 | 425 | item.m_pItem->SetData(data); |
edaa81ae | 426 | } |
c801d85f | 427 | |
f135ff73 | 428 | void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) |
c801d85f | 429 | { |
4832f7c0 VZ |
430 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
431 | ||
f135ff73 | 432 | item.m_pItem->SetHasPlus(has); |
edaa81ae | 433 | } |
c801d85f | 434 | |
f135ff73 VZ |
435 | // ----------------------------------------------------------------------------- |
436 | // item status inquiries | |
437 | // ----------------------------------------------------------------------------- | |
438 | ||
df875e59 | 439 | bool wxTreeCtrl::IsVisible(const wxTreeItemId& WXUNUSED(item)) const |
c801d85f | 440 | { |
f135ff73 VZ |
441 | wxFAIL_MSG("not implemented"); |
442 | ||
c801d85f | 443 | return TRUE; |
edaa81ae | 444 | } |
c801d85f | 445 | |
f135ff73 | 446 | bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const |
c801d85f | 447 | { |
4832f7c0 VZ |
448 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
449 | ||
f135ff73 | 450 | return !item.m_pItem->GetChildren().IsEmpty(); |
edaa81ae | 451 | } |
c801d85f | 452 | |
f135ff73 | 453 | bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const |
c801d85f | 454 | { |
4832f7c0 VZ |
455 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
456 | ||
f135ff73 VZ |
457 | return item.m_pItem->IsExpanded(); |
458 | } | |
29d87bba | 459 | |
f135ff73 VZ |
460 | bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const |
461 | { | |
4832f7c0 VZ |
462 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
463 | ||
f135ff73 VZ |
464 | return item.m_pItem->HasHilight(); |
465 | } | |
29d87bba | 466 | |
f135ff73 VZ |
467 | // ----------------------------------------------------------------------------- |
468 | // navigation | |
469 | // ----------------------------------------------------------------------------- | |
29d87bba | 470 | |
f135ff73 VZ |
471 | wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const |
472 | { | |
473 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
389cdc7a | 474 | |
f135ff73 VZ |
475 | return item.m_pItem->GetParent(); |
476 | } | |
29d87bba | 477 | |
f135ff73 VZ |
478 | wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) const |
479 | { | |
480 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 481 | |
f135ff73 VZ |
482 | cookie = 0; |
483 | return GetNextChild(item, cookie); | |
484 | } | |
29d87bba | 485 | |
f135ff73 VZ |
486 | wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) const |
487 | { | |
488 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 489 | |
4832f7c0 VZ |
490 | wxArrayTreeItems& children = item.m_pItem->GetChildren(); |
491 | if ( (size_t)cookie < children.Count() ) | |
492 | { | |
493 | return item.m_pItem->GetChildren().Item(cookie++); | |
494 | } | |
495 | else | |
496 | { | |
497 | // there are no more of them | |
498 | return NULL; | |
499 | } | |
f135ff73 | 500 | } |
29d87bba | 501 | |
f135ff73 VZ |
502 | wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const |
503 | { | |
504 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
505 | ||
506 | wxGenericTreeItem *i = item.m_pItem; | |
507 | wxGenericTreeItem *parent = i->GetParent(); | |
508 | if ( parent == NULL ) | |
509 | { | |
510 | // root item doesn't have any siblings | |
511 | return NULL; | |
edaa81ae | 512 | } |
4832f7c0 | 513 | |
f135ff73 VZ |
514 | wxArrayTreeItems& siblings = parent->GetChildren(); |
515 | int index = siblings.Index(i); | |
516 | wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? | |
29d87bba | 517 | |
f135ff73 | 518 | size_t n = (size_t)(index + 1); |
de646ed1 | 519 | return n == siblings.Count() ? (wxGenericTreeItem*)NULL : siblings[n]; |
edaa81ae | 520 | } |
c801d85f | 521 | |
f135ff73 | 522 | wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const |
c801d85f | 523 | { |
f135ff73 VZ |
524 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); |
525 | ||
526 | wxGenericTreeItem *i = item.m_pItem; | |
527 | wxGenericTreeItem *parent = i->GetParent(); | |
528 | if ( parent == NULL ) | |
c801d85f | 529 | { |
f135ff73 VZ |
530 | // root item doesn't have any siblings |
531 | return NULL; | |
edaa81ae | 532 | } |
4832f7c0 | 533 | |
f135ff73 VZ |
534 | wxArrayTreeItems& siblings = parent->GetChildren(); |
535 | int index = siblings.Index(i); | |
536 | wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? | |
29d87bba | 537 | |
de646ed1 | 538 | return index == 0 ? (wxGenericTreeItem*)NULL : siblings[(size_t)(index - 1)]; |
f135ff73 | 539 | } |
389cdc7a | 540 | |
f135ff73 VZ |
541 | wxTreeItemId wxTreeCtrl::GetFirstVisibleItem() const |
542 | { | |
543 | wxFAIL_MSG("not implemented"); | |
29d87bba | 544 | |
f135ff73 VZ |
545 | return NULL; |
546 | } | |
29d87bba | 547 | |
f135ff73 VZ |
548 | wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const |
549 | { | |
550 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 551 | |
f135ff73 | 552 | wxFAIL_MSG("not implemented"); |
29d87bba | 553 | |
f135ff73 VZ |
554 | return NULL; |
555 | } | |
29d87bba | 556 | |
f135ff73 VZ |
557 | wxTreeItemId wxTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const |
558 | { | |
559 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 560 | |
f135ff73 | 561 | wxFAIL_MSG("not implemented"); |
29d87bba | 562 | |
f135ff73 | 563 | return NULL; |
edaa81ae | 564 | } |
c801d85f | 565 | |
f135ff73 VZ |
566 | // ----------------------------------------------------------------------------- |
567 | // operations | |
568 | // ----------------------------------------------------------------------------- | |
569 | ||
570 | wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, | |
571 | size_t previous, | |
572 | const wxString& text, | |
573 | int image, int selImage, | |
574 | wxTreeItemData *data) | |
c801d85f | 575 | { |
f135ff73 VZ |
576 | wxGenericTreeItem *parent = parentId.m_pItem; |
577 | if ( !parent ) | |
578 | { | |
579 | // should we give a warning here? | |
580 | return AddRoot(text, image, selImage, data); | |
581 | } | |
4832f7c0 | 582 | |
f135ff73 VZ |
583 | wxClientDC dc(this); |
584 | wxGenericTreeItem *item = new wxGenericTreeItem(parent, | |
585 | text, dc, | |
586 | image, selImage, | |
587 | data); | |
74bedbeb | 588 | |
f135ff73 | 589 | if ( data != NULL ) |
c801d85f | 590 | { |
f135ff73 VZ |
591 | data->m_pItem = item; |
592 | } | |
74bedbeb | 593 | |
f135ff73 | 594 | parent->Insert( item, previous ); |
3db7be80 RR |
595 | |
596 | m_dirty = TRUE; | |
389cdc7a | 597 | |
f135ff73 | 598 | return item; |
4c681997 RR |
599 | } |
600 | ||
f135ff73 VZ |
601 | wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text, |
602 | int image, int selImage, | |
603 | wxTreeItemData *data) | |
4c681997 | 604 | { |
f135ff73 | 605 | wxCHECK_MSG( !m_anchor, NULL, "tree can have only one root" ); |
389cdc7a | 606 | |
f135ff73 VZ |
607 | wxClientDC dc(this); |
608 | m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, dc, | |
609 | image, selImage, data); | |
610 | if ( data != NULL ) | |
611 | { | |
612 | data->m_pItem = m_anchor; | |
613 | } | |
389cdc7a | 614 | |
f135ff73 | 615 | AdjustMyScrollbars(); |
a32dd690 | 616 | Refresh(); |
a32dd690 | 617 | |
f135ff73 | 618 | return m_anchor; |
edaa81ae | 619 | } |
c801d85f | 620 | |
f135ff73 VZ |
621 | wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent, |
622 | const wxString& text, | |
623 | int image, int selImage, | |
624 | wxTreeItemData *data) | |
c801d85f | 625 | { |
f135ff73 | 626 | return DoInsertItem(parent, 0u, text, image, selImage, data); |
edaa81ae | 627 | } |
c801d85f | 628 | |
f135ff73 VZ |
629 | wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parentId, |
630 | const wxTreeItemId& idPrevious, | |
631 | const wxString& text, | |
632 | int image, int selImage, | |
633 | wxTreeItemData *data) | |
c801d85f | 634 | { |
f135ff73 VZ |
635 | wxGenericTreeItem *parent = parentId.m_pItem; |
636 | if ( !parent ) | |
637 | { | |
638 | // should we give a warning here? | |
639 | return AddRoot(text, image, selImage, data); | |
640 | } | |
c801d85f | 641 | |
f135ff73 VZ |
642 | int index = parent->GetChildren().Index(idPrevious.m_pItem); |
643 | wxASSERT_MSG( index != NOT_FOUND, | |
644 | "previous item in wxTreeCtrl::InsertItem() is not a sibling" ); | |
645 | return DoInsertItem(parentId, (size_t)index, text, image, selImage, data); | |
edaa81ae | 646 | } |
c801d85f | 647 | |
f135ff73 VZ |
648 | wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parentId, |
649 | const wxString& text, | |
650 | int image, int selImage, | |
651 | wxTreeItemData *data) | |
74bedbeb | 652 | { |
f135ff73 VZ |
653 | wxGenericTreeItem *parent = parentId.m_pItem; |
654 | if ( !parent ) | |
655 | { | |
656 | // should we give a warning here? | |
657 | return AddRoot(text, image, selImage, data); | |
658 | } | |
659 | ||
660 | return DoInsertItem(parent, parent->GetChildren().Count(), text, | |
661 | image, selImage, data); | |
74bedbeb VZ |
662 | } |
663 | ||
f135ff73 | 664 | void wxTreeCtrl::Delete(const wxTreeItemId& itemId) |
c801d85f | 665 | { |
f135ff73 | 666 | wxGenericTreeItem *item = itemId.m_pItem; |
ff5bf259 VZ |
667 | wxGenericTreeItem *parent = item->GetParent(); |
668 | ||
669 | if ( parent ) | |
670 | { | |
671 | parent->GetChildren().Remove(item); | |
672 | } | |
f135ff73 VZ |
673 | |
674 | delete item; | |
675 | ||
676 | Refresh(); | |
edaa81ae | 677 | } |
c801d85f | 678 | |
f135ff73 | 679 | void wxTreeCtrl::DeleteAllItems() |
c801d85f | 680 | { |
f135ff73 VZ |
681 | if ( m_anchor ) |
682 | { | |
683 | delete m_anchor; | |
684 | m_anchor = NULL; | |
685 | ||
686 | Refresh(); | |
687 | } | |
edaa81ae RR |
688 | } |
689 | ||
f135ff73 | 690 | void wxTreeCtrl::Expand(const wxTreeItemId& itemId) |
edaa81ae | 691 | { |
f135ff73 VZ |
692 | wxGenericTreeItem *item = itemId.m_pItem; |
693 | ||
694 | if ( item->IsExpanded() ) | |
695 | return; | |
696 | ||
697 | wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, GetId() ); | |
698 | event.m_item = item; | |
699 | event.SetEventObject( this ); | |
700 | if ( ProcessEvent( event ) && event.m_code ) | |
701 | { | |
702 | // cancelled by program | |
703 | return; | |
704 | } | |
4832f7c0 | 705 | |
f135ff73 VZ |
706 | item->Expand(); |
707 | ||
708 | RefreshSubtree(item); | |
709 | ||
710 | event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); | |
711 | ProcessEvent( event ); | |
edaa81ae RR |
712 | } |
713 | ||
f135ff73 | 714 | void wxTreeCtrl::Collapse(const wxTreeItemId& itemId) |
edaa81ae | 715 | { |
f135ff73 VZ |
716 | wxGenericTreeItem *item = itemId.m_pItem; |
717 | ||
718 | if ( !item->IsExpanded() ) | |
719 | return; | |
720 | ||
721 | wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, GetId() ); | |
722 | event.m_item = item; | |
723 | event.SetEventObject( this ); | |
724 | if ( ProcessEvent( event ) && event.m_code ) | |
edaa81ae | 725 | { |
f135ff73 VZ |
726 | // cancelled by program |
727 | return; | |
728 | } | |
4832f7c0 | 729 | |
f135ff73 VZ |
730 | item->Collapse(); |
731 | ||
732 | wxArrayTreeItems& children = item->GetChildren(); | |
733 | size_t count = children.Count(); | |
734 | for ( size_t n = 0; n < count; n++ ) | |
735 | { | |
736 | Collapse(children[n]); | |
edaa81ae | 737 | } |
f135ff73 VZ |
738 | |
739 | CalculatePositions(); | |
740 | ||
741 | RefreshSubtree(item); | |
742 | ||
743 | event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED); | |
744 | ProcessEvent( event ); | |
edaa81ae | 745 | } |
c801d85f | 746 | |
f135ff73 | 747 | void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item) |
c801d85f | 748 | { |
f135ff73 VZ |
749 | Collapse(item); |
750 | Delete(item); | |
edaa81ae | 751 | } |
c801d85f | 752 | |
f135ff73 | 753 | void wxTreeCtrl::Toggle(const wxTreeItemId& itemId) |
c801d85f | 754 | { |
f135ff73 | 755 | wxGenericTreeItem *item = itemId.m_pItem; |
389cdc7a | 756 | |
f135ff73 VZ |
757 | if ( item->IsExpanded() ) |
758 | Collapse(itemId); | |
759 | else | |
760 | Expand(itemId); | |
761 | } | |
389cdc7a | 762 | |
f135ff73 VZ |
763 | void wxTreeCtrl::Unselect() |
764 | { | |
765 | if ( m_current ) | |
766 | { | |
767 | m_current->SetHilight( FALSE ); | |
768 | RefreshLine( m_current ); | |
769 | } | |
edaa81ae | 770 | } |
c801d85f | 771 | |
f135ff73 | 772 | void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId) |
389cdc7a | 773 | { |
f135ff73 VZ |
774 | wxGenericTreeItem *item = itemId.m_pItem; |
775 | ||
776 | if ( m_current != item ) | |
389cdc7a | 777 | { |
f135ff73 VZ |
778 | wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() ); |
779 | event.m_item = item; | |
780 | event.m_itemOld = m_current; | |
781 | event.SetEventObject( this ); | |
782 | if ( ProcessEvent( event ) && event.WasVetoed() ) | |
783 | return; | |
784 | ||
785 | if ( m_current ) | |
389cdc7a VZ |
786 | { |
787 | m_current->SetHilight( FALSE ); | |
788 | RefreshLine( m_current ); | |
edaa81ae | 789 | } |
f135ff73 | 790 | |
389cdc7a VZ |
791 | m_current = item; |
792 | m_current->SetHilight( TRUE ); | |
793 | RefreshLine( m_current ); | |
794 | ||
f135ff73 VZ |
795 | event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); |
796 | ProcessEvent( event ); | |
389cdc7a VZ |
797 | } |
798 | } | |
799 | ||
df875e59 | 800 | void wxTreeCtrl::EnsureVisible(const wxTreeItemId& WXUNUSED(item)) |
c801d85f | 801 | { |
f135ff73 | 802 | wxFAIL_MSG("not implemented"); |
edaa81ae | 803 | } |
c801d85f | 804 | |
df875e59 | 805 | void wxTreeCtrl::ScrollTo(const wxTreeItemId& WXUNUSED(item)) |
c801d85f | 806 | { |
f135ff73 | 807 | wxFAIL_MSG("not implemented"); |
edaa81ae | 808 | } |
c801d85f | 809 | |
df875e59 RR |
810 | wxTextCtrl *wxTreeCtrl::EditLabel( const wxTreeItemId& WXUNUSED(item), |
811 | wxClassInfo* WXUNUSED(textCtrlClass) ) | |
c801d85f | 812 | { |
f135ff73 | 813 | wxFAIL_MSG("not implemented"); |
c801d85f | 814 | |
f135ff73 | 815 | return NULL; |
edaa81ae | 816 | } |
c801d85f | 817 | |
f135ff73 | 818 | wxTextCtrl *wxTreeCtrl::GetEditControl() const |
c801d85f | 819 | { |
f135ff73 | 820 | wxFAIL_MSG("not implemented"); |
c801d85f | 821 | |
f135ff73 | 822 | return NULL; |
edaa81ae | 823 | } |
c801d85f | 824 | |
df875e59 | 825 | void wxTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item), bool WXUNUSED(discardChanges)) |
74bedbeb | 826 | { |
f135ff73 | 827 | wxFAIL_MSG("not implemented"); |
74bedbeb VZ |
828 | } |
829 | ||
df875e59 RR |
830 | void wxTreeCtrl::SortChildren( const wxTreeItemId& WXUNUSED(item), |
831 | wxTreeItemCmpFunc *WXUNUSED(cmpFunction)) | |
edaa81ae | 832 | { |
f135ff73 | 833 | wxFAIL_MSG("not implemented"); |
edaa81ae RR |
834 | } |
835 | ||
f135ff73 | 836 | wxImageList *wxTreeCtrl::GetImageList() const |
edaa81ae | 837 | { |
f135ff73 | 838 | return m_imageListNormal; |
edaa81ae RR |
839 | } |
840 | ||
f135ff73 | 841 | wxImageList *wxTreeCtrl::GetStateImageList() const |
c801d85f | 842 | { |
f135ff73 | 843 | return m_imageListState; |
edaa81ae | 844 | } |
c801d85f | 845 | |
f135ff73 | 846 | void wxTreeCtrl::SetImageList(wxImageList *imageList) |
e2414cbe | 847 | { |
f135ff73 | 848 | m_imageListNormal = imageList; |
edaa81ae | 849 | } |
e2414cbe | 850 | |
f135ff73 | 851 | void wxTreeCtrl::SetStateImageList(wxImageList *imageList) |
e2414cbe | 852 | { |
f135ff73 | 853 | m_imageListState = imageList; |
edaa81ae | 854 | } |
e2414cbe | 855 | |
f135ff73 VZ |
856 | // ----------------------------------------------------------------------------- |
857 | // helpers | |
858 | // ----------------------------------------------------------------------------- | |
74bedbeb | 859 | void wxTreeCtrl::AdjustMyScrollbars() |
c801d85f KB |
860 | { |
861 | if (m_anchor) | |
862 | { | |
863 | int x = 0; | |
864 | int y = 0; | |
865 | m_anchor->GetSize( x, y ); | |
866 | y += 2*m_lineHeight; | |
867 | int x_pos = GetScrollPos( wxHORIZONTAL ); | |
868 | int y_pos = GetScrollPos( wxVERTICAL ); | |
869 | SetScrollbars( 10, 10, x/10, y/10, x_pos, y_pos ); | |
870 | } | |
871 | else | |
872 | { | |
873 | SetScrollbars( 0, 0, 0, 0 ); | |
edaa81ae RR |
874 | } |
875 | } | |
c801d85f | 876 | |
16c1f7f3 | 877 | void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &y ) |
c801d85f | 878 | { |
4c681997 | 879 | int horizX = level*m_indent; |
389cdc7a | 880 | |
f135ff73 VZ |
881 | item->SetX( horizX+33 ); |
882 | item->SetY( y-m_lineHeight/3 ); | |
883 | item->SetHeight( m_lineHeight ); | |
389cdc7a | 884 | |
4c681997 RR |
885 | item->SetCross( horizX+15, y ); |
886 | ||
c801d85f | 887 | int oldY = y; |
389cdc7a | 888 | |
d4c99d6f | 889 | int exposed_x = dc.LogicalToDeviceX( 0 ); |
f135ff73 | 890 | int exposed_y = dc.LogicalToDeviceY( item->GetY()-2 ); |
4832f7c0 | 891 | |
df875e59 | 892 | if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 )) // 10000 = very much |
c801d85f | 893 | { |
4c681997 RR |
894 | int startX = horizX; |
895 | int endX = horizX + 10; | |
29d87bba | 896 | |
4c681997 | 897 | if (!item->HasChildren()) endX += 20; |
4832f7c0 | 898 | |
389cdc7a | 899 | dc.DrawLine( startX, y, endX, y ); |
29d87bba | 900 | |
f135ff73 VZ |
901 | if (item->HasPlus()) |
902 | { | |
903 | dc.DrawLine( horizX+20, y, horizX+30, y ); | |
904 | dc.SetPen( *wxGREY_PEN ); | |
905 | dc.DrawRectangle( horizX+10, y-4, 11, 9 ); | |
906 | dc.SetPen( *wxBLACK_PEN ); | |
907 | dc.DrawLine( horizX+13, y, horizX+18, y ); | |
908 | ||
909 | if (!item->IsExpanded()) | |
910 | dc.DrawLine( horizX+15, y-2, horizX+15, y+3 ); | |
911 | } | |
c801d85f | 912 | |
f135ff73 VZ |
913 | if (item->HasHilight()) |
914 | { | |
915 | dc.SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); | |
916 | dc.SetBrush( *m_hilightBrush ); | |
4832f7c0 | 917 | |
df875e59 RR |
918 | long text_w = 0; |
919 | long text_h = 0; | |
920 | dc.GetTextExtent( item->GetText(), &text_w, &text_h ); | |
4832f7c0 | 921 | |
df875e59 RR |
922 | int image_h = 0; |
923 | int image_w = 0; | |
924 | if (item->GetImage() != -1) | |
c801d85f | 925 | { |
df875e59 RR |
926 | m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); |
927 | image_w += 4; | |
29d87bba | 928 | } |
4832f7c0 | 929 | |
df875e59 RR |
930 | if (m_hasFocus) |
931 | dc.SetPen( *wxBLACK_PEN ); | |
29d87bba | 932 | else |
389cdc7a | 933 | dc.SetPen( *wxTRANSPARENT_PEN ); |
4832f7c0 | 934 | |
df875e59 | 935 | dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); |
4832f7c0 | 936 | |
df875e59 RR |
937 | if (item->GetImage() != -1) |
938 | { | |
939 | dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); | |
940 | m_imageListNormal->Draw( item->GetImage(), dc, item->GetX(), item->GetY()-1, wxIMAGELIST_DRAW_TRANSPARENT ); | |
941 | dc.DestroyClippingRegion(); | |
edaa81ae | 942 | } |
df875e59 | 943 | dc.DrawText( item->GetText(), image_w+item->GetX(), item->GetY() ); |
f135ff73 VZ |
944 | |
945 | dc.SetPen( *wxBLACK_PEN ); | |
946 | dc.SetTextForeground( *wxBLACK ); | |
947 | dc.SetBrush( *wxWHITE_BRUSH ); | |
948 | } | |
949 | else | |
950 | { | |
951 | dc.SetBrush( *wxWHITE_BRUSH ); | |
952 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
4832f7c0 | 953 | |
df875e59 RR |
954 | long text_w = 0; |
955 | long text_h = 0; | |
956 | dc.GetTextExtent( item->GetText(), &text_w, &text_h ); | |
4832f7c0 | 957 | |
df875e59 RR |
958 | int image_h = 0; |
959 | int image_w = 0; | |
960 | if (item->GetImage() != -1) | |
961 | { | |
962 | m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); | |
963 | image_w += 4; | |
964 | } | |
4832f7c0 | 965 | |
df875e59 | 966 | dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); |
4832f7c0 | 967 | |
df875e59 RR |
968 | if (item->GetImage() != -1) |
969 | { | |
970 | dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); | |
971 | m_imageListNormal->Draw( item->GetImage(), dc, item->GetX(), item->GetY()-1, wxIMAGELIST_DRAW_TRANSPARENT ); | |
972 | dc.DestroyClippingRegion(); | |
973 | } | |
4832f7c0 | 974 | |
df875e59 | 975 | dc.DrawText( item->GetText(), image_w+item->GetX(), item->GetY() ); |
f135ff73 VZ |
976 | dc.SetPen( *wxBLACK_PEN ); |
977 | } | |
edaa81ae | 978 | } |
4c681997 | 979 | |
f135ff73 VZ |
980 | if ( !item->IsExpanded() ) |
981 | return; | |
e2414cbe | 982 | |
389cdc7a VZ |
983 | int semiOldY = y; |
984 | ||
f135ff73 VZ |
985 | wxArrayTreeItems& children = item->GetChildren(); |
986 | size_t count = children.Count(); | |
987 | for ( size_t n = 0; n < count; n++ ) | |
4c681997 | 988 | { |
c801d85f | 989 | y += m_lineHeight; |
e2414cbe | 990 | semiOldY = y; |
389cdc7a | 991 | |
f135ff73 | 992 | PaintLevel( children[n], dc, level+1, y ); |
edaa81ae | 993 | } |
4c681997 | 994 | |
e2414cbe | 995 | dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY ); |
4c681997 | 996 | } |
c801d85f | 997 | |
f135ff73 VZ |
998 | // ----------------------------------------------------------------------------- |
999 | // wxWindows callbacks | |
1000 | // ----------------------------------------------------------------------------- | |
1001 | ||
3db7be80 | 1002 | void wxTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) ) |
c801d85f | 1003 | { |
f135ff73 VZ |
1004 | if ( !m_anchor ) |
1005 | return; | |
c801d85f | 1006 | |
d4c99d6f RR |
1007 | wxPaintDC dc(this); |
1008 | PrepareDC( dc ); | |
29d87bba | 1009 | |
d4c99d6f | 1010 | dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) ); |
29d87bba | 1011 | |
d4c99d6f RR |
1012 | dc.SetPen( m_dottedPen ); |
1013 | m_lineHeight = (int)(dc.GetCharHeight() + 4); | |
29d87bba | 1014 | |
c801d85f | 1015 | int y = m_lineHeight / 2 + 2; |
d4c99d6f | 1016 | PaintLevel( m_anchor, dc, 0, y ); |
edaa81ae | 1017 | } |
c801d85f | 1018 | |
3db7be80 | 1019 | void wxTreeCtrl::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) |
c801d85f KB |
1020 | { |
1021 | m_hasFocus = TRUE; | |
f135ff73 VZ |
1022 | if ( m_current ) |
1023 | RefreshLine( m_current ); | |
edaa81ae | 1024 | } |
c801d85f | 1025 | |
3db7be80 | 1026 | void wxTreeCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) |
c801d85f KB |
1027 | { |
1028 | m_hasFocus = FALSE; | |
f135ff73 VZ |
1029 | if ( m_current ) |
1030 | RefreshLine( m_current ); | |
edaa81ae | 1031 | } |
c801d85f KB |
1032 | |
1033 | void wxTreeCtrl::OnChar( wxKeyEvent &event ) | |
1034 | { | |
f135ff73 | 1035 | // TODO process '+', '-' (expand/collapse branch) and cursor keys |
c801d85f | 1036 | event.Skip(); |
edaa81ae | 1037 | } |
c801d85f | 1038 | |
3db7be80 | 1039 | void wxTreeCtrl::OnMouse( wxMouseEvent &event ) |
c801d85f | 1040 | { |
f135ff73 VZ |
1041 | if ( !(event.LeftDown() || event.LeftDClick()) ) |
1042 | return; | |
1043 | ||
1044 | if ( !m_anchor ) | |
1045 | return; | |
29d87bba | 1046 | |
c801d85f KB |
1047 | wxClientDC dc(this); |
1048 | PrepareDC(dc); | |
1049 | long x = dc.DeviceToLogicalX( (long)event.GetX() ); | |
1050 | long y = dc.DeviceToLogicalY( (long)event.GetY() ); | |
29d87bba | 1051 | |
f135ff73 VZ |
1052 | bool onButton = FALSE; |
1053 | wxGenericTreeItem *item = m_anchor->HitTest( wxPoint(x,y), onButton ); | |
1054 | if ( item == NULL ) | |
29d87bba | 1055 | return; |
29d87bba | 1056 | |
389cdc7a | 1057 | SelectItem(item); |
29d87bba | 1058 | |
f135ff73 VZ |
1059 | if ( event.LeftDClick() ) |
1060 | { | |
1061 | wxTreeEvent event( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() ); | |
1062 | event.m_item = item; | |
1063 | event.m_code = 0; | |
1064 | event.SetEventObject( this ); | |
1065 | ProcessEvent( event ); | |
1066 | } | |
29d87bba | 1067 | |
f135ff73 | 1068 | if ( onButton ) |
c801d85f | 1069 | { |
f135ff73 | 1070 | Toggle( item ); |
edaa81ae RR |
1071 | } |
1072 | } | |
c801d85f | 1073 | |
3db7be80 RR |
1074 | void wxTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) ) |
1075 | { | |
1076 | if (!m_dirty) return; | |
1077 | ||
1078 | m_dirty = FALSE; | |
1079 | ||
1080 | CalculatePositions(); | |
1081 | ||
1082 | AdjustMyScrollbars(); | |
1083 | } | |
1084 | ||
f135ff73 VZ |
1085 | // ----------------------------------------------------------------------------- |
1086 | // ----------------------------------------------------------------------------- | |
1087 | void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item, | |
1088 | wxDC &dc, | |
1089 | int level, | |
1090 | int &y ) | |
c801d85f | 1091 | { |
4c681997 | 1092 | int horizX = level*m_indent; |
389cdc7a | 1093 | |
f135ff73 VZ |
1094 | item->SetX( horizX+33 ); |
1095 | item->SetY( y-m_lineHeight/3-2 ); | |
1096 | item->SetHeight( m_lineHeight ); | |
4c681997 | 1097 | |
f135ff73 VZ |
1098 | if ( item->IsExpanded() ) |
1099 | return; | |
389cdc7a | 1100 | |
f135ff73 VZ |
1101 | wxArrayTreeItems& children = item->GetChildren(); |
1102 | size_t count = children.Count(); | |
1103 | for ( size_t n = 0; n < count; n++ ) | |
c801d85f | 1104 | { |
c801d85f | 1105 | y += m_lineHeight; |
f135ff73 | 1106 | CalculateLevel( children[n], dc, level+1, y ); |
edaa81ae RR |
1107 | } |
1108 | } | |
c801d85f | 1109 | |
74bedbeb | 1110 | void wxTreeCtrl::CalculatePositions() |
c801d85f | 1111 | { |
f135ff73 | 1112 | if ( !m_anchor ) |
29d87bba VZ |
1113 | return; |
1114 | ||
c801d85f KB |
1115 | wxClientDC dc(this); |
1116 | PrepareDC( dc ); | |
29d87bba | 1117 | |
c801d85f | 1118 | dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) ); |
29d87bba | 1119 | |
c801d85f KB |
1120 | dc.SetPen( m_dottedPen ); |
1121 | m_lineHeight = (int)(dc.GetCharHeight() + 4); | |
29d87bba | 1122 | |
c801d85f KB |
1123 | int y = m_lineHeight / 2 + 2; |
1124 | CalculateLevel( m_anchor, dc, 0, y ); | |
edaa81ae | 1125 | } |
c801d85f | 1126 | |
f135ff73 | 1127 | void wxTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) |
c801d85f | 1128 | { |
f135ff73 VZ |
1129 | wxClientDC dc(this); |
1130 | PrepareDC(dc); | |
4832f7c0 | 1131 | |
f135ff73 VZ |
1132 | int cw = 0; |
1133 | int ch = 0; | |
1134 | GetClientSize( &cw, &ch ); | |
4832f7c0 | 1135 | |
f135ff73 VZ |
1136 | wxRect rect; |
1137 | rect.x = dc.LogicalToDeviceX( 0 ); | |
1138 | rect.width = cw; | |
1139 | rect.y = dc.LogicalToDeviceY( item->GetY() ); | |
1140 | rect.height = ch; | |
1141 | ||
1142 | Refresh( TRUE, &rect ); | |
1143 | ||
1144 | AdjustMyScrollbars(); | |
edaa81ae | 1145 | } |
c801d85f KB |
1146 | |
1147 | void wxTreeCtrl::RefreshLine( wxGenericTreeItem *item ) | |
1148 | { | |
c801d85f KB |
1149 | wxClientDC dc(this); |
1150 | PrepareDC( dc ); | |
f135ff73 | 1151 | |
c801d85f | 1152 | wxRect rect; |
f135ff73 VZ |
1153 | rect.x = dc.LogicalToDeviceX( item->GetX() - 2 ); |
1154 | rect.y = dc.LogicalToDeviceY( item->GetY() - 2 ); | |
c801d85f | 1155 | rect.width = 1000; |
f135ff73 VZ |
1156 | rect.height = dc.GetCharHeight() + 6; |
1157 | ||
c801d85f | 1158 | Refresh( TRUE, &rect ); |
edaa81ae | 1159 | } |
c801d85f | 1160 |