]> git.saurik.com Git - wxWidgets.git/blame - src/generic/treectrl.cpp
Fixed typo.
[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
f135ff73 143IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent)
c801d85f 144
f135ff73
VZ
145wxTreeEvent::wxTreeEvent( wxEventType commandType, int id )
146 : wxCommandEvent( 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
701 Refresh();
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
711 Refresh();
712 }
edaa81ae
RR
713}
714
f135ff73 715void wxTreeCtrl::Expand(const wxTreeItemId& itemId)
edaa81ae 716{
f135ff73
VZ
717 wxGenericTreeItem *item = itemId.m_pItem;
718
719 if ( item->IsExpanded() )
720 return;
721
722 wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, GetId() );
723 event.m_item = item;
724 event.SetEventObject( this );
725 if ( ProcessEvent( event ) && event.m_code )
726 {
727 // cancelled by program
728 return;
729 }
4832f7c0 730
f135ff73
VZ
731 item->Expand();
732
733 RefreshSubtree(item);
734
735 event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED);
736 ProcessEvent( event );
edaa81ae
RR
737}
738
f135ff73 739void wxTreeCtrl::Collapse(const wxTreeItemId& itemId)
edaa81ae 740{
f135ff73
VZ
741 wxGenericTreeItem *item = itemId.m_pItem;
742
743 if ( !item->IsExpanded() )
744 return;
745
746 wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, GetId() );
747 event.m_item = item;
748 event.SetEventObject( this );
749 if ( ProcessEvent( event ) && event.m_code )
edaa81ae 750 {
f135ff73
VZ
751 // cancelled by program
752 return;
753 }
4832f7c0 754
f135ff73
VZ
755 item->Collapse();
756
757 wxArrayTreeItems& children = item->GetChildren();
758 size_t count = children.Count();
759 for ( size_t n = 0; n < count; n++ )
760 {
761 Collapse(children[n]);
edaa81ae 762 }
f135ff73
VZ
763
764 CalculatePositions();
765
766 RefreshSubtree(item);
767
768 event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
769 ProcessEvent( event );
edaa81ae 770}
c801d85f 771
f135ff73 772void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item)
c801d85f 773{
f135ff73
VZ
774 Collapse(item);
775 Delete(item);
edaa81ae 776}
c801d85f 777
f135ff73 778void wxTreeCtrl::Toggle(const wxTreeItemId& itemId)
c801d85f 779{
f135ff73 780 wxGenericTreeItem *item = itemId.m_pItem;
389cdc7a 781
f135ff73
VZ
782 if ( item->IsExpanded() )
783 Collapse(itemId);
784 else
785 Expand(itemId);
786}
389cdc7a 787
f135ff73
VZ
788void wxTreeCtrl::Unselect()
789{
790 if ( m_current )
791 {
792 m_current->SetHilight( FALSE );
793 RefreshLine( m_current );
794 }
edaa81ae 795}
c801d85f 796
f135ff73 797void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId)
389cdc7a 798{
f135ff73
VZ
799 wxGenericTreeItem *item = itemId.m_pItem;
800
801 if ( m_current != item )
389cdc7a 802 {
f135ff73
VZ
803 wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() );
804 event.m_item = item;
805 event.m_itemOld = m_current;
806 event.SetEventObject( this );
6daa0637 807 if ( GetEventHandler()->ProcessEvent( event ) && event.WasVetoed() )
f135ff73
VZ
808 return;
809
810 if ( m_current )
389cdc7a
VZ
811 {
812 m_current->SetHilight( FALSE );
813 RefreshLine( m_current );
edaa81ae 814 }
f135ff73 815
389cdc7a
VZ
816 m_current = item;
817 m_current->SetHilight( TRUE );
818 RefreshLine( m_current );
819
f135ff73 820 event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
6daa0637 821 GetEventHandler()->ProcessEvent( event );
389cdc7a
VZ
822 }
823}
824
6daa0637 825void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
c801d85f 826{
6daa0637 827 wxGenericTreeItem *gitem = item.m_pItem;
ef44a621 828
6daa0637 829 int item_y = gitem->GetY();
ef44a621 830
6daa0637
RR
831 int start_x = 0;
832 int start_y = 0;
833 ViewStart( &start_x, &start_y );
834 start_y *= 10;
ef44a621 835
6daa0637
RR
836 if (item_y < start_y+3)
837 {
838 int x = 0;
839 int y = 0;
840 m_anchor->GetSize( x, y );
841 y += 2*m_lineHeight;
842 int x_pos = GetScrollPos( wxHORIZONTAL );
843 SetScrollbars( 10, 10, x/10, y/10, x_pos, item_y/10 );
844 return;
845 }
ef44a621 846
6daa0637
RR
847 int w = 0;
848 int h = 0;
849 GetClientSize( &w, &h );
ef44a621 850
6daa0637
RR
851 if (item_y > start_y+h-26)
852 {
853 int x = 0;
854 int y = 0;
855 m_anchor->GetSize( x, y );
856 y += 2*m_lineHeight;
857 int x_pos = GetScrollPos( wxHORIZONTAL );
858 SetScrollbars( 10, 10, x/10, y/10, x_pos, (item_y-h+30)/10 );
859 return;
ef44a621 860 }
edaa81ae 861}
c801d85f 862
df875e59 863void wxTreeCtrl::ScrollTo(const wxTreeItemId& WXUNUSED(item))
c801d85f 864{
f135ff73 865 wxFAIL_MSG("not implemented");
edaa81ae 866}
c801d85f 867
df875e59
RR
868wxTextCtrl *wxTreeCtrl::EditLabel( const wxTreeItemId& WXUNUSED(item),
869 wxClassInfo* WXUNUSED(textCtrlClass) )
c801d85f 870{
f135ff73 871 wxFAIL_MSG("not implemented");
c801d85f 872
f135ff73 873 return NULL;
edaa81ae 874}
c801d85f 875
f135ff73 876wxTextCtrl *wxTreeCtrl::GetEditControl() const
c801d85f 877{
f135ff73 878 wxFAIL_MSG("not implemented");
c801d85f 879
f135ff73 880 return NULL;
edaa81ae 881}
c801d85f 882
df875e59 883void wxTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item), bool WXUNUSED(discardChanges))
74bedbeb 884{
f135ff73 885 wxFAIL_MSG("not implemented");
74bedbeb
VZ
886}
887
df875e59
RR
888void wxTreeCtrl::SortChildren( const wxTreeItemId& WXUNUSED(item),
889 wxTreeItemCmpFunc *WXUNUSED(cmpFunction))
edaa81ae 890{
f135ff73 891 wxFAIL_MSG("not implemented");
edaa81ae
RR
892}
893
f135ff73 894wxImageList *wxTreeCtrl::GetImageList() const
edaa81ae 895{
f135ff73 896 return m_imageListNormal;
edaa81ae
RR
897}
898
f135ff73 899wxImageList *wxTreeCtrl::GetStateImageList() const
c801d85f 900{
f135ff73 901 return m_imageListState;
edaa81ae 902}
c801d85f 903
f135ff73 904void wxTreeCtrl::SetImageList(wxImageList *imageList)
e2414cbe 905{
f135ff73 906 m_imageListNormal = imageList;
edaa81ae 907}
e2414cbe 908
f135ff73 909void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
e2414cbe 910{
f135ff73 911 m_imageListState = imageList;
edaa81ae 912}
e2414cbe 913
f135ff73
VZ
914// -----------------------------------------------------------------------------
915// helpers
916// -----------------------------------------------------------------------------
74bedbeb 917void wxTreeCtrl::AdjustMyScrollbars()
c801d85f
KB
918{
919 if (m_anchor)
920 {
921 int x = 0;
922 int y = 0;
923 m_anchor->GetSize( x, y );
924 y += 2*m_lineHeight;
925 int x_pos = GetScrollPos( wxHORIZONTAL );
926 int y_pos = GetScrollPos( wxVERTICAL );
927 SetScrollbars( 10, 10, x/10, y/10, x_pos, y_pos );
928 }
929 else
930 {
931 SetScrollbars( 0, 0, 0, 0 );
edaa81ae
RR
932 }
933}
c801d85f 934
ef44a621
VZ
935void wxTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
936{
937 // render bold items in bold
c59e2a82
RR
938 wxFont fontOld;
939 wxFont fontNew;
940
ef44a621
VZ
941 if ( item->IsBold() )
942 {
943 fontOld = dc.GetFont();
c59e2a82 944 if (fontOld.Ok())
ef44a621
VZ
945 {
946 // @@ is there any better way to make a bold variant of old font?
c59e2a82
RR
947 fontNew = wxFont( fontOld.GetPointSize(),
948 fontOld.GetFamily(),
949 fontOld.GetStyle(),
950 wxBOLD,
951 fontOld.GetUnderlined());
ef44a621
VZ
952 dc.SetFont(fontNew);
953 }
954 else
955 {
956 wxFAIL_MSG("wxDC::GetFont() failed!");
957 }
958 }
959
960 long text_w = 0;
961 long text_h = 0;
962 dc.GetTextExtent( item->GetText(), &text_w, &text_h );
963
964 int image_h = 0;
965 int image_w = 0;
966 if (item->GetImage() != -1)
967 {
968 m_imageListNormal->GetSize( item->GetImage(), image_w, image_h );
969 image_w += 4;
970 }
971
972 dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 );
973
974 if (item->GetImage() != -1)
975 {
976 dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h );
977 m_imageListNormal->Draw( item->GetImage(), dc,
978 item->GetX(), item->GetY()-1,
979 wxIMAGELIST_DRAW_TRANSPARENT );
980 dc.DestroyClippingRegion();
981 }
982
983 dc.DrawText( item->GetText(), image_w + item->GetX(), item->GetY() );
984
985 // restore normal font for bold items
c59e2a82 986 if (fontOld.Ok())
ef44a621 987 {
c59e2a82 988 dc.SetFont( fontOld);
ef44a621
VZ
989 }
990}
991
16c1f7f3 992void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &y )
c801d85f 993{
4c681997 994 int horizX = level*m_indent;
389cdc7a 995
f135ff73
VZ
996 item->SetX( horizX+33 );
997 item->SetY( y-m_lineHeight/3 );
998 item->SetHeight( m_lineHeight );
389cdc7a 999
4c681997
RR
1000 item->SetCross( horizX+15, y );
1001
c801d85f 1002 int oldY = y;
389cdc7a 1003
d4c99d6f 1004 int exposed_x = dc.LogicalToDeviceX( 0 );
f135ff73 1005 int exposed_y = dc.LogicalToDeviceY( item->GetY()-2 );
4832f7c0 1006
df875e59 1007 if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 )) // 10000 = very much
c801d85f 1008 {
4c681997
RR
1009 int startX = horizX;
1010 int endX = horizX + 10;
29d87bba 1011
4c681997 1012 if (!item->HasChildren()) endX += 20;
4832f7c0 1013
389cdc7a 1014 dc.DrawLine( startX, y, endX, y );
29d87bba 1015
f135ff73
VZ
1016 if (item->HasPlus())
1017 {
1018 dc.DrawLine( horizX+20, y, horizX+30, y );
1019 dc.SetPen( *wxGREY_PEN );
1020 dc.DrawRectangle( horizX+10, y-4, 11, 9 );
1021 dc.SetPen( *wxBLACK_PEN );
1022 dc.DrawLine( horizX+13, y, horizX+18, y );
1023
1024 if (!item->IsExpanded())
1025 dc.DrawLine( horizX+15, y-2, horizX+15, y+3 );
1026 }
c801d85f 1027
f135ff73
VZ
1028 if (item->HasHilight())
1029 {
1030 dc.SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
a367b9b3 1031
f135ff73 1032 dc.SetBrush( *m_hilightBrush );
4832f7c0 1033
df875e59
RR
1034 if (m_hasFocus)
1035 dc.SetPen( *wxBLACK_PEN );
29d87bba 1036 else
389cdc7a 1037 dc.SetPen( *wxTRANSPARENT_PEN );
4832f7c0 1038
ef44a621 1039 PaintItem(item, dc);
f135ff73
VZ
1040
1041 dc.SetPen( *wxBLACK_PEN );
1042 dc.SetTextForeground( *wxBLACK );
1043 dc.SetBrush( *wxWHITE_BRUSH );
1044 }
1045 else
1046 {
1047 dc.SetBrush( *wxWHITE_BRUSH );
1048 dc.SetPen( *wxTRANSPARENT_PEN );
4832f7c0 1049
ef44a621 1050 PaintItem(item, dc);
4832f7c0 1051
f135ff73
VZ
1052 dc.SetPen( *wxBLACK_PEN );
1053 }
edaa81ae 1054 }
4c681997 1055
f135ff73
VZ
1056 if ( !item->IsExpanded() )
1057 return;
e2414cbe 1058
389cdc7a
VZ
1059 int semiOldY = y;
1060
f135ff73
VZ
1061 wxArrayTreeItems& children = item->GetChildren();
1062 size_t count = children.Count();
1063 for ( size_t n = 0; n < count; n++ )
4c681997 1064 {
c801d85f 1065 y += m_lineHeight;
e2414cbe 1066 semiOldY = y;
389cdc7a 1067
f135ff73 1068 PaintLevel( children[n], dc, level+1, y );
edaa81ae 1069 }
4c681997 1070
e2414cbe 1071 dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY );
4c681997 1072}
c801d85f 1073
f135ff73
VZ
1074// -----------------------------------------------------------------------------
1075// wxWindows callbacks
1076// -----------------------------------------------------------------------------
1077
3db7be80 1078void wxTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
c801d85f 1079{
f135ff73
VZ
1080 if ( !m_anchor )
1081 return;
c801d85f 1082
d4c99d6f
RR
1083 wxPaintDC dc(this);
1084 PrepareDC( dc );
29d87bba 1085
d4c99d6f 1086 dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) );
29d87bba 1087
d4c99d6f
RR
1088 dc.SetPen( m_dottedPen );
1089 m_lineHeight = (int)(dc.GetCharHeight() + 4);
29d87bba 1090
c801d85f 1091 int y = m_lineHeight / 2 + 2;
d4c99d6f 1092 PaintLevel( m_anchor, dc, 0, y );
edaa81ae 1093}
c801d85f 1094
3db7be80 1095void wxTreeCtrl::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
c801d85f
KB
1096{
1097 m_hasFocus = TRUE;
f135ff73
VZ
1098 if ( m_current )
1099 RefreshLine( m_current );
edaa81ae 1100}
c801d85f 1101
3db7be80 1102void wxTreeCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
c801d85f
KB
1103{
1104 m_hasFocus = FALSE;
f135ff73
VZ
1105 if ( m_current )
1106 RefreshLine( m_current );
edaa81ae 1107}
c801d85f
KB
1108
1109void wxTreeCtrl::OnChar( wxKeyEvent &event )
1110{
6daa0637 1111 if (m_current == 0)
ef44a621 1112 {
6daa0637
RR
1113 event.Skip();
1114 return;
1115 }
ef44a621 1116
6daa0637
RR
1117 switch (event.KeyCode())
1118 {
1119 case '+':
1120 case WXK_ADD:
6daa0637
RR
1121 if (HasChildren(m_current) && !IsExpanded(m_current))
1122 {
1123 Expand(m_current);
1124 }
ef44a621
VZ
1125 break;
1126
6daa0637
RR
1127 case '-':
1128 case WXK_SUBTRACT:
6daa0637
RR
1129 if (IsExpanded(m_current))
1130 {
1131 Collapse(m_current);
1132 }
ef44a621
VZ
1133 break;
1134
1135 case '*':
1136 case WXK_MULTIPLY:
1137 Toggle(m_current);
1138 break;
1139
6daa0637
RR
1140 case ' ':
1141 case WXK_RETURN:
ef44a621
VZ
1142 {
1143 wxTreeEvent event( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() );
1144 event.m_item = m_current;
1145 event.m_code = 0;
1146 event.SetEventObject( this );
1147 GetEventHandler()->ProcessEvent( event );
1148 }
1149 break;
1150
1151 case WXK_LEFT:
6daa0637 1152 case WXK_UP:
6daa0637 1153 {
ef44a621
VZ
1154 wxTreeItemId prev = GetPrevSibling( m_current );
1155 if (prev != 0)
1156 {
1157 SelectItem( prev );
1158 EnsureVisible( prev );
1159 }
1160 else
1161 {
1162 prev = GetParent( m_current );
1163 if (prev)
1164 {
1165 EnsureVisible( prev );
1166 SelectItem( prev );
1167 }
1168 }
6daa0637 1169 }
ef44a621
VZ
1170 break;
1171
1172 case WXK_RIGHT:
1173 // this works the same as the down arrow except that we also expand the
1174 // item if it wasn't expanded yet
1175 Expand(m_current);
1176 // fall through
1177
1178 case WXK_DOWN:
6daa0637 1179 {
ef44a621
VZ
1180 if (IsExpanded(m_current))
1181 {
1182 long cookie = 0;
1183 wxTreeItemId child = GetFirstChild( m_current, cookie );
1184 SelectItem( child );
1185 EnsureVisible( child );
1186 }
1187 else
1188 {
1189 wxTreeItemId next = GetNextSibling( m_current );
1190 if (next == 0)
1191 {
1192 wxTreeItemId current = m_current;
1193 while (current && !next)
1194 {
1195 current = GetParent( current );
1196 if (current) next = GetNextSibling( current );
1197 }
1198 }
1199 if (next != 0)
1200 {
1201 SelectItem( next );
1202 EnsureVisible( next );
1203 }
1204 }
6daa0637 1205 }
ef44a621
VZ
1206 break;
1207
1208 default:
1209 event.Skip();
6daa0637 1210 }
edaa81ae 1211}
c801d85f 1212
3db7be80 1213void wxTreeCtrl::OnMouse( wxMouseEvent &event )
c801d85f 1214{
f135ff73
VZ
1215 if ( !(event.LeftDown() || event.LeftDClick()) )
1216 return;
1217
1218 if ( !m_anchor )
1219 return;
29d87bba 1220
c801d85f
KB
1221 wxClientDC dc(this);
1222 PrepareDC(dc);
1223 long x = dc.DeviceToLogicalX( (long)event.GetX() );
1224 long y = dc.DeviceToLogicalY( (long)event.GetY() );
29d87bba 1225
f135ff73
VZ
1226 bool onButton = FALSE;
1227 wxGenericTreeItem *item = m_anchor->HitTest( wxPoint(x,y), onButton );
1228 if ( item == NULL )
29d87bba 1229 return;
29d87bba 1230
6daa0637 1231 if (!IsSelected(item)) SelectItem(item);
29d87bba 1232
f135ff73
VZ
1233 if ( event.LeftDClick() )
1234 {
1235 wxTreeEvent event( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() );
1236 event.m_item = item;
1237 event.m_code = 0;
1238 event.SetEventObject( this );
6daa0637 1239 GetEventHandler()->ProcessEvent( event );
f135ff73 1240 }
29d87bba 1241
f135ff73 1242 if ( onButton )
c801d85f 1243 {
f135ff73 1244 Toggle( item );
edaa81ae
RR
1245 }
1246}
c801d85f 1247
3db7be80
RR
1248void wxTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
1249{
1250 if (!m_dirty) return;
ef44a621 1251
3db7be80 1252 m_dirty = FALSE;
ef44a621 1253
3db7be80
RR
1254 CalculatePositions();
1255
1256 AdjustMyScrollbars();
1257}
1258
f135ff73
VZ
1259// -----------------------------------------------------------------------------
1260// -----------------------------------------------------------------------------
1261void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item,
1262 wxDC &dc,
1263 int level,
1264 int &y )
c801d85f 1265{
4c681997 1266 int horizX = level*m_indent;
389cdc7a 1267
f135ff73
VZ
1268 item->SetX( horizX+33 );
1269 item->SetY( y-m_lineHeight/3-2 );
1270 item->SetHeight( m_lineHeight );
4c681997 1271
f135ff73
VZ
1272 if ( item->IsExpanded() )
1273 return;
389cdc7a 1274
f135ff73
VZ
1275 wxArrayTreeItems& children = item->GetChildren();
1276 size_t count = children.Count();
1277 for ( size_t n = 0; n < count; n++ )
c801d85f 1278 {
c801d85f 1279 y += m_lineHeight;
f135ff73 1280 CalculateLevel( children[n], dc, level+1, y );
edaa81ae
RR
1281 }
1282}
c801d85f 1283
74bedbeb 1284void wxTreeCtrl::CalculatePositions()
c801d85f 1285{
f135ff73 1286 if ( !m_anchor )
29d87bba
VZ
1287 return;
1288
c801d85f
KB
1289 wxClientDC dc(this);
1290 PrepareDC( dc );
29d87bba 1291
c801d85f 1292 dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) );
29d87bba 1293
c801d85f
KB
1294 dc.SetPen( m_dottedPen );
1295 m_lineHeight = (int)(dc.GetCharHeight() + 4);
29d87bba 1296
c801d85f
KB
1297 int y = m_lineHeight / 2 + 2;
1298 CalculateLevel( m_anchor, dc, 0, y );
edaa81ae 1299}
c801d85f 1300
f135ff73 1301void wxTreeCtrl::RefreshSubtree(wxGenericTreeItem *item)
c801d85f 1302{
f135ff73
VZ
1303 wxClientDC dc(this);
1304 PrepareDC(dc);
4832f7c0 1305
f135ff73
VZ
1306 int cw = 0;
1307 int ch = 0;
1308 GetClientSize( &cw, &ch );
4832f7c0 1309
f135ff73
VZ
1310 wxRect rect;
1311 rect.x = dc.LogicalToDeviceX( 0 );
1312 rect.width = cw;
1313 rect.y = dc.LogicalToDeviceY( item->GetY() );
1314 rect.height = ch;
1315
1316 Refresh( TRUE, &rect );
1317
1318 AdjustMyScrollbars();
edaa81ae 1319}
c801d85f
KB
1320
1321void wxTreeCtrl::RefreshLine( wxGenericTreeItem *item )
1322{
c801d85f
KB
1323 wxClientDC dc(this);
1324 PrepareDC( dc );
f135ff73 1325
c801d85f 1326 wxRect rect;
f135ff73
VZ
1327 rect.x = dc.LogicalToDeviceX( item->GetX() - 2 );
1328 rect.y = dc.LogicalToDeviceY( item->GetY() - 2 );
c801d85f 1329 rect.width = 1000;
f135ff73 1330 rect.height = dc.GetCharHeight() + 6;
c801d85f 1331 Refresh( TRUE, &rect );
edaa81ae 1332}
c801d85f 1333