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