]> git.saurik.com Git - wxWidgets.git/blob - src/generic/treectrl.cpp
Pretty redical change concerning the underlying
[wxWidgets.git] / src / generic / treectrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: treectrl.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id: $Id$
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "treectrl.h"
13 #endif
14
15 #include "wx/treectrl.h"
16 #include "wx/settings.h"
17 #include "wx/log.h"
18
19 //-----------------------------------------------------------------------------
20 // wxTreeItem
21 //-----------------------------------------------------------------------------
22
23 IMPLEMENT_DYNAMIC_CLASS(wxTreeItem, wxObject)
24
25 wxTreeItem::wxTreeItem()
26 {
27 m_mask = 0;
28 m_itemId = 0;
29 m_state = 0;
30 m_stateMask = 0;
31 m_image = -1;
32 m_selectedImage = -1;
33 m_children = 0;
34 m_data = 0;
35 };
36
37 //-----------------------------------------------------------------------------
38 // wxTreeEvent
39 //-----------------------------------------------------------------------------
40
41 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent,wxCommandEvent)
42
43 wxTreeEvent::wxTreeEvent( wxEventType commandType, int id ) :
44 wxCommandEvent( commandType, id )
45 {
46 m_code = 0;
47 m_oldItem = 0;
48 };
49
50 //-----------------------------------------------------------------------------
51 // wxGenericTreeItem
52 //-----------------------------------------------------------------------------
53
54 IMPLEMENT_DYNAMIC_CLASS(wxGenericTreeItem,wxObject)
55
56 wxGenericTreeItem::wxGenericTreeItem( wxGenericTreeItem *parent )
57 {
58 Reset();
59 m_parent = parent;
60 m_hasHilight = FALSE;
61 };
62
63 wxGenericTreeItem::wxGenericTreeItem( wxGenericTreeItem *parent, const wxTreeItem& item, wxDC *dc )
64 {
65 Reset();
66 SetItem( item, dc );
67 m_parent = parent;
68 m_hasHilight = FALSE;
69 };
70
71 void wxGenericTreeItem::SetItem( const wxTreeItem &item, wxDC *dc )
72 {
73 if ((item.m_mask & wxTREE_MASK_HANDLE) == wxTREE_MASK_HANDLE)
74 m_itemId = item.m_itemId;
75 if ((item.m_mask & wxTREE_MASK_STATE) == wxTREE_MASK_STATE)
76 m_state = item.m_state;
77 if ((item.m_mask & wxTREE_MASK_TEXT) == wxTREE_MASK_TEXT)
78 m_text = item.m_text;
79 if ((item.m_mask & wxTREE_MASK_IMAGE) == wxTREE_MASK_IMAGE)
80 m_image = item.m_image;
81 if ((item.m_mask & wxTREE_MASK_SELECTED_IMAGE) == wxTREE_MASK_SELECTED_IMAGE)
82 m_selectedImage = item.m_selectedImage;
83 if ((item.m_mask & wxTREE_MASK_CHILDREN) == wxTREE_MASK_CHILDREN)
84 m_hasChildren = (item.m_children > 0);
85 if ((item.m_mask & wxTREE_MASK_DATA) == wxTREE_MASK_DATA)
86 m_data = item.m_data;
87 long lw = 0;
88 long lh = 0;
89 dc->GetTextExtent( m_text, &lw, &lh );
90 m_width = lw;
91 m_height = lh;
92 };
93
94 void wxGenericTreeItem::SetText( const wxString &text, wxDC *dc )
95 {
96 m_text = text;
97 long lw = 0;
98 long lh = 0;
99 dc->GetTextExtent( m_text, &lw, &lh );
100 m_width = lw;
101 m_height = lh;
102 };
103
104 void wxGenericTreeItem::Reset()
105 {
106 m_itemId = -1;
107 m_state = 0;
108 m_text = "";
109 m_image = -1;
110 m_selectedImage = -1;
111 // m_children = 0;
112 m_hasChildren = FALSE;
113 m_data = 0;
114 m_x = 0;
115 m_y = 0;
116 m_height = 0;
117 m_width = 0;
118 m_xCross = 0;
119 m_yCross = 0;
120 m_level = 0;
121 m_children.DeleteContents( TRUE );
122 m_isCollapsed = TRUE;
123 m_parent = NULL;
124 };
125
126 void wxGenericTreeItem::GetItem( wxTreeItem &item ) const
127 {
128 if ((item.m_mask & wxTREE_MASK_STATE) == wxTREE_MASK_STATE)
129 item.m_state = m_state;
130 if ((item.m_mask & wxTREE_MASK_TEXT) == wxTREE_MASK_TEXT)
131 item.m_text = m_text;
132 if ((item.m_mask & wxTREE_MASK_IMAGE) == wxTREE_MASK_IMAGE)
133 item.m_image = m_image;
134 if ((item.m_mask & wxTREE_MASK_SELECTED_IMAGE) == wxTREE_MASK_SELECTED_IMAGE)
135 item.m_selectedImage = m_selectedImage;
136 if ((item.m_mask & wxTREE_MASK_CHILDREN) == wxTREE_MASK_CHILDREN)
137 item.m_children = (int)m_hasChildren;
138 if ((item.m_mask & wxTREE_MASK_DATA) == wxTREE_MASK_DATA)
139 item.m_data = m_data;
140 };
141
142 bool wxGenericTreeItem::HasChildren()
143 {
144 return m_hasChildren;
145 };
146
147 bool wxGenericTreeItem::HasPlus()
148 {
149 if ( !HasChildren() )
150 return FALSE;
151
152 return !IsExpanded();
153 };
154
155 int wxGenericTreeItem::NumberOfVisibleDescendents()
156 {
157 int ret = m_children.Number();
158 wxNode *node = m_children.First();
159 while (node)
160 {
161 wxGenericTreeItem *item = (wxGenericTreeItem*)node->Data();
162 ret += item->NumberOfVisibleDescendents();
163 node = node->Next();
164 };
165 return ret;
166 };
167
168 int wxGenericTreeItem::NumberOfVisibleChildren()
169 {
170 return m_isCollapsed ? 0 : m_children.Number();
171 };
172
173 wxGenericTreeItem *wxGenericTreeItem::FindItem( long itemId ) const
174 {
175 if (m_itemId == itemId) return (wxGenericTreeItem*)(this);
176 wxNode *node = m_children.First();
177 while (node)
178 {
179 wxGenericTreeItem *item = (wxGenericTreeItem*)node->Data();
180 wxGenericTreeItem *res = item->FindItem( itemId );
181 if (res) return (wxGenericTreeItem*)(res);
182 node = node->Next();
183 };
184 return NULL;
185 };
186
187 void wxGenericTreeItem::AddChild( wxGenericTreeItem *child )
188 {
189 m_children.Append( child );
190 };
191
192 void wxGenericTreeItem::SetCross( int x, int y )
193 {
194 m_xCross = x;
195 m_yCross = y;
196 };
197
198 void wxGenericTreeItem::GetSize( int &x, int &y )
199 {
200 if (y < m_y + 10) y = m_y +10;
201 int width = m_x + m_width;
202 if (width > x) x = width;
203 wxNode *node = m_children.First();
204 while (node)
205 {
206 wxGenericTreeItem *item = (wxGenericTreeItem*)node->Data();
207 item->GetSize( x, y );
208 node = node->Next();
209 };
210 };
211
212 long wxGenericTreeItem::HitTest( const wxPoint& point, int &flags )
213 {
214 if ((point.y > m_y) && (point.y < m_y+m_height))
215 {
216 if ((point.x > m_xCross-5) &&
217 (point.x < m_xCross+5) &&
218 (point.y > m_yCross-5) &&
219 (point.y < m_yCross+5) &&
220 (m_hasChildren))
221 {
222 flags = wxTREE_HITTEST_ONITEMBUTTON;
223 return m_itemId;
224 };
225 if ((point.x > m_x) && (point.x < m_x+m_width))
226 {
227 flags = wxTREE_HITTEST_ONITEMLABEL;
228 return m_itemId;
229 };
230 if (point.x > m_x)
231 {
232 flags = wxTREE_HITTEST_ONITEMRIGHT;
233 return m_itemId;
234 };
235 flags = wxTREE_HITTEST_ONITEMINDENT;
236 return m_itemId;
237 }
238 else
239 {
240 if (!m_isCollapsed)
241 {
242 wxNode *node = m_children.First();
243 while (node)
244 {
245 wxGenericTreeItem *child = (wxGenericTreeItem*)node->Data();
246 long res = child->HitTest( point, flags );
247 if (res != -1) return res;
248 node = node->Next();
249 };
250 };
251 };
252 return -1;
253 };
254
255 void wxGenericTreeItem::PrepareEvent( wxTreeEvent &event )
256 {
257 event.m_item.m_itemId = m_itemId;
258 event.m_item.m_state = m_state;
259 event.m_item.m_text = m_text;
260 event.m_item.m_image = m_image;
261 event.m_item.m_selectedImage = m_selectedImage;
262 event.m_item.m_children = (int)m_hasChildren;
263 event.m_item.m_data = m_data;
264 event.m_oldItem = 0;
265 event.m_code = 0;
266 event.m_pointDrag.x = 0;
267 event.m_pointDrag.y = 0;
268 };
269
270 void wxGenericTreeItem::SendKeyDown( wxWindow *target )
271 {
272 wxTreeEvent event( wxEVT_COMMAND_TREE_KEY_DOWN, target->GetId() );
273 PrepareEvent( event );
274 event.SetEventObject( target );
275 target->ProcessEvent( event );
276 };
277
278 void wxGenericTreeItem::SendSelected( wxWindow *target )
279 {
280 wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGED, target->GetId() );
281 PrepareEvent( event );
282 event.SetEventObject( target );
283 target->ProcessEvent( event );
284 };
285
286 void wxGenericTreeItem::SendDelete( wxWindow *target )
287 {
288 wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, target->GetId() );
289 PrepareEvent( event );
290 event.SetEventObject( target );
291 target->ProcessEvent( event );
292 };
293
294 void wxGenericTreeItem::SendExpand( wxWindow *target )
295 {
296 m_isCollapsed = FALSE;
297
298 wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, target->GetId() );
299 event.SetEventObject( target );
300 PrepareEvent( event );
301 target->ProcessEvent( event );
302
303 event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED);
304 PrepareEvent( event );
305 target->ProcessEvent( event );
306 };
307
308 void wxGenericTreeItem::SendCollapse( wxWindow *target )
309 {
310 m_isCollapsed = TRUE;
311
312 wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, target->GetId() );
313 event.SetEventObject( target );
314 PrepareEvent( event );
315 target->ProcessEvent( event );
316
317 event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
318 PrepareEvent( event );
319 target->ProcessEvent( event );
320 };
321
322 void wxGenericTreeItem::SetHilight( bool set )
323 {
324 m_hasHilight = set;
325 };
326
327 bool wxGenericTreeItem::HasHilight()
328 {
329 return m_hasHilight;
330 };
331
332 //-----------------------------------------------------------------------------
333 // wxTreeCtrl
334 //-----------------------------------------------------------------------------
335
336 IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl,wxScrolledWindow)
337
338 BEGIN_EVENT_TABLE(wxTreeCtrl,wxScrolledWindow)
339 EVT_PAINT (wxTreeCtrl::OnPaint)
340 EVT_MOUSE_EVENTS (wxTreeCtrl::OnMouse)
341 EVT_CHAR (wxTreeCtrl::OnChar)
342 EVT_SET_FOCUS (wxTreeCtrl::OnSetFocus)
343 EVT_KILL_FOCUS (wxTreeCtrl::OnKillFocus)
344 END_EVENT_TABLE()
345
346 wxTreeCtrl::wxTreeCtrl()
347 {
348 m_current = NULL;
349 m_anchor = NULL;
350 m_hasFocus = FALSE;
351 m_xScroll = 0;
352 m_yScroll = 0;
353 m_lastId = 0;
354 m_lineHeight = 10;
355 m_indent = 15;
356 m_isCreated = FALSE;
357 m_hilightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
358 m_imageList = NULL;
359 m_smallImageList = NULL;
360 };
361
362 wxTreeCtrl::wxTreeCtrl(wxWindow *parent, wxWindowID id,
363 const wxPoint& pos, const wxSize& size,
364 long style, const wxString& name )
365 {
366 m_current = NULL;
367 m_anchor = NULL;
368 m_hasFocus = FALSE;
369 m_xScroll = 0;
370 m_yScroll = 0;
371 m_lastId = 0;
372 m_lineHeight = 10;
373 m_indent = 15;
374 m_isCreated = FALSE;
375 m_hilightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
376 m_imageList = NULL;
377 m_smallImageList = NULL;
378 Create( parent, id, pos, size, style, name );
379 };
380
381 wxTreeCtrl::~wxTreeCtrl()
382 {
383 };
384
385 bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id,
386 const wxPoint& pos, const wxSize& size,
387 long style, const wxString& name )
388 {
389 wxScrolledWindow::Create( parent, id, pos, size, style, name );
390 SetBackgroundColour( *wxWHITE );
391 m_dottedPen = wxPen( *wxBLACK, 0, 0 );
392 return TRUE;
393 };
394
395 int wxTreeCtrl::GetCount() const
396 {
397 if (!m_anchor) return 0;
398 return m_anchor->NumberOfVisibleDescendents();
399 };
400
401 long wxTreeCtrl::InsertItem( long parent, const wxString& label, int image,
402 int selImage, long WXUNUSED(insertAfter) )
403 {
404 wxGenericTreeItem *p = NULL;
405 if (parent == 0)
406 {
407 if (m_anchor) return -1;
408 }
409 else
410 {
411 p = FindItem( parent );
412 if (!p) return -1;
413 };
414 wxTreeItem item;
415 m_lastId++;
416 item.m_mask = wxTREE_MASK_HANDLE;
417 item.m_itemId = m_lastId;
418 if (!label.IsNull() || (label == ""))
419 {
420 item.m_text = label;
421 item.m_mask |= wxTREE_MASK_TEXT;
422 };
423 if (image >= 0)
424 {
425 item.m_image = image;
426 item.m_mask |= wxTREE_MASK_IMAGE;
427 };
428 if (selImage >= 0)
429 {
430 item.m_selectedImage = selImage;
431 item.m_mask |= wxTREE_MASK_SELECTED_IMAGE;
432 };
433
434 wxClientDC dc(this);
435 wxGenericTreeItem *new_child = new wxGenericTreeItem( p, item, &dc );
436 if (p)
437 p->AddChild( new_child );
438 else
439 m_anchor = new_child;
440
441 if (p)
442 {
443 CalculatePositions();
444
445 if (!p->HasChildren()) p->m_hasChildren = TRUE;
446
447 int ch = 0;
448 GetClientSize( NULL, &ch );
449
450 PrepareDC( dc );
451
452 wxRectangle rect;
453 rect.x = dc.LogicalToDeviceX( 0 );
454 rect.y = 0;
455 rect.width = 10000;
456 rect.height = ch;
457
458 if (p->m_children.Number() == 1)
459 {
460 rect.y = dc.LogicalToDeviceY( p->m_y );
461 }
462 else
463 {
464 wxNode *node = p->m_children.Member( new_child )->Previous();
465 wxGenericTreeItem* last_child = (wxGenericTreeItem*)node->Data();
466 rect.y = dc.LogicalToDeviceY( last_child->m_y );
467 };
468
469 AdjustMyScrollbars();
470
471 if (rect.height > 0) Refresh( FALSE, &rect);
472 }
473 else
474 {
475 AdjustMyScrollbars();
476
477 Refresh();
478 };
479
480 return m_lastId;
481 };
482
483 long wxTreeCtrl::InsertItem( long parent, wxTreeItem &info, long WXUNUSED(insertAfter) )
484 {
485 int oldMask = info.m_mask;
486 wxGenericTreeItem *p = NULL;
487 if (parent == 0)
488 {
489 if (m_anchor) return -1;
490 }
491 else
492 {
493 p = FindItem( parent );
494 if (!p)
495 {
496 printf( "TreeItem not found.\n" );
497 return -1;
498 };
499 };
500 long ret = 0;
501 if ((info.m_mask & wxTREE_MASK_HANDLE) == 0)
502 {
503 m_lastId++;
504 info.m_itemId = m_lastId;
505 info.m_mask |= wxTREE_MASK_HANDLE;
506 ret = m_lastId;
507 }
508 else
509 {
510 ret = info.m_itemId;
511 };
512
513 wxClientDC dc(this);
514 wxGenericTreeItem *new_child = new wxGenericTreeItem( p, info, &dc );
515 if (p)
516 p->AddChild( new_child );
517 else
518 m_anchor = new_child;
519
520 if (p)
521 {
522 CalculatePositions();
523
524 if (!p->HasChildren()) p->m_hasChildren = TRUE;
525
526 int ch = 0;
527 GetClientSize( NULL, &ch );
528
529 PrepareDC( dc );
530
531 wxRectangle rect;
532 rect.x = dc.LogicalToDeviceX( 0 );
533 rect.y = 0;
534 rect.width = 10000;
535 rect.height = ch;
536
537 if (p->m_children.Number() == 1)
538 {
539 rect.y = dc.LogicalToDeviceY( p->m_y );
540 }
541 else
542 {
543 wxNode *node = p->m_children.Member( new_child )->Previous();
544 wxGenericTreeItem* last_child = (wxGenericTreeItem*)node->Data();
545 rect.y = dc.LogicalToDeviceY( last_child->m_y );
546 };
547
548 AdjustMyScrollbars();
549
550 if (rect.height > 0) Refresh( FALSE, &rect);
551 }
552 else
553 {
554 AdjustMyScrollbars();
555
556 Refresh();
557 };
558
559 info.m_mask = oldMask;
560 return ret;
561 };
562
563 bool wxTreeCtrl::ExpandItem( long item, int action )
564 {
565 wxGenericTreeItem *i = FindItem( item );
566 if (!i)
567 return FALSE;
568
569 switch (action)
570 {
571 case wxTREE_EXPAND_EXPAND:
572 {
573 i->SendExpand( this );
574 break;
575 }
576
577 case wxTREE_EXPAND_COLLAPSE_RESET:
578 case wxTREE_EXPAND_COLLAPSE:
579 {
580 wxNode *node = i->m_children.First();
581 while (node)
582 {
583 wxGenericTreeItem *child = (wxGenericTreeItem*)node->Data();
584 if ( child->IsExpanded() )
585 ExpandItem( child->m_itemId, wxTREE_EXPAND_COLLAPSE );
586 node = node->Next();
587 };
588
589 CalculatePositions();
590
591 i->SendCollapse( this );
592 break;
593 }
594
595 case wxTREE_EXPAND_TOGGLE:
596 {
597 if ( i->IsExpanded() )
598 ExpandItem( item, wxTREE_EXPAND_COLLAPSE );
599 else
600 ExpandItem( item, wxTREE_EXPAND_EXPAND );
601 return TRUE;
602 }
603 };
604
605 wxClientDC dc(this);
606 PrepareDC(dc);
607
608 int cw = 0;
609 int ch = 0;
610 GetClientSize( &cw, &ch );
611
612 wxRect rect;
613 rect.x = dc.LogicalToDeviceX( 0 );
614 rect.width = cw;
615 rect.y = dc.LogicalToDeviceY( i->m_y );
616 rect.height = ch;
617 Refresh( TRUE, &rect );
618
619 AdjustMyScrollbars();
620
621 return TRUE;
622 };
623
624 void wxTreeCtrl::DeleteItem( long item )
625 {
626 wxGenericTreeItem *pItem = FindItem( item );
627 wxCHECK_RET( pItem != NULL, "wxTreeCtrl::DeleteItem: no such pItem." );
628
629 pItem->m_parent->m_children.DeleteObject(pItem);
630
631 Refresh();
632 }
633
634 void wxTreeCtrl::DeleteChildren( long item )
635 {
636 wxGenericTreeItem *pItem = FindItem( item );
637 wxCHECK_RET( pItem != NULL, "wxTreeCtrl::DeleteChildren: no such pItem." );
638
639 pItem->m_children.Clear();
640
641 Refresh();
642 }
643
644 bool wxTreeCtrl::DeleteAllItems()
645 {
646 delete m_anchor;
647 m_anchor = NULL;
648 Refresh();
649 return TRUE;
650 };
651
652 bool wxTreeCtrl::GetItem( wxTreeItem &info ) const
653 {
654 wxGenericTreeItem *i = FindItem( info.m_itemId );
655 if (!i) return FALSE;
656 i->GetItem( info );
657 return TRUE;
658 };
659
660 long wxTreeCtrl::GetItemData( long item ) const
661 {
662 wxGenericTreeItem *i = FindItem( item );
663 if (!i) return 0;
664 return i->m_data;
665 };
666
667 wxString wxTreeCtrl::GetItemText( long item ) const
668 {
669 wxGenericTreeItem *i = FindItem( item );
670 if (!i) return "";
671 return i->m_text;
672 };
673
674 int wxTreeCtrl::GetItemImage(long item) const
675 {
676 wxGenericTreeItem *i = FindItem( item );
677 return i == 0 ? -1 : i->GetImage();
678 }
679
680 long wxTreeCtrl::GetParent( long item ) const
681 {
682 wxGenericTreeItem *i = FindItem( item );
683 if (!i) return -1;
684 i = i->m_parent;
685 if (!i) return -1;
686 return i->m_parent->m_itemId;
687 };
688
689 long wxTreeCtrl::GetRootItem() const
690 {
691 if (m_anchor) return m_anchor->m_itemId;
692 return -1;
693 };
694
695 long wxTreeCtrl::GetSelection() const
696 {
697 return m_current ? m_current->GetItemId() : -1;
698 };
699
700 bool wxTreeCtrl::SelectItem(long itemId)
701 {
702 wxGenericTreeItem *pItem = FindItem(itemId);
703 if ( !pItem ) {
704 wxLogDebug("Can't select an item %d which doesn't exist.", itemId);
705
706 return FALSE;
707 }
708
709 SelectItem(pItem);
710
711 return TRUE;
712 };
713
714 void wxTreeCtrl::SelectItem(wxGenericTreeItem *item, bool bDoEvents )
715 {
716 if (m_current != item)
717 {
718 if (m_current)
719 {
720 m_current->SetHilight( FALSE );
721 RefreshLine( m_current );
722 };
723 m_current = item;
724 m_current->SetHilight( TRUE );
725 RefreshLine( m_current );
726
727 if (bDoEvents) m_current->SendSelected( this );
728 }
729 }
730
731 bool wxTreeCtrl::ItemHasChildren( long item ) const
732 {
733 wxGenericTreeItem *i = FindItem( item );
734 if (!i) return FALSE;
735 return i->m_hasChildren;
736 };
737
738 void wxTreeCtrl::SetIndent( int indent )
739 {
740 m_indent = indent;
741 Refresh();
742 };
743
744 int wxTreeCtrl::GetIndent() const
745 {
746 return m_indent;
747 };
748
749 bool wxTreeCtrl::SetItem( wxTreeItem &info )
750 {
751 wxGenericTreeItem *i = FindItem( info.m_itemId );
752 if (!i) return FALSE;
753 wxClientDC dc(this);
754 i->SetItem( info, &dc );
755 Refresh();
756 return TRUE;
757 };
758
759 bool wxTreeCtrl::SetItemData( long item, long data )
760 {
761 wxGenericTreeItem *i = FindItem( item );
762 if (!i) return FALSE;
763 i->m_data = data;
764 return TRUE;
765 };
766
767 bool wxTreeCtrl::SetItemText( long item, const wxString &text )
768 {
769 wxGenericTreeItem *i = FindItem( item );
770 if (!i) return FALSE;
771 wxClientDC dc(this);
772 i->SetText( text, &dc );
773 return TRUE;
774 };
775
776 void wxTreeCtrl::SetItemImage(long item, int image, int imageSel) const
777 {
778 wxGenericTreeItem *i = FindItem( item );
779 if ( i != 0 ) {
780 i->SetImage(image);
781 i->SetSelectedImage(imageSel);
782 }
783 }
784
785 long wxTreeCtrl::HitTest( const wxPoint& point, int &flags )
786 {
787 flags = 0;
788 if (!m_anchor) return -1;
789 return m_anchor->HitTest( point, flags );
790 };
791
792 wxImageList *wxTreeCtrl::GetImageList( int which ) const
793 {
794 if (which == wxIMAGE_LIST_NORMAL) return m_imageList;
795 return m_smallImageList;
796 };
797
798 void wxTreeCtrl::SetImageList( wxImageList *imageList, int which )
799 {
800 if (which == wxIMAGE_LIST_NORMAL)
801 {
802 if (m_imageList) delete m_imageList;
803 m_imageList = imageList;
804 }
805 else
806 {
807 if (m_smallImageList) delete m_smallImageList;
808 m_smallImageList = imageList;
809 };
810 };
811
812 void wxTreeCtrl::AdjustMyScrollbars()
813 {
814 if (m_anchor)
815 {
816 int x = 0;
817 int y = 0;
818 m_anchor->GetSize( x, y );
819 y += 2*m_lineHeight;
820 int x_pos = GetScrollPos( wxHORIZONTAL );
821 int y_pos = GetScrollPos( wxVERTICAL );
822 SetScrollbars( 10, 10, x/10, y/10, x_pos, y_pos );
823 }
824 else
825 {
826 SetScrollbars( 0, 0, 0, 0 );
827 };
828 };
829
830 void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxPaintDC &dc, int level, int &y )
831 {
832 int horizX = level*m_indent;
833
834 item->m_x = horizX+33;
835 item->m_y = y-m_lineHeight/3;
836 item->m_height = m_lineHeight;
837
838 item->SetCross( horizX+15, y );
839
840 int oldY = y;
841
842 int exposed_x = dc.LogicalToDeviceX( 0 );
843 int exposed_y = dc.LogicalToDeviceY( item->m_y-2 );
844
845 if (IsExposed( exposed_x, exposed_y, 1000, m_lineHeight+4 ))
846 {
847 int startX = horizX;
848 int endX = horizX + 10;
849
850 if (!item->HasChildren()) endX += 20;
851
852 dc.DrawLine( startX, y, endX, y );
853
854 if (item->HasChildren())
855 {
856 dc.DrawLine( horizX+20, y, horizX+30, y );
857 dc.SetPen( *wxGREY_PEN );
858 dc.DrawRectangle( horizX+10, y-4, 11, 9 );
859 dc.SetPen( *wxBLACK_PEN );
860 dc.DrawLine( horizX+13, y, horizX+18, y );
861 if (item->HasPlus())
862 dc.DrawLine( horizX+15, y-2, horizX+15, y+3 );
863 };
864
865 if (item->HasHilight())
866 {
867 dc.SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
868 dc.SetBrush( *m_hilightBrush );
869 long tw, th;
870 dc.GetTextExtent( item->m_text, &tw, &th );
871 if (m_hasFocus)
872 {
873 dc.SetPen( *wxBLACK_PEN );
874 dc.DrawRectangle( item->m_x-2, item->m_y-2, tw+4, th+4 );
875 }
876 else
877 {
878 dc.SetPen( *wxTRANSPARENT_PEN );
879 dc.DrawRectangle( item->m_x-2, item->m_y-2, tw+4, th+4 );
880 }
881 dc.DrawText( item->m_text, item->m_x, item->m_y );
882
883 dc.SetPen( *wxBLACK_PEN );
884 dc.SetTextForeground( *wxBLACK );
885 dc.SetBrush( *wxWHITE_BRUSH );
886 }
887 else
888 {
889 dc.SetBrush( *wxWHITE_BRUSH );
890 dc.SetPen( *wxTRANSPARENT_PEN );
891 long tw, th;
892 dc.GetTextExtent( item->m_text, &tw, &th );
893 dc.DrawRectangle( item->m_x-2, item->m_y-2, tw+4, th+4 );
894 dc.DrawText( item->m_text, item->m_x, item->m_y );
895 dc.SetPen( *wxBLACK_PEN );
896 };
897 };
898
899 if (item->NumberOfVisibleChildren() == 0) return;
900
901 int semiOldY = y;
902
903 wxNode *node = item->m_children.First();
904 while (node)
905 {
906 wxGenericTreeItem *child = (wxGenericTreeItem *)node->Data();
907
908 y += m_lineHeight;
909 semiOldY = y;
910
911 PaintLevel( child, dc, level+1, y );
912
913 node = node->Next();
914 };
915
916 dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY );
917 }
918
919 void wxTreeCtrl::OnPaint( const wxPaintEvent &WXUNUSED(event) )
920 {
921 if (!m_anchor) return;
922
923 wxPaintDC dc(this);
924 PrepareDC( dc );
925
926 dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) );
927
928 dc.SetPen( m_dottedPen );
929 m_lineHeight = (int)(dc.GetCharHeight() + 4);
930
931 int y = m_lineHeight / 2 + 2;
932 PaintLevel( m_anchor, dc, 0, y );
933 };
934
935 void wxTreeCtrl::OnSetFocus( const wxFocusEvent &WXUNUSED(event) )
936 {
937 m_hasFocus = TRUE;
938 if (m_current) RefreshLine( m_current );
939 };
940
941 void wxTreeCtrl::OnKillFocus( const wxFocusEvent &WXUNUSED(event) )
942 {
943 m_hasFocus = FALSE;
944 if (m_current) RefreshLine( m_current );
945 };
946
947 void wxTreeCtrl::OnChar( wxKeyEvent &event )
948 {
949 event.Skip();
950 };
951
952 void wxTreeCtrl::OnMouse( const wxMouseEvent &event )
953 {
954 if (!event.LeftDown() &&
955 !event.LeftDClick()) return;
956
957 wxClientDC dc(this);
958 PrepareDC(dc);
959 long x = dc.DeviceToLogicalX( (long)event.GetX() );
960 long y = dc.DeviceToLogicalY( (long)event.GetY() );
961
962 int flag = 0;
963 long id = HitTest( wxPoint(x,y), flag );
964 if (id == -1)
965 return;
966 wxGenericTreeItem *item = FindItem( id );
967
968 if (!item) return;
969 if ((flag != wxTREE_HITTEST_ONITEMBUTTON) &&
970 (flag != wxTREE_HITTEST_ONITEMLABEL)) return;
971
972 SelectItem(item);
973
974 if (event.LeftDClick())
975 m_current->SendKeyDown( this );
976
977 if (flag == wxTREE_HITTEST_ONITEMBUTTON)
978 {
979 ExpandItem( item->m_itemId, wxTREE_EXPAND_TOGGLE );
980 return;
981 };
982 };
983
984 void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item, wxPaintDC &dc, int level, int &y )
985 {
986 int horizX = level*m_indent;
987
988 item->m_x = horizX+33;
989 item->m_y = y-m_lineHeight/3-2;
990 item->m_height = m_lineHeight;
991
992 if (item->NumberOfVisibleChildren() == 0) return;
993
994 wxNode *node = item->m_children.First();
995 while (node)
996 {
997 wxGenericTreeItem *child = (wxGenericTreeItem *)node->Data();
998
999 y += m_lineHeight;
1000 CalculateLevel( child, dc, level+1, y );
1001
1002 node = node->Next();
1003 };
1004 };
1005
1006 void wxTreeCtrl::CalculatePositions()
1007 {
1008 if (!m_anchor)
1009 return;
1010
1011 wxClientDC dc(this);
1012 PrepareDC( dc );
1013
1014 dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) );
1015
1016 dc.SetPen( m_dottedPen );
1017 m_lineHeight = (int)(dc.GetCharHeight() + 4);
1018
1019 int y = m_lineHeight / 2 + 2;
1020 CalculateLevel( m_anchor, dc, 0, y );
1021 };
1022
1023 wxGenericTreeItem *wxTreeCtrl::FindItem( long itemId ) const
1024 {
1025 if (!m_anchor) return NULL;
1026 return m_anchor->FindItem( itemId );
1027 };
1028
1029 void wxTreeCtrl::RefreshLine( wxGenericTreeItem *item )
1030 {
1031 if (!item) return;
1032 wxClientDC dc(this);
1033 PrepareDC( dc );
1034 wxRect rect;
1035 rect.x = dc.LogicalToDeviceX( item->m_x-2 );
1036 rect.y = dc.LogicalToDeviceY( item->m_y-2 );
1037 rect.width = 1000;
1038 rect.height = dc.GetCharHeight()+6;
1039 Refresh( TRUE, &rect );
1040 };
1041
1042
1043