Implement and document wxDataViewTreeCtrl::IsContainer(), use it in the sample to...
[wxWidgets.git] / src / common / datavcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/datavcmn.cpp
3 // Purpose: wxDataViewCtrl base classes and common parts
4 // Author: Robert Roebling
5 // Created: 2006/02/20
6 // RCS-ID: $Id$
7 // Copyright: (c) 2006, Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_DATAVIEWCTRL
19
20 #include "wx/dataview.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/dc.h"
24 #include "wx/settings.h"
25 #include "wx/log.h"
26 #include "wx/crt.h"
27 #endif
28
29 #include "wx/spinctrl.h"
30 #include "wx/choice.h"
31 #include "wx/imaglist.h"
32
33 const char wxDataViewCtrlNameStr[] = "dataviewCtrl";
34
35 // ---------------------------------------------------------
36 // wxDataViewModelNotifier
37 // ---------------------------------------------------------
38
39 #include "wx/listimpl.cpp"
40 WX_DEFINE_LIST(wxDataViewModelNotifiers)
41
42 bool wxDataViewModelNotifier::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
43 {
44 size_t count = items.GetCount();
45 size_t i;
46 for (i = 0; i < count; i++)
47 if (!ItemAdded( parent, items[i] )) return false;
48
49 return true;
50 }
51
52 bool wxDataViewModelNotifier::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
53 {
54 size_t count = items.GetCount();
55 size_t i;
56 for (i = 0; i < count; i++)
57 if (!ItemDeleted( parent, items[i] )) return false;
58
59 return true;
60 }
61
62 bool wxDataViewModelNotifier::ItemsChanged( const wxDataViewItemArray &items )
63 {
64 size_t count = items.GetCount();
65 size_t i;
66 for (i = 0; i < count; i++)
67 if (!ItemChanged( items[i] )) return false;
68
69 return true;
70 }
71
72 // ---------------------------------------------------------
73 // wxDataViewModel
74 // ---------------------------------------------------------
75
76 wxDataViewModel::wxDataViewModel()
77 {
78 m_notifiers.DeleteContents( true );
79 }
80
81 bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
82 {
83 bool ret = true;
84
85 wxDataViewModelNotifiers::iterator iter;
86 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
87 {
88 wxDataViewModelNotifier* notifier = *iter;
89 if (!notifier->ItemAdded( parent, item ))
90 ret = false;
91 }
92
93 return ret;
94 }
95
96 bool wxDataViewModel::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
97 {
98 bool ret = true;
99
100 wxDataViewModelNotifiers::iterator iter;
101 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
102 {
103 wxDataViewModelNotifier* notifier = *iter;
104 if (!notifier->ItemDeleted( parent, item ))
105 ret = false;
106 }
107
108 return ret;
109 }
110
111 bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
112 {
113 bool ret = true;
114
115 wxDataViewModelNotifiers::iterator iter;
116 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
117 {
118 wxDataViewModelNotifier* notifier = *iter;
119 if (!notifier->ItemChanged( item ))
120 ret = false;
121 }
122
123 return ret;
124 }
125
126 bool wxDataViewModel::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
127 {
128 bool ret = true;
129
130 wxDataViewModelNotifiers::iterator iter;
131 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
132 {
133 wxDataViewModelNotifier* notifier = *iter;
134 if (!notifier->ItemsAdded( parent, items ))
135 ret = false;
136 }
137
138 return ret;
139 }
140
141 bool wxDataViewModel::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
142 {
143 bool ret = true;
144
145 wxDataViewModelNotifiers::iterator iter;
146 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
147 {
148 wxDataViewModelNotifier* notifier = *iter;
149 if (!notifier->ItemsDeleted( parent, items ))
150 ret = false;
151 }
152
153 return ret;
154 }
155
156 bool wxDataViewModel::ItemsChanged( const wxDataViewItemArray &items )
157 {
158 bool ret = true;
159
160 wxDataViewModelNotifiers::iterator iter;
161 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
162 {
163 wxDataViewModelNotifier* notifier = *iter;
164 if (!notifier->ItemsChanged( items ))
165 ret = false;
166 }
167
168 return ret;
169 }
170
171 bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
172 {
173 bool ret = true;
174
175 wxDataViewModelNotifiers::iterator iter;
176 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
177 {
178 wxDataViewModelNotifier* notifier = *iter;
179 if (!notifier->ValueChanged( item, col ))
180 ret = false;
181 }
182
183 return ret;
184 }
185
186 bool wxDataViewModel::Cleared()
187 {
188 bool ret = true;
189
190 wxDataViewModelNotifiers::iterator iter;
191 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
192 {
193 wxDataViewModelNotifier* notifier = *iter;
194 if (!notifier->Cleared())
195 ret = false;
196 }
197
198 return ret;
199 }
200
201 void wxDataViewModel::Resort()
202 {
203 wxDataViewModelNotifiers::iterator iter;
204 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
205 {
206 wxDataViewModelNotifier* notifier = *iter;
207 notifier->Resort();
208 }
209 }
210
211 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
212 {
213 m_notifiers.push_back( notifier );
214 notifier->SetOwner( this );
215 }
216
217 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
218 {
219 m_notifiers.DeleteObject( notifier );
220 }
221
222 int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
223 unsigned int column, bool ascending ) const
224 {
225 // sort branches before leaves
226 bool item1_is_container = IsContainer(item1);
227 bool item2_is_container = IsContainer(item2);
228
229 if (item1_is_container && !item2_is_container)
230 return 1;
231 if (item2_is_container && !item1_is_container)
232 return -1;
233
234 wxVariant value1,value2;
235 GetValue( value1, item1, column );
236 GetValue( value2, item2, column );
237
238 if (!ascending)
239 {
240 wxVariant temp = value1;
241 value1 = value2;
242 value2 = temp;
243 }
244
245 if (value1.GetType() == wxT("string"))
246 {
247 wxString str1 = value1.GetString();
248 wxString str2 = value2.GetString();
249 int res = str1.Cmp( str2 );
250 if (res)
251 return res;
252 }
253 else if (value1.GetType() == wxT("long"))
254 {
255 long l1 = value1.GetLong();
256 long l2 = value2.GetLong();
257 long res = l1-l2;
258 if (res)
259 return res;
260 }
261 else if (value1.GetType() == wxT("double"))
262 {
263 double d1 = value1.GetDouble();
264 double d2 = value2.GetDouble();
265 if (d1 < d2)
266 return 1;
267 if (d1 > d2)
268 return -1;
269 }
270 else if (value1.GetType() == wxT("datetime"))
271 {
272 wxDateTime dt1 = value1.GetDateTime();
273 wxDateTime dt2 = value2.GetDateTime();
274 if (dt1.IsEarlierThan(dt2))
275 return 1;
276 if (dt2.IsEarlierThan(dt1))
277 return -1;
278 }
279
280 // items must be different
281 wxUIntPtr id1 = wxPtrToUInt(item1.GetID()),
282 id2 = wxPtrToUInt(item2.GetID());
283
284 return ascending ? id1 - id2 : id2 - id1;
285 }
286
287 // ---------------------------------------------------------
288 // wxDataViewIndexListModel
289 // ---------------------------------------------------------
290
291 static int my_sort( int *v1, int *v2 )
292 {
293 return *v2-*v1;
294 }
295
296
297 wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size )
298 {
299 // IDs are ordered until an item gets deleted or inserted
300 m_ordered = true;
301
302 // build initial index
303 unsigned int i;
304 for (i = 1; i < initial_size+1; i++)
305 m_hash.Add( wxUIntToPtr(i) );
306 m_nextFreeID = initial_size + 1;
307 }
308
309 void wxDataViewIndexListModel::Reset( unsigned int new_size )
310 {
311 m_hash.Clear();
312
313 // IDs are ordered until an item gets deleted or inserted
314 m_ordered = true;
315
316 // build initial index
317 unsigned int i;
318 for (i = 1; i < new_size+1; i++)
319 m_hash.Add( wxUIntToPtr(i) );
320
321 m_nextFreeID = new_size + 1;
322
323 wxDataViewModel::Cleared();
324 }
325
326 void wxDataViewIndexListModel::RowPrepended()
327 {
328 m_ordered = false;
329
330 unsigned int id = m_nextFreeID;
331 m_nextFreeID++;
332
333 m_hash.Insert( wxUIntToPtr(id), 0 );
334 wxDataViewItem item( wxUIntToPtr(id) );
335 ItemAdded( wxDataViewItem(0), item );
336
337 }
338
339 void wxDataViewIndexListModel::RowInserted( unsigned int before )
340 {
341 m_ordered = false;
342
343 unsigned int id = m_nextFreeID;
344 m_nextFreeID++;
345
346 m_hash.Insert( wxUIntToPtr(id), before );
347 wxDataViewItem item( wxUIntToPtr(id) );
348 ItemAdded( wxDataViewItem(0), item );
349 }
350
351 void wxDataViewIndexListModel::RowAppended()
352 {
353 unsigned int id = m_nextFreeID;
354 m_nextFreeID++;
355
356 m_hash.Add( wxUIntToPtr(id) );
357 wxDataViewItem item( wxUIntToPtr(id) );
358 ItemAdded( wxDataViewItem(0), item );
359 }
360
361 void wxDataViewIndexListModel::RowDeleted( unsigned int row )
362 {
363 m_ordered = false;
364
365 wxDataViewItem item( m_hash[row] );
366 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item );
367 m_hash.RemoveAt( row );
368 }
369
370 void wxDataViewIndexListModel::RowsDeleted( const wxArrayInt &rows )
371 {
372 wxArrayInt sorted = rows;
373 sorted.Sort( my_sort );
374
375 m_ordered = false;
376
377 wxDataViewItemArray array;
378 unsigned int i;
379 for (i = 0; i < rows.GetCount(); i++)
380 {
381 wxDataViewItem item( m_hash[rows[i]] );
382 array.Add( item );
383 }
384 wxDataViewModel::ItemsDeleted( wxDataViewItem(0), array );
385
386 for (i = 0; i < sorted.GetCount(); i++)
387 m_hash.RemoveAt( sorted[i] );
388 }
389
390 void wxDataViewIndexListModel::RowChanged( unsigned int row )
391 {
392 wxDataViewModel::ItemChanged( GetItem(row) );
393 }
394
395 void wxDataViewIndexListModel::RowValueChanged( unsigned int row, unsigned int col )
396 {
397 wxDataViewModel::ValueChanged( GetItem(row), col );
398 }
399
400 unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem &item ) const
401 {
402 if (m_ordered)
403 return wxPtrToUInt(item.GetID())-1;
404
405 // assert for not found
406 return (unsigned int) m_hash.Index( item.GetID() );
407 }
408
409 wxDataViewItem wxDataViewIndexListModel::GetItem( unsigned int row ) const
410 {
411 wxASSERT( row < m_hash.GetCount() );
412 return wxDataViewItem( m_hash[row] );
413 }
414
415 bool wxDataViewIndexListModel::HasDefaultCompare() const
416 {
417 return !m_ordered;
418 }
419
420 int wxDataViewIndexListModel::Compare(const wxDataViewItem& item1,
421 const wxDataViewItem& item2,
422 unsigned int WXUNUSED(column),
423 bool ascending) const
424 {
425 if (m_ordered)
426 {
427 unsigned int pos1 = wxPtrToUInt(item1.GetID()); // -1 not needed here
428 unsigned int pos2 = wxPtrToUInt(item2.GetID()); // -1 not needed here
429
430 if (ascending)
431 return pos1 - pos2;
432 else
433 return pos2 - pos1;
434 }
435
436 if (ascending)
437 return GetRow(item1) - GetRow(item2);
438
439 return GetRow(item2) - GetRow(item1);
440 }
441
442 unsigned int wxDataViewIndexListModel::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
443 {
444 if (item.IsOk())
445 return 0;
446
447 children = m_hash;
448
449 return m_hash.GetCount();
450 }
451
452 // ---------------------------------------------------------
453 // wxDataViewVirtualListModel
454 // ---------------------------------------------------------
455
456 #ifndef __WXMAC__
457
458 wxDataViewVirtualListModel::wxDataViewVirtualListModel( unsigned int initial_size )
459 {
460 m_size = initial_size;
461 }
462
463 void wxDataViewVirtualListModel::Reset( unsigned int new_size )
464 {
465 m_size = new_size;
466
467 wxDataViewModel::Cleared();
468 }
469
470 void wxDataViewVirtualListModel::RowPrepended()
471 {
472 m_size++;
473 wxDataViewItem item( wxUIntToPtr(1) );
474 ItemAdded( wxDataViewItem(0), item );
475 }
476
477 void wxDataViewVirtualListModel::RowInserted( unsigned int before )
478 {
479 m_size++;
480 wxDataViewItem item( wxUIntToPtr(before+1) );
481 ItemAdded( wxDataViewItem(0), item );
482 }
483
484 void wxDataViewVirtualListModel::RowAppended()
485 {
486 m_size++;
487 wxDataViewItem item( wxUIntToPtr(m_size) );
488 ItemAdded( wxDataViewItem(0), item );
489 }
490
491 void wxDataViewVirtualListModel::RowDeleted( unsigned int row )
492 {
493 m_size--;
494 wxDataViewItem item( wxUIntToPtr(row+1) );
495 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item );
496 }
497
498 void wxDataViewVirtualListModel::RowsDeleted( const wxArrayInt &rows )
499 {
500 m_size -= rows.GetCount();
501
502 wxArrayInt sorted = rows;
503 sorted.Sort( my_sort );
504
505 wxDataViewItemArray array;
506 unsigned int i;
507 for (i = 0; i < sorted.GetCount(); i++)
508 {
509 wxDataViewItem item( wxUIntToPtr(sorted[i]+1) );
510 array.Add( item );
511 }
512 wxDataViewModel::ItemsDeleted( wxDataViewItem(0), array );
513 }
514
515 void wxDataViewVirtualListModel::RowChanged( unsigned int row )
516 {
517 wxDataViewModel::ItemChanged( GetItem(row) );
518 }
519
520 void wxDataViewVirtualListModel::RowValueChanged( unsigned int row, unsigned int col )
521 {
522 wxDataViewModel::ValueChanged( GetItem(row), col );
523 }
524
525 unsigned int wxDataViewVirtualListModel::GetRow( const wxDataViewItem &item ) const
526 {
527 return wxPtrToUInt( item.GetID() ) -1;
528 }
529
530 wxDataViewItem wxDataViewVirtualListModel::GetItem( unsigned int row ) const
531 {
532 return wxDataViewItem( wxUIntToPtr(row+1) );
533 }
534
535 bool wxDataViewVirtualListModel::HasDefaultCompare() const
536 {
537 return true;
538 }
539
540 int wxDataViewVirtualListModel::Compare(const wxDataViewItem& item1,
541 const wxDataViewItem& item2,
542 unsigned int WXUNUSED(column),
543 bool ascending) const
544 {
545 unsigned int pos1 = wxPtrToUInt(item1.GetID()); // -1 not needed here
546 unsigned int pos2 = wxPtrToUInt(item2.GetID()); // -1 not needed here
547
548 if (ascending)
549 return pos1 - pos2;
550 else
551 return pos2 - pos1;
552 }
553
554 unsigned int wxDataViewVirtualListModel::GetChildren( const wxDataViewItem &WXUNUSED(item), wxDataViewItemArray &WXUNUSED(children) ) const
555 {
556 return 0; // should we report an error ?
557 }
558
559 #endif // __WXMAC__
560
561 //-----------------------------------------------------------------------------
562 // wxDataViewIconText
563 //-----------------------------------------------------------------------------
564
565 IMPLEMENT_DYNAMIC_CLASS(wxDataViewIconText,wxObject)
566
567 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxDataViewIconText, WXDLLIMPEXP_ADV)
568
569 // ---------------------------------------------------------
570 // wxDataViewRendererBase
571 // ---------------------------------------------------------
572
573 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
574
575 wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
576 wxDataViewCellMode WXUNUSED(mode),
577 int WXUNUSED(align) )
578 {
579 m_variantType = varianttype;
580 m_owner = NULL;
581 }
582
583 wxDataViewRendererBase::~wxDataViewRendererBase()
584 {
585 }
586
587 const wxDataViewCtrl* wxDataViewRendererBase::GetView() const
588 {
589 return const_cast<wxDataViewRendererBase*>(this)->GetOwner()->GetOwner();
590 }
591
592 class wxKillRef: public wxWindowRef
593 {
594 public:
595 wxKillRef( wxWindow *win ) : wxWindowRef( win ) { }
596 virtual void OnObjectDestroy()
597 {
598 get()->PopEventHandler( true );
599 m_pobj = NULL;
600 delete this;
601 }
602 };
603
604 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
605 {
606 wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
607
608 // Before doing anything we send an event asking if editing of this item is really wanted.
609 wxDataViewEvent start_event( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, dv_ctrl->GetId() );
610 start_event.SetDataViewColumn( GetOwner() );
611 start_event.SetModel( dv_ctrl->GetModel() );
612 start_event.SetItem( item );
613 start_event.SetEventObject( dv_ctrl );
614 dv_ctrl->GetEventHandler()->ProcessEvent( start_event );
615 if( !start_event.IsAllowed() )
616 return false;
617
618 m_item = item; // remember for later
619
620 unsigned int col = GetOwner()->GetModelColumn();
621 wxVariant value;
622 dv_ctrl->GetModel()->GetValue( value, item, col );
623
624 m_editorCtrl = CreateEditorCtrl( dv_ctrl->GetMainWindow(), labelRect, value );
625
626 // there might be no editor control for the given item
627 if(!m_editorCtrl)
628 return false;
629
630 (void) new wxKillRef( m_editorCtrl.get() );
631
632 wxDataViewEditorCtrlEvtHandler *handler =
633 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
634
635 m_editorCtrl->PushEventHandler( handler );
636
637 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
638 handler->SetFocusOnIdle();
639 #else
640 m_editorCtrl->SetFocus();
641 #endif
642
643 // Now we should send Editing Started event
644 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv_ctrl->GetId() );
645 event.SetDataViewColumn( GetOwner() );
646 event.SetModel( dv_ctrl->GetModel() );
647 event.SetItem( item );
648 event.SetEventObject( dv_ctrl );
649 dv_ctrl->GetEventHandler()->ProcessEvent( event );
650
651 return true;
652 }
653
654 void wxDataViewRendererBase::CancelEditing()
655 {
656 if (!m_editorCtrl)
657 return;
658
659 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
660
661 m_editorCtrl->Hide();
662 wxPendingDelete.Append( m_editorCtrl );
663 }
664
665 bool wxDataViewRendererBase::FinishEditing()
666 {
667 if (!m_editorCtrl)
668 return true;
669
670 wxVariant value;
671 GetValueFromEditorCtrl( m_editorCtrl, value );
672
673 wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
674
675 dv_ctrl->GetMainWindow()->SetFocus();
676
677 m_editorCtrl->Hide();
678 wxPendingDelete.Append( m_editorCtrl );
679
680 if (!Validate(value))
681 return false;
682
683 unsigned int col = GetOwner()->GetModelColumn();
684 dv_ctrl->GetModel()->ChangeValue(value, m_item, col);
685
686 // Now we should send Editing Done event
687 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv_ctrl->GetId() );
688 event.SetDataViewColumn( GetOwner() );
689 event.SetModel( dv_ctrl->GetModel() );
690 event.SetItem( m_item );
691 event.SetEventObject( dv_ctrl );
692 dv_ctrl->GetEventHandler()->ProcessEvent( event );
693
694 return true;
695 }
696
697 // ----------------------------------------------------------------------------
698 // wxDataViewCustomRendererBase
699 // ----------------------------------------------------------------------------
700
701 void
702 wxDataViewCustomRendererBase::WXCallRender(wxRect rectCell, wxDC *dc, int state)
703 {
704 wxCHECK_RET( dc, "no DC to draw on in custom renderer?" );
705
706 // adjust the rectangle ourselves to account for the alignment
707 wxRect rectItem = rectCell;
708 const int align = GetAlignment();
709 if ( align != wxDVR_DEFAULT_ALIGNMENT )
710 {
711 const wxSize size = GetSize();
712
713 // take alignment into account only if there is enough space, otherwise
714 // show as much contents as possible
715 //
716 // notice that many existing renderers (e.g. wxDataViewSpinRenderer)
717 // return hard-coded size which can be more than they need and if we
718 // trusted their GetSize() we'd draw the text out of cell bounds
719 // entirely
720
721 if ( size.x >= 0 && size.x < rectCell.width )
722 {
723 if ( align & wxALIGN_CENTER_HORIZONTAL )
724 rectItem.x += (rectCell.width - size.x)/2;
725 else if ( align & wxALIGN_RIGHT )
726 rectItem.x += rectCell.width - size.x;
727 // else: wxALIGN_LEFT is the default
728
729 rectItem.width = size.x;
730 }
731
732 if ( size.y >= 0 && size.y < rectCell.height )
733 {
734 if ( align & wxALIGN_CENTER_VERTICAL )
735 rectItem.y += (rectCell.height - size.y)/2;
736 else if ( align & wxALIGN_BOTTOM )
737 rectItem.y += rectCell.height - size.y;
738 // else: wxALIGN_TOP is the default
739
740 rectItem.height = size.y;
741 }
742 }
743
744
745 // set up the DC attributes
746
747 // override custom foreground with the standard one for the selected items
748 // because we currently don't allow changing the selection background and
749 // custom colours may be unreadable on it
750 wxColour col;
751 if ( state & wxDATAVIEW_CELL_SELECTED )
752 col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
753 else if ( m_attr.HasColour() )
754 col = m_attr.GetColour();
755 else // use default foreground
756 col = GetOwner()->GetOwner()->GetForegroundColour();
757
758 wxDCTextColourChanger changeFg(*dc, col);
759
760 wxDCFontChanger changeFont(*dc);
761 if ( m_attr.HasFont() )
762 {
763 wxFont font(dc->GetFont());
764 if ( m_attr.GetBold() )
765 font.MakeBold();
766 if ( m_attr.GetItalic() )
767 font.MakeItalic();
768
769 changeFont.Set(font);
770 }
771
772 Render(rectItem, dc, state);
773 }
774
775 void
776 wxDataViewCustomRendererBase::RenderText(const wxString& text,
777 int xoffset,
778 wxRect rect,
779 wxDC *dc,
780 int WXUNUSED(state))
781 {
782 wxRect rectText = rect;
783 rectText.x += xoffset;
784 rectText.width -= xoffset;
785
786 // check if we want to ellipsize the text if it doesn't fit
787 wxString ellipsizedText;
788 if ( GetEllipsizeMode() != wxELLIPSIZE_NONE )
789 {
790 ellipsizedText = wxControl::Ellipsize
791 (
792 text,
793 *dc,
794 GetEllipsizeMode(),
795 rect.width,
796 wxELLIPSIZE_FLAGS_NONE
797 );
798 }
799
800 dc->DrawLabel(ellipsizedText.empty() ? text : ellipsizedText,
801 rectText, GetAlignment());
802 }
803
804 //-----------------------------------------------------------------------------
805 // wxDataViewEditorCtrlEvtHandler
806 //-----------------------------------------------------------------------------
807
808 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
809 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
810 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
811 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
812 EVT_TEXT_ENTER (-1, wxDataViewEditorCtrlEvtHandler::OnTextEnter)
813 END_EVENT_TABLE()
814
815 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
816 wxControl *editorCtrl,
817 wxDataViewRenderer *owner )
818 {
819 m_owner = owner;
820 m_editorCtrl = editorCtrl;
821
822 m_finished = false;
823 }
824
825 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
826 {
827 if (m_focusOnIdle)
828 {
829 m_focusOnIdle = false;
830 if (wxWindow::FindFocus() != m_editorCtrl)
831 m_editorCtrl->SetFocus();
832 }
833
834 event.Skip();
835 }
836
837 void wxDataViewEditorCtrlEvtHandler::OnTextEnter( wxCommandEvent &WXUNUSED(event) )
838 {
839 m_finished = true;
840 m_owner->FinishEditing();
841 }
842
843 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
844 {
845 switch ( event.m_keyCode )
846 {
847 case WXK_RETURN:
848 m_finished = true;
849 m_owner->FinishEditing();
850 break;
851
852 case WXK_ESCAPE:
853 {
854 m_finished = true;
855 m_owner->CancelEditing();
856 break;
857 }
858 default:
859 event.Skip();
860 }
861 }
862
863 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
864 {
865 if (!m_finished)
866 {
867 m_finished = true;
868 m_owner->FinishEditing();
869 }
870
871 event.Skip();
872 }
873
874 // ---------------------------------------------------------
875 // wxDataViewColumnBase
876 // ---------------------------------------------------------
877
878 void wxDataViewColumnBase::Init(wxDataViewRenderer *renderer,
879 unsigned int model_column)
880 {
881 m_renderer = renderer;
882 m_model_column = model_column;
883 m_owner = NULL;
884 m_renderer->SetOwner( (wxDataViewColumn*) this );
885 }
886
887 wxDataViewColumnBase::~wxDataViewColumnBase()
888 {
889 delete m_renderer;
890 }
891
892 // ---------------------------------------------------------
893 // wxDataViewCtrlBase
894 // ---------------------------------------------------------
895
896 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
897
898 wxDataViewCtrlBase::wxDataViewCtrlBase()
899 {
900 m_model = NULL;
901 m_expander_column = 0;
902 m_indent = 8;
903 }
904
905 wxDataViewCtrlBase::~wxDataViewCtrlBase()
906 {
907 if (m_model)
908 {
909 m_model->DecRef();
910 m_model = NULL;
911 }
912 }
913
914 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
915 {
916 if (m_model)
917 {
918 m_model->DecRef(); // discard old model, if any
919 }
920
921 // add our own reference to the new model:
922 m_model = model;
923 if (m_model)
924 {
925 m_model->IncRef();
926 }
927
928 return true;
929 }
930
931 wxDataViewModel* wxDataViewCtrlBase::GetModel()
932 {
933 return m_model;
934 }
935
936 const wxDataViewModel* wxDataViewCtrlBase::GetModel() const
937 {
938 return m_model;
939 }
940
941 void wxDataViewCtrlBase::ExpandAncestors( const wxDataViewItem & item )
942 {
943 if (!m_model) return;
944
945 if (!item.IsOk()) return;
946
947 wxVector<wxDataViewItem> parentChain;
948
949 // at first we get all the parents of the selected item
950 wxDataViewItem parent = m_model->GetParent(item);
951 while (parent.IsOk())
952 {
953 parentChain.push_back(parent);
954 parent = m_model->GetParent(parent);
955 }
956
957 // then we expand the parents, starting at the root
958 while (!parentChain.empty())
959 {
960 Expand(parentChain.back());
961 parentChain.pop_back();
962 }
963 }
964
965 wxDataViewColumn *
966 wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
967 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
968 {
969 wxDataViewColumn *ret = new wxDataViewColumn( label,
970 new wxDataViewTextRenderer( wxT("string"), mode ),
971 model_column, width, align, flags );
972 AppendColumn( ret );
973 return ret;
974 }
975
976 wxDataViewColumn *
977 wxDataViewCtrlBase::AppendIconTextColumn( const wxString &label, unsigned int model_column,
978 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
979 {
980 wxDataViewColumn *ret = new wxDataViewColumn( label,
981 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
982 model_column, width, align, flags );
983 AppendColumn( ret );
984 return ret;
985 }
986
987 wxDataViewColumn *
988 wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
989 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
990 {
991 wxDataViewColumn *ret = new wxDataViewColumn( label,
992 new wxDataViewToggleRenderer( wxT("bool"), mode ),
993 model_column, width, align, flags );
994 AppendColumn( ret );
995 return ret;
996 }
997
998 wxDataViewColumn *
999 wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
1000 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1001 {
1002 wxDataViewColumn *ret = new wxDataViewColumn( label,
1003 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1004 model_column, width, align, flags );
1005 AppendColumn( ret );
1006 return ret;
1007 }
1008
1009 wxDataViewColumn *
1010 wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
1011 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1012 {
1013 wxDataViewColumn *ret = new wxDataViewColumn( label,
1014 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1015 model_column, width, align, flags );
1016 AppendColumn( ret );
1017 return ret;
1018 }
1019
1020 wxDataViewColumn *
1021 wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
1022 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1023 {
1024 wxDataViewColumn *ret = new wxDataViewColumn( label,
1025 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1026 model_column, width, align, flags );
1027 AppendColumn( ret );
1028 return ret;
1029 }
1030
1031 wxDataViewColumn *
1032 wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
1033 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1034 {
1035 wxDataViewColumn *ret = new wxDataViewColumn( label,
1036 new wxDataViewTextRenderer( wxT("string"), mode ),
1037 model_column, width, align, flags );
1038 AppendColumn( ret );
1039 return ret;
1040 }
1041
1042 wxDataViewColumn *
1043 wxDataViewCtrlBase::AppendIconTextColumn( const wxBitmap &label, unsigned int model_column,
1044 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1045 {
1046 wxDataViewColumn *ret = new wxDataViewColumn( label,
1047 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1048 model_column, width, align, flags );
1049 AppendColumn( ret );
1050 return ret;
1051 }
1052
1053 wxDataViewColumn *
1054 wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
1055 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1056 {
1057 wxDataViewColumn *ret = new wxDataViewColumn( label,
1058 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1059 model_column, width, align, flags );
1060 AppendColumn( ret );
1061 return ret;
1062 }
1063
1064 wxDataViewColumn *
1065 wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
1066 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1067 {
1068 wxDataViewColumn *ret = new wxDataViewColumn( label,
1069 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1070 model_column, width, align, flags );
1071 AppendColumn( ret );
1072 return ret;
1073 }
1074
1075 wxDataViewColumn *
1076 wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
1077 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1078 {
1079 wxDataViewColumn *ret = new wxDataViewColumn( label,
1080 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1081 model_column, width, align, flags );
1082 AppendColumn( ret );
1083 return ret;
1084 }
1085
1086 wxDataViewColumn *
1087 wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
1088 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1089 {
1090 wxDataViewColumn *ret = new wxDataViewColumn( label,
1091 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1092 model_column, width, align, flags );
1093 AppendColumn( ret );
1094 return ret;
1095 }
1096
1097 wxDataViewColumn *
1098 wxDataViewCtrlBase::PrependTextColumn( const wxString &label, unsigned int model_column,
1099 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1100 {
1101 wxDataViewColumn *ret = new wxDataViewColumn( label,
1102 new wxDataViewTextRenderer( wxT("string"), mode ),
1103 model_column, width, align, flags );
1104 PrependColumn( ret );
1105 return ret;
1106 }
1107
1108 wxDataViewColumn *
1109 wxDataViewCtrlBase::PrependIconTextColumn( const wxString &label, unsigned int model_column,
1110 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1111 {
1112 wxDataViewColumn *ret = new wxDataViewColumn( label,
1113 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1114 model_column, width, align, flags );
1115 PrependColumn( ret );
1116 return ret;
1117 }
1118
1119 wxDataViewColumn *
1120 wxDataViewCtrlBase::PrependToggleColumn( const wxString &label, unsigned int model_column,
1121 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1122 {
1123
1124 wxDataViewColumn *ret = new wxDataViewColumn( label,
1125 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1126 model_column, width, align, flags );
1127 PrependColumn( ret );
1128 return ret;
1129 }
1130
1131 wxDataViewColumn *
1132 wxDataViewCtrlBase::PrependProgressColumn( const wxString &label, unsigned int model_column,
1133 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1134 {
1135 wxDataViewColumn *ret = new wxDataViewColumn( label,
1136 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1137 model_column, width, align, flags );
1138 PrependColumn( ret );
1139 return ret;
1140 }
1141
1142 wxDataViewColumn *
1143 wxDataViewCtrlBase::PrependDateColumn( const wxString &label, unsigned int model_column,
1144 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1145 {
1146 wxDataViewColumn *ret = new wxDataViewColumn( label,
1147 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1148 model_column, width, align, flags );
1149 PrependColumn( ret );
1150 return ret;
1151 }
1152
1153 wxDataViewColumn *
1154 wxDataViewCtrlBase::PrependBitmapColumn( const wxString &label, unsigned int model_column,
1155 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1156 {
1157 wxDataViewColumn *ret = new wxDataViewColumn( label,
1158 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1159 model_column, width, align, flags );
1160 PrependColumn( ret );
1161 return ret;
1162 }
1163
1164 wxDataViewColumn *
1165 wxDataViewCtrlBase::PrependTextColumn( const wxBitmap &label, unsigned int model_column,
1166 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1167 {
1168 wxDataViewColumn *ret = new wxDataViewColumn( label,
1169 new wxDataViewTextRenderer( wxT("string"), mode ),
1170 model_column, width, align, flags );
1171 PrependColumn( ret );
1172 return ret;
1173 }
1174
1175 wxDataViewColumn *
1176 wxDataViewCtrlBase::PrependIconTextColumn( const wxBitmap &label, unsigned int model_column,
1177 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1178 {
1179 wxDataViewColumn *ret = new wxDataViewColumn( label,
1180 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1181 model_column, width, align, flags );
1182 PrependColumn( ret );
1183 return ret;
1184 }
1185
1186 wxDataViewColumn *
1187 wxDataViewCtrlBase::PrependToggleColumn( const wxBitmap &label, unsigned int model_column,
1188 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1189 {
1190 wxDataViewColumn *ret = new wxDataViewColumn( label,
1191 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1192 model_column, width, align, flags );
1193 PrependColumn( ret );
1194 return ret;
1195 }
1196
1197 wxDataViewColumn *
1198 wxDataViewCtrlBase::PrependProgressColumn( const wxBitmap &label, unsigned int model_column,
1199 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1200 {
1201 wxDataViewColumn *ret = new wxDataViewColumn( label,
1202 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1203 model_column, width, align, flags );
1204 PrependColumn( ret );
1205 return ret;
1206 }
1207
1208 wxDataViewColumn *
1209 wxDataViewCtrlBase::PrependDateColumn( const wxBitmap &label, unsigned int model_column,
1210 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1211 {
1212 wxDataViewColumn *ret = new wxDataViewColumn( label,
1213 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1214 model_column, width, align, flags );
1215 PrependColumn( ret );
1216 return ret;
1217 }
1218
1219 wxDataViewColumn *
1220 wxDataViewCtrlBase::PrependBitmapColumn( const wxBitmap &label, unsigned int model_column,
1221 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1222 {
1223 wxDataViewColumn *ret = new wxDataViewColumn( label,
1224 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1225 model_column, width, align, flags );
1226 PrependColumn( ret );
1227 return ret;
1228 }
1229
1230 bool
1231 wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
1232 {
1233 col->SetOwner( (wxDataViewCtrl*) this );
1234 return true;
1235 }
1236
1237 bool
1238 wxDataViewCtrlBase::PrependColumn( wxDataViewColumn *col )
1239 {
1240 col->SetOwner( (wxDataViewCtrl*) this );
1241 return true;
1242 }
1243
1244 bool
1245 wxDataViewCtrlBase::InsertColumn( unsigned int WXUNUSED(pos), wxDataViewColumn *col )
1246 {
1247 col->SetOwner( (wxDataViewCtrl*) this );
1248 return true;
1249 }
1250
1251 // ---------------------------------------------------------
1252 // wxDataViewEvent
1253 // ---------------------------------------------------------
1254
1255 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
1256
1257 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEvent );
1258
1259 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEvent );
1260 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, wxDataViewEvent );
1261 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, wxDataViewEvent );
1262 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, wxDataViewEvent );
1263 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, wxDataViewEvent );
1264 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, wxDataViewEvent );
1265 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, wxDataViewEvent );
1266 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEvent );
1267 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEvent );
1268
1269 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEvent );
1270
1271 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, wxDataViewEvent );
1272 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, wxDataViewEvent );
1273 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, wxDataViewEvent );
1274 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED, wxDataViewEvent );
1275
1276 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_CACHE_HINT, wxDataViewEvent );
1277
1278 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, wxDataViewEvent );
1279 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, wxDataViewEvent );
1280 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, wxDataViewEvent );
1281
1282
1283
1284 // -------------------------------------
1285 // wxDataViewSpinRenderer
1286 // -------------------------------------
1287
1288 wxDataViewSpinRenderer::wxDataViewSpinRenderer( int min, int max, wxDataViewCellMode mode, int alignment ) :
1289 wxDataViewCustomRenderer(wxT("long"), mode, alignment )
1290 {
1291 m_min = min;
1292 m_max = max;
1293 }
1294
1295 wxControl* wxDataViewSpinRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
1296 {
1297 long l = value;
1298 wxSize size = labelRect.GetSize();
1299 #ifdef __WXMAC__
1300 size = wxSize( wxMax(70,labelRect.width ), -1 );
1301 #endif
1302 wxString str;
1303 str.Printf( wxT("%d"), (int) l );
1304 wxSpinCtrl *sc = new wxSpinCtrl( parent, wxID_ANY, str,
1305 labelRect.GetTopLeft(), size, wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER, m_min, m_max, l );
1306 #ifdef __WXMAC__
1307 size = sc->GetSize();
1308 wxPoint pt = sc->GetPosition();
1309 sc->SetSize( pt.x - 4, pt.y - 4, size.x, size.y );
1310 #endif
1311
1312 return sc;
1313 }
1314
1315 bool wxDataViewSpinRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVariant &value )
1316 {
1317 wxSpinCtrl *sc = (wxSpinCtrl*) editor;
1318 long l = sc->GetValue();
1319 value = l;
1320 return true;
1321 }
1322
1323 bool wxDataViewSpinRenderer::Render( wxRect rect, wxDC *dc, int state )
1324 {
1325 wxString str;
1326 str.Printf(wxT("%d"), (int) m_data );
1327 RenderText( str, 0, rect, dc, state );
1328 return true;
1329 }
1330
1331 wxSize wxDataViewSpinRenderer::GetSize() const
1332 {
1333 return wxSize(80,16);
1334 }
1335
1336 bool wxDataViewSpinRenderer::SetValue( const wxVariant &value )
1337 {
1338 m_data = value.GetLong();
1339 return true;
1340 }
1341
1342 bool wxDataViewSpinRenderer::GetValue( wxVariant &value ) const
1343 {
1344 value = m_data;
1345 return true;
1346 }
1347
1348 // -------------------------------------
1349 // wxDataViewChoiceRenderer
1350 // -------------------------------------
1351
1352 #if defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXOSX_CARBON__)
1353
1354 wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString& choices, wxDataViewCellMode mode, int alignment ) :
1355 wxDataViewCustomRenderer(wxT("string"), mode, alignment )
1356 {
1357 m_choices = choices;
1358 }
1359
1360 wxControl* wxDataViewChoiceRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
1361 {
1362 wxString s = value;
1363 wxSize size = labelRect.GetSize();
1364 #ifdef __WXMAC__
1365 size = wxSize( wxMax(70,labelRect.width ), -1 );
1366 #endif
1367 wxChoice *c = new wxChoice( parent, wxID_ANY, labelRect.GetTopLeft(), size, m_choices );
1368 c->SetStringSelection( value.GetString() );
1369
1370 return c;
1371 }
1372
1373 bool wxDataViewChoiceRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVariant &value )
1374 {
1375 wxChoice *c = (wxChoice*) editor;
1376 wxString s = c->GetStringSelection();
1377 value = s;
1378 return true;
1379 }
1380
1381 bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state )
1382 {
1383 RenderText( m_data, 0, rect, dc, state );
1384 return true;
1385 }
1386
1387 wxSize wxDataViewChoiceRenderer::GetSize() const
1388 {
1389 return wxSize(80,16);
1390 }
1391
1392 bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
1393 {
1394 m_data = value.GetString();
1395 return true;
1396 }
1397
1398 bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
1399 {
1400 value = m_data;
1401 return true;
1402 }
1403
1404 #endif
1405
1406 //-----------------------------------------------------------------------------
1407 // wxDataViewListStore
1408 //-----------------------------------------------------------------------------
1409
1410 wxDataViewListStore::wxDataViewListStore()
1411 {
1412 }
1413
1414 wxDataViewListStore::~wxDataViewListStore()
1415 {
1416 wxVector<wxDataViewListStoreLine*>::iterator it;
1417 for (it = m_data.begin(); it != m_data.end(); ++it)
1418 {
1419 wxDataViewListStoreLine* line = *it;
1420 delete line;
1421 }
1422 }
1423
1424 void wxDataViewListStore::PrependColumn( const wxString &varianttype )
1425 {
1426 m_cols.Insert( varianttype, 0 );
1427 }
1428
1429 void wxDataViewListStore::InsertColumn( unsigned int pos, const wxString &varianttype )
1430 {
1431 m_cols.Insert( varianttype, pos );
1432 }
1433
1434 void wxDataViewListStore::AppendColumn( const wxString &varianttype )
1435 {
1436 m_cols.Add( varianttype );
1437 }
1438
1439 unsigned int wxDataViewListStore::GetColumnCount() const
1440 {
1441 return m_cols.GetCount();
1442 }
1443
1444 wxString wxDataViewListStore::GetColumnType( unsigned int pos ) const
1445 {
1446 return m_cols[pos];
1447 }
1448
1449 void wxDataViewListStore::AppendItem( const wxVector<wxVariant> &values, wxClientData *data )
1450 {
1451 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1452 line->m_values = values;
1453 m_data.push_back( line );
1454
1455 RowAppended();
1456 }
1457
1458 void wxDataViewListStore::PrependItem( const wxVector<wxVariant> &values, wxClientData *data )
1459 {
1460 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1461 line->m_values = values;
1462 m_data.insert( m_data.begin(), line );
1463
1464 RowPrepended();
1465 }
1466
1467 void wxDataViewListStore::InsertItem( unsigned int row, const wxVector<wxVariant> &values,
1468 wxClientData *data )
1469 {
1470 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1471 line->m_values = values;
1472 m_data.insert( m_data.begin()+row, line );
1473
1474 RowInserted( row );
1475 }
1476
1477 void wxDataViewListStore::DeleteItem( unsigned int row )
1478 {
1479 wxVector<wxDataViewListStoreLine*>::iterator it = m_data.begin() + row;
1480 m_data.erase( it );
1481
1482 RowDeleted( row );
1483 }
1484
1485 void wxDataViewListStore::DeleteAllItems()
1486 {
1487 wxVector<wxDataViewListStoreLine*>::iterator it;
1488 for (it = m_data.begin(); it != m_data.end(); ++it)
1489 {
1490 wxDataViewListStoreLine* line = *it;
1491 delete line;
1492 }
1493
1494 m_data.clear();
1495
1496 Reset( 0 );
1497 }
1498
1499 void wxDataViewListStore::GetValueByRow( wxVariant &value, unsigned int row, unsigned int col ) const
1500 {
1501 wxDataViewListStoreLine *line = m_data[row];
1502 value = line->m_values[col];
1503 }
1504
1505 bool wxDataViewListStore::SetValueByRow( const wxVariant &value, unsigned int row, unsigned int col )
1506 {
1507 wxDataViewListStoreLine *line = m_data[row];
1508 line->m_values[col] = value;
1509
1510 return true;
1511 }
1512
1513 //-----------------------------------------------------------------------------
1514 // wxDataViewListCtrl
1515 //-----------------------------------------------------------------------------
1516
1517 IMPLEMENT_DYNAMIC_CLASS(wxDataViewListCtrl,wxDataViewCtrl)
1518
1519 BEGIN_EVENT_TABLE(wxDataViewListCtrl,wxDataViewCtrl)
1520 EVT_SIZE( wxDataViewListCtrl::OnSize )
1521 END_EVENT_TABLE()
1522
1523 wxDataViewListCtrl::wxDataViewListCtrl()
1524 {
1525 }
1526
1527 wxDataViewListCtrl::wxDataViewListCtrl( wxWindow *parent, wxWindowID id,
1528 const wxPoint& pos, const wxSize& size, long style,
1529 const wxValidator& validator )
1530 {
1531 Create( parent, id, pos, size, style, validator );
1532
1533 wxDataViewListStore *store = new wxDataViewListStore;
1534 AssociateModel( store );
1535 store->DecRef();
1536 }
1537
1538 wxDataViewListCtrl::~wxDataViewListCtrl()
1539 {
1540 }
1541
1542
1543 bool wxDataViewListCtrl::Create( wxWindow *parent, wxWindowID id,
1544 const wxPoint& pos, const wxSize& size, long style,
1545 const wxValidator& validator )
1546 {
1547 return wxDataViewCtrl::Create( parent, id, pos, size, style, validator );
1548 }
1549
1550 bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *column, const wxString &varianttype )
1551 {
1552 GetStore()->AppendColumn( varianttype );
1553 return wxDataViewCtrl::AppendColumn( column );
1554 }
1555
1556 bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *column, const wxString &varianttype )
1557 {
1558 GetStore()->PrependColumn( varianttype );
1559 return wxDataViewCtrl::PrependColumn( column );
1560 }
1561
1562 bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *column, const wxString &varianttype )
1563 {
1564 GetStore()->InsertColumn( pos, varianttype );
1565 return wxDataViewCtrl::InsertColumn( pos, column );
1566 }
1567
1568 bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *col )
1569 {
1570 return PrependColumn( col, "string" );
1571 }
1572
1573 bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
1574 {
1575 return InsertColumn( pos, col, "string" );
1576 }
1577
1578 bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *col )
1579 {
1580 return AppendColumn( col, "string" );
1581 }
1582
1583 wxDataViewColumn *wxDataViewListCtrl::AppendTextColumn( const wxString &label,
1584 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1585 {
1586 GetStore()->AppendColumn( wxT("string") );
1587
1588 wxDataViewColumn *ret = new wxDataViewColumn( label,
1589 new wxDataViewTextRenderer( wxT("string"), mode ),
1590 GetStore()->GetColumnCount()-1, width, align, flags );
1591
1592 wxDataViewCtrl::AppendColumn( ret );
1593
1594 return ret;
1595 }
1596
1597 wxDataViewColumn *wxDataViewListCtrl::AppendToggleColumn( const wxString &label,
1598 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1599 {
1600 GetStore()->AppendColumn( wxT("bool") );
1601
1602 wxDataViewColumn *ret = new wxDataViewColumn( label,
1603 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1604 GetStore()->GetColumnCount()-1, width, align, flags );
1605
1606 wxDataViewCtrl::AppendColumn( ret );
1607
1608 return ret;
1609 }
1610
1611 wxDataViewColumn *wxDataViewListCtrl::AppendProgressColumn( const wxString &label,
1612 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1613 {
1614 GetStore()->AppendColumn( wxT("long") );
1615
1616 wxDataViewColumn *ret = new wxDataViewColumn( label,
1617 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1618 GetStore()->GetColumnCount()-1, width, align, flags );
1619
1620 wxDataViewCtrl::AppendColumn( ret );
1621
1622 return ret;
1623 }
1624
1625 wxDataViewColumn *wxDataViewListCtrl::AppendIconTextColumn( const wxString &label,
1626 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1627 {
1628 GetStore()->AppendColumn( wxT("wxDataViewIconText") );
1629
1630 wxDataViewColumn *ret = new wxDataViewColumn( label,
1631 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1632 GetStore()->GetColumnCount()-1, width, align, flags );
1633
1634 wxDataViewCtrl::AppendColumn( ret );
1635
1636 return ret;
1637 }
1638
1639 void wxDataViewListCtrl::OnSize( wxSizeEvent &event )
1640 {
1641 event.Skip( true );
1642 }
1643
1644 //-----------------------------------------------------------------------------
1645 // wxDataViewTreeStore
1646 //-----------------------------------------------------------------------------
1647
1648 wxDataViewTreeStoreNode::wxDataViewTreeStoreNode(
1649 wxDataViewTreeStoreNode *parent,
1650 const wxString &text, const wxIcon &icon, wxClientData *data )
1651 {
1652 m_parent = parent;
1653 m_text = text;
1654 m_icon = icon;
1655 m_data = data;
1656 }
1657
1658 wxDataViewTreeStoreNode::~wxDataViewTreeStoreNode()
1659 {
1660 if (m_data)
1661 delete m_data;
1662 }
1663
1664 #include "wx/listimpl.cpp"
1665 WX_DEFINE_LIST(wxDataViewTreeStoreNodeList)
1666
1667 wxDataViewTreeStoreContainerNode::wxDataViewTreeStoreContainerNode(
1668 wxDataViewTreeStoreNode *parent, const wxString &text,
1669 const wxIcon &icon, const wxIcon &expanded, wxClientData *data ) :
1670 wxDataViewTreeStoreNode( parent, text, icon, data )
1671 {
1672 m_iconExpanded = expanded;
1673 m_isExpanded = false;
1674 m_children.DeleteContents(true);
1675 }
1676
1677 wxDataViewTreeStoreContainerNode::~wxDataViewTreeStoreContainerNode()
1678 {
1679 }
1680
1681 //-----------------------------------------------------------------------------
1682
1683 wxDataViewTreeStore::wxDataViewTreeStore()
1684 {
1685 m_root = new wxDataViewTreeStoreContainerNode( NULL, wxEmptyString );
1686 }
1687
1688 wxDataViewTreeStore::~wxDataViewTreeStore()
1689 {
1690 delete m_root;
1691 }
1692
1693 wxDataViewItem wxDataViewTreeStore::AppendItem( const wxDataViewItem& parent,
1694 const wxString &text, const wxIcon &icon, wxClientData *data )
1695 {
1696 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1697 if (!parent_node) return wxDataViewItem(0);
1698
1699 wxDataViewTreeStoreNode *node =
1700 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
1701 parent_node->GetChildren().Append( node );
1702
1703 return node->GetItem();
1704 }
1705
1706 wxDataViewItem wxDataViewTreeStore::PrependItem( const wxDataViewItem& parent,
1707 const wxString &text, const wxIcon &icon, wxClientData *data )
1708 {
1709 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1710 if (!parent_node) return wxDataViewItem(0);
1711
1712 wxDataViewTreeStoreNode *node =
1713 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
1714 parent_node->GetChildren().Insert( node );
1715
1716 return node->GetItem();
1717 }
1718
1719 wxDataViewItem
1720 wxDataViewTreeStore::InsertItem(const wxDataViewItem& parent,
1721 const wxDataViewItem& previous,
1722 const wxString& text,
1723 const wxIcon& icon,
1724 wxClientData *data)
1725 {
1726 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1727 if (!parent_node) return wxDataViewItem(0);
1728
1729 wxDataViewTreeStoreNode *previous_node = FindNode( previous );
1730 int pos = parent_node->GetChildren().IndexOf( previous_node );
1731 if (pos == wxNOT_FOUND) return wxDataViewItem(0);
1732
1733 wxDataViewTreeStoreNode *node =
1734 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
1735 parent_node->GetChildren().Insert( (size_t) pos, node );
1736
1737 return node->GetItem();
1738 }
1739
1740 wxDataViewItem wxDataViewTreeStore::PrependContainer( const wxDataViewItem& parent,
1741 const wxString &text, const wxIcon &icon, const wxIcon &expanded,
1742 wxClientData *data )
1743 {
1744 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1745 if (!parent_node) return wxDataViewItem(0);
1746
1747 wxDataViewTreeStoreContainerNode *node =
1748 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
1749 parent_node->GetChildren().Insert( node );
1750
1751 return node->GetItem();
1752 }
1753
1754 wxDataViewItem
1755 wxDataViewTreeStore::AppendContainer(const wxDataViewItem& parent,
1756 const wxString &text,
1757 const wxIcon& icon,
1758 const wxIcon& expanded,
1759 wxClientData * data)
1760 {
1761 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1762 if (!parent_node) return wxDataViewItem(0);
1763
1764 wxDataViewTreeStoreContainerNode *node =
1765 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
1766 parent_node->GetChildren().Append( node );
1767
1768 return node->GetItem();
1769 }
1770
1771 wxDataViewItem
1772 wxDataViewTreeStore::InsertContainer(const wxDataViewItem& parent,
1773 const wxDataViewItem& previous,
1774 const wxString& text,
1775 const wxIcon& icon,
1776 const wxIcon& expanded,
1777 wxClientData * data)
1778 {
1779 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1780 if (!parent_node) return wxDataViewItem(0);
1781
1782 wxDataViewTreeStoreNode *previous_node = FindNode( previous );
1783 int pos = parent_node->GetChildren().IndexOf( previous_node );
1784 if (pos == wxNOT_FOUND) return wxDataViewItem(0);
1785
1786 wxDataViewTreeStoreContainerNode *node =
1787 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
1788 parent_node->GetChildren().Insert( (size_t) pos, node );
1789
1790 return node->GetItem();
1791 }
1792
1793 bool wxDataViewTreeStore::IsContainer( const wxDataViewItem& item ) const
1794 {
1795 wxDataViewTreeStoreNode *node = FindNode( item );
1796 if (!node) return false;
1797
1798 return node->IsContainer();
1799 }
1800
1801 wxDataViewItem wxDataViewTreeStore::GetNthChild( const wxDataViewItem& parent, unsigned int pos ) const
1802 {
1803 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1804 if (!parent_node) return wxDataViewItem(0);
1805
1806 wxDataViewTreeStoreNodeList::compatibility_iterator node = parent_node->GetChildren().Item( pos );
1807 if (node)
1808 return node->GetData();
1809
1810 return wxDataViewItem(0);
1811 }
1812
1813 int wxDataViewTreeStore::GetChildCount( const wxDataViewItem& parent ) const
1814 {
1815 wxDataViewTreeStoreNode *node = FindNode( parent );
1816 if (!node) return -1;
1817
1818 if (!node->IsContainer())
1819 return 0;
1820
1821 wxDataViewTreeStoreContainerNode *container_node = (wxDataViewTreeStoreContainerNode*) node;
1822 return (int) container_node->GetChildren().GetCount();
1823 }
1824
1825 void wxDataViewTreeStore::SetItemText( const wxDataViewItem& item, const wxString &text )
1826 {
1827 wxDataViewTreeStoreNode *node = FindNode( item );
1828 if (!node) return;
1829
1830 node->SetText( text );
1831 }
1832
1833 wxString wxDataViewTreeStore::GetItemText( const wxDataViewItem& item ) const
1834 {
1835 wxDataViewTreeStoreNode *node = FindNode( item );
1836 if (!node) return wxEmptyString;
1837
1838 return node->GetText();
1839 }
1840
1841 void wxDataViewTreeStore::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
1842 {
1843 wxDataViewTreeStoreNode *node = FindNode( item );
1844 if (!node) return;
1845
1846 node->SetIcon( icon );
1847 }
1848
1849 const wxIcon &wxDataViewTreeStore::GetItemIcon( const wxDataViewItem& item ) const
1850 {
1851 wxDataViewTreeStoreNode *node = FindNode( item );
1852 if (!node) return wxNullIcon;
1853
1854 return node->GetIcon();
1855 }
1856
1857 void wxDataViewTreeStore::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
1858 {
1859 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1860 if (!node) return;
1861
1862 node->SetExpandedIcon( icon );
1863 }
1864
1865 const wxIcon &wxDataViewTreeStore::GetItemExpandedIcon( const wxDataViewItem& item ) const
1866 {
1867 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1868 if (!node) return wxNullIcon;
1869
1870 return node->GetExpandedIcon();
1871 }
1872
1873 void wxDataViewTreeStore::SetItemData( const wxDataViewItem& item, wxClientData *data )
1874 {
1875 wxDataViewTreeStoreNode *node = FindNode( item );
1876 if (!node) return;
1877
1878 node->SetData( data );
1879 }
1880
1881 wxClientData *wxDataViewTreeStore::GetItemData( const wxDataViewItem& item ) const
1882 {
1883 wxDataViewTreeStoreNode *node = FindNode( item );
1884 if (!node) return NULL;
1885
1886 return node->GetData();
1887 }
1888
1889 void wxDataViewTreeStore::DeleteItem( const wxDataViewItem& item )
1890 {
1891 if (!item.IsOk()) return;
1892
1893 wxDataViewItem parent_item = GetParent( item );
1894
1895 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent_item );
1896 if (!parent_node) return;
1897
1898 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1899 if (!node) return;
1900
1901 parent_node->GetChildren().DeleteObject( node );
1902 }
1903
1904 void wxDataViewTreeStore::DeleteChildren( const wxDataViewItem& item )
1905 {
1906 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1907 if (!node) return;
1908
1909 node->GetChildren().clear();
1910 }
1911
1912 void wxDataViewTreeStore::DeleteAllItems()
1913 {
1914 DeleteChildren(m_root);
1915 }
1916
1917 void
1918 wxDataViewTreeStore::GetValue(wxVariant &variant,
1919 const wxDataViewItem &item,
1920 unsigned int WXUNUSED(col)) const
1921 {
1922 // if (col != 0) return;
1923
1924 wxDataViewTreeStoreNode *node = FindNode( item );
1925 if (!node) return;
1926
1927 wxIcon icon( node->GetIcon());
1928 if (node->IsContainer())
1929 {
1930 wxDataViewTreeStoreContainerNode *container = (wxDataViewTreeStoreContainerNode*) node;
1931 if (container->IsExpanded() && container->GetExpandedIcon().IsOk())
1932 icon = container->GetExpandedIcon();
1933 }
1934
1935 wxDataViewIconText data( node->GetText(), icon );
1936
1937 variant << data;
1938 }
1939
1940 bool
1941 wxDataViewTreeStore::SetValue(const wxVariant& variant,
1942 const wxDataViewItem& item,
1943 unsigned int WXUNUSED(col))
1944 {
1945 // if (col != 0) return false;
1946
1947 wxDataViewTreeStoreNode *node = FindNode( item );
1948 if (!node) return false;
1949
1950 wxDataViewIconText data;
1951
1952 data << variant;
1953
1954 node->SetText( data.GetText() );
1955 node->SetIcon( data.GetIcon() );
1956
1957 return true;
1958 }
1959
1960 wxDataViewItem wxDataViewTreeStore::GetParent( const wxDataViewItem &item ) const
1961 {
1962 wxDataViewTreeStoreNode *node = FindNode( item );
1963 if (!node) return wxDataViewItem(0);
1964
1965 wxDataViewTreeStoreNode *parent = node->GetParent();
1966 if (!parent) return wxDataViewItem(0);
1967
1968 if (parent == m_root)
1969 return wxDataViewItem(0);
1970
1971 return parent->GetItem();
1972 }
1973
1974 unsigned int wxDataViewTreeStore::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
1975 {
1976 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1977 if (!node) return 0;
1978
1979 wxDataViewTreeStoreNodeList::iterator iter;
1980 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
1981 {
1982 wxDataViewTreeStoreNode* child = *iter;
1983 children.Add( child->GetItem() );
1984 }
1985
1986 return node->GetChildren().GetCount();
1987 }
1988
1989 int wxDataViewTreeStore::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
1990 unsigned int WXUNUSED(column), bool WXUNUSED(ascending) ) const
1991 {
1992 wxDataViewTreeStoreNode *node1 = FindNode( item1 );
1993 wxDataViewTreeStoreNode *node2 = FindNode( item2 );
1994
1995 if (!node1 || !node2)
1996 return 0;
1997
1998 wxDataViewTreeStoreContainerNode* parent1 =
1999 (wxDataViewTreeStoreContainerNode*) node1->GetParent();
2000 wxDataViewTreeStoreContainerNode* parent2 =
2001 (wxDataViewTreeStoreContainerNode*) node2->GetParent();
2002
2003 if (parent1 != parent2)
2004 {
2005 wxLogError( wxT("Comparing items with different parent.") );
2006 return 0;
2007 }
2008
2009 if (node1->IsContainer() && !node2->IsContainer())
2010 return -1;
2011
2012 if (node2->IsContainer() && !node1->IsContainer())
2013 return 1;
2014
2015 return parent1->GetChildren().IndexOf( node1 ) - parent2->GetChildren().IndexOf( node2 );
2016 }
2017
2018 wxDataViewTreeStoreNode *wxDataViewTreeStore::FindNode( const wxDataViewItem &item ) const
2019 {
2020 if (!item.IsOk())
2021 return m_root;
2022
2023 return (wxDataViewTreeStoreNode*) item.GetID();
2024 }
2025
2026 wxDataViewTreeStoreContainerNode *wxDataViewTreeStore::FindContainerNode( const wxDataViewItem &item ) const
2027 {
2028 if (!item.IsOk())
2029 return (wxDataViewTreeStoreContainerNode*) m_root;
2030
2031 wxDataViewTreeStoreNode* node = (wxDataViewTreeStoreNode*) item.GetID();
2032
2033 if (!node->IsContainer())
2034 return NULL;
2035
2036 return (wxDataViewTreeStoreContainerNode*) node;
2037 }
2038
2039 //-----------------------------------------------------------------------------
2040 // wxDataViewTreeCtrl
2041 //-----------------------------------------------------------------------------
2042
2043 IMPLEMENT_DYNAMIC_CLASS(wxDataViewTreeCtrl,wxDataViewCtrl)
2044
2045 BEGIN_EVENT_TABLE(wxDataViewTreeCtrl,wxDataViewCtrl)
2046 EVT_DATAVIEW_ITEM_EXPANDED(-1, wxDataViewTreeCtrl::OnExpanded)
2047 EVT_DATAVIEW_ITEM_COLLAPSED(-1, wxDataViewTreeCtrl::OnCollapsed)
2048 EVT_SIZE( wxDataViewTreeCtrl::OnSize )
2049 END_EVENT_TABLE()
2050
2051 wxDataViewTreeCtrl::~wxDataViewTreeCtrl()
2052 {
2053 delete m_imageList;
2054 }
2055
2056 bool wxDataViewTreeCtrl::Create( wxWindow *parent, wxWindowID id,
2057 const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator )
2058 {
2059 if ( !wxDataViewCtrl::Create( parent, id, pos, size, style, validator ) )
2060 return false;
2061
2062 // create the standard model and a column in the tree
2063 wxDataViewTreeStore *store = new wxDataViewTreeStore;
2064 AssociateModel( store );
2065 store->DecRef();
2066
2067 AppendIconTextColumn
2068 (
2069 wxString(), // no label (header is not shown anyhow)
2070 0, // the only model column
2071 wxDATAVIEW_CELL_EDITABLE,
2072 -1, // default width
2073 wxALIGN_NOT, // and alignment
2074 0 // not resizeable
2075 );
2076
2077 return true;
2078 }
2079
2080 void wxDataViewTreeCtrl::SetImageList( wxImageList *imagelist )
2081 {
2082 delete m_imageList;
2083
2084 m_imageList = imagelist;
2085 }
2086
2087 wxDataViewItem wxDataViewTreeCtrl::AppendItem( const wxDataViewItem& parent,
2088 const wxString &text, int iconIndex, wxClientData *data )
2089 {
2090 wxIcon icon = wxNullIcon;
2091 if (m_imageList && (iconIndex != -1))
2092 icon = m_imageList->GetIcon( iconIndex );
2093
2094 wxDataViewItem res = GetStore()->AppendItem( parent, text, icon, data );
2095
2096 GetStore()->ItemAdded( parent, res );
2097
2098 return res;
2099 }
2100
2101 wxDataViewItem wxDataViewTreeCtrl::PrependItem( const wxDataViewItem& parent,
2102 const wxString &text, int iconIndex, wxClientData *data )
2103 {
2104 wxIcon icon = wxNullIcon;
2105 if (m_imageList && (iconIndex != -1))
2106 icon = m_imageList->GetIcon( iconIndex );
2107
2108 wxDataViewItem res = GetStore()->PrependItem( parent, text, icon, data );
2109
2110 GetStore()->ItemAdded( parent, res );
2111
2112 return res;
2113 }
2114
2115 wxDataViewItem wxDataViewTreeCtrl::InsertItem( const wxDataViewItem& parent, const wxDataViewItem& previous,
2116 const wxString &text, int iconIndex, wxClientData *data )
2117 {
2118 wxIcon icon = wxNullIcon;
2119 if (m_imageList && (iconIndex != -1))
2120 icon = m_imageList->GetIcon( iconIndex );
2121
2122 wxDataViewItem res = GetStore()->InsertItem( parent, previous, text, icon, data );
2123
2124 GetStore()->ItemAdded( parent, res );
2125
2126 return res;
2127 }
2128
2129 wxDataViewItem wxDataViewTreeCtrl::PrependContainer( const wxDataViewItem& parent,
2130 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2131 {
2132 wxIcon icon = wxNullIcon;
2133 if (m_imageList && (iconIndex != -1))
2134 icon = m_imageList->GetIcon( iconIndex );
2135
2136 wxIcon expanded = wxNullIcon;
2137 if (m_imageList && (expandedIndex != -1))
2138 expanded = m_imageList->GetIcon( expandedIndex );
2139
2140 wxDataViewItem res = GetStore()->PrependContainer( parent, text, icon, expanded, data );
2141
2142 GetStore()->ItemAdded( parent, res );
2143
2144 return res;
2145 }
2146
2147 wxDataViewItem wxDataViewTreeCtrl::AppendContainer( const wxDataViewItem& parent,
2148 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2149 {
2150 wxIcon icon = wxNullIcon;
2151 if (m_imageList && (iconIndex != -1))
2152 icon = m_imageList->GetIcon( iconIndex );
2153
2154 wxIcon expanded = wxNullIcon;
2155 if (m_imageList && (expandedIndex != -1))
2156 expanded = m_imageList->GetIcon( expandedIndex );
2157
2158 wxDataViewItem res = GetStore()->AppendContainer( parent, text, icon, expanded, data );
2159
2160 GetStore()->ItemAdded( parent, res );
2161
2162 return res;
2163 }
2164
2165 wxDataViewItem wxDataViewTreeCtrl::InsertContainer( const wxDataViewItem& parent, const wxDataViewItem& previous,
2166 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2167 {
2168 wxIcon icon = wxNullIcon;
2169 if (m_imageList && (iconIndex != -1))
2170 icon = m_imageList->GetIcon( iconIndex );
2171
2172 wxIcon expanded = wxNullIcon;
2173 if (m_imageList && (expandedIndex != -1))
2174 expanded = m_imageList->GetIcon( expandedIndex );
2175
2176 wxDataViewItem res = GetStore()->InsertContainer( parent, previous, text, icon, expanded, data );
2177
2178 GetStore()->ItemAdded( parent, res );
2179
2180 return res;
2181 }
2182
2183 void wxDataViewTreeCtrl::SetItemText( const wxDataViewItem& item, const wxString &text )
2184 {
2185 GetStore()->SetItemText(item,text);
2186
2187 // notify control
2188 GetStore()->ValueChanged( item, 0 );
2189 }
2190
2191 void wxDataViewTreeCtrl::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
2192 {
2193 GetStore()->SetItemIcon(item,icon);
2194
2195 // notify control
2196 GetStore()->ValueChanged( item, 0 );
2197 }
2198
2199 void wxDataViewTreeCtrl::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
2200 {
2201 GetStore()->SetItemExpandedIcon(item,icon);
2202
2203 // notify control
2204 GetStore()->ValueChanged( item, 0 );
2205 }
2206
2207 void wxDataViewTreeCtrl::DeleteItem( const wxDataViewItem& item )
2208 {
2209 wxDataViewItem parent_item = GetStore()->GetParent( item );
2210
2211 GetStore()->DeleteItem(item);
2212
2213 // notify control
2214 GetStore()->ItemDeleted( parent_item, item );
2215 }
2216
2217 void wxDataViewTreeCtrl::DeleteChildren( const wxDataViewItem& item )
2218 {
2219 wxDataViewTreeStoreContainerNode *node = GetStore()->FindContainerNode( item );
2220 if (!node) return;
2221
2222 wxDataViewItemArray array;
2223 wxDataViewTreeStoreNodeList::iterator iter;
2224 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
2225 {
2226 wxDataViewTreeStoreNode* child = *iter;
2227 array.Add( child->GetItem() );
2228 }
2229
2230 GetStore()->DeleteChildren( item );
2231
2232 // notify control
2233 GetStore()->ItemsDeleted( item, array );
2234 }
2235
2236 void wxDataViewTreeCtrl::DeleteAllItems()
2237 {
2238 GetStore()->DeleteAllItems();
2239
2240 GetStore()->Cleared();
2241 }
2242
2243 void wxDataViewTreeCtrl::OnExpanded( wxDataViewEvent &event )
2244 {
2245 if (m_imageList) return;
2246
2247 wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
2248 if (!container) return;
2249
2250 container->SetExpanded( true );
2251
2252 GetStore()->ItemChanged( event.GetItem() );
2253 }
2254
2255 void wxDataViewTreeCtrl::OnCollapsed( wxDataViewEvent &event )
2256 {
2257 if (m_imageList) return;
2258
2259 wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
2260 if (!container) return;
2261
2262 container->SetExpanded( false );
2263
2264 GetStore()->ItemChanged( event.GetItem() );
2265 }
2266
2267 void wxDataViewTreeCtrl::OnSize( wxSizeEvent &event )
2268 {
2269 #if defined(wxUSE_GENERICDATAVIEWCTRL)
2270 // automatically resize our only column to take the entire control width
2271 if ( GetColumnCount() )
2272 {
2273 wxSize size = GetClientSize();
2274 GetColumn(0)->SetWidth(size.x);
2275 }
2276 #endif
2277 event.Skip( true );
2278 }
2279
2280 #endif // wxUSE_DATAVIEWCTRL
2281