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