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