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