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