]> git.saurik.com Git - wxWidgets.git/blob - src/common/datavcmn.cpp
Add wxDataViewTreeStore with sample
[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/log.h"
24 #include "wx/icon.h"
25 #endif
26
27 const wxChar wxDataViewCtrlNameStr[] = wxT("dataviewCtrl");
28
29
30 bool operator == (const wxDataViewItem &left, const wxDataViewItem &right)
31 {
32 return (left.GetID() == right.GetID() );
33 }
34
35
36 // ---------------------------------------------------------
37 // wxDataViewModelNotifier
38 // ---------------------------------------------------------
39
40 #include "wx/listimpl.cpp"
41 WX_DEFINE_LIST(wxDataViewModelNotifiers);
42
43 bool wxDataViewModelNotifier::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
44 {
45 size_t count = items.GetCount();
46 size_t i;
47 for (i = 0; i < count; i++)
48 if (!ItemAdded( parent, items[i] )) return false;
49
50 return true;
51 }
52
53 bool wxDataViewModelNotifier::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
54 {
55 size_t count = items.GetCount();
56 size_t i;
57 for (i = 0; i < count; i++)
58 if (!ItemDeleted( parent, items[i] )) return false;
59
60 return true;
61 }
62
63 bool wxDataViewModelNotifier::ItemsChanged( const wxDataViewItemArray &items )
64 {
65 size_t count = items.GetCount();
66 size_t i;
67 for (i = 0; i < count; i++)
68 if (!ItemChanged( items[i] )) return false;
69
70 return true;
71 }
72
73 // ---------------------------------------------------------
74 // wxDataViewModel
75 // ---------------------------------------------------------
76
77 wxDataViewModel::wxDataViewModel()
78 {
79 m_notifiers.DeleteContents( true );
80 }
81
82 bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
83 {
84 bool ret = true;
85
86 wxDataViewModelNotifiers::iterator iter;
87 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
88 {
89 wxDataViewModelNotifier* notifier = *iter;
90 if (!notifier->ItemAdded( parent, item ))
91 ret = false;
92 }
93
94 return ret;
95 }
96
97 bool wxDataViewModel::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
98 {
99 bool ret = true;
100
101 wxDataViewModelNotifiers::iterator iter;
102 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
103 {
104 wxDataViewModelNotifier* notifier = *iter;
105 if (!notifier->ItemDeleted( parent, item ))
106 ret = false;
107 }
108
109 return ret;
110 }
111
112 bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
113 {
114 bool ret = true;
115
116 wxDataViewModelNotifiers::iterator iter;
117 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
118 {
119 wxDataViewModelNotifier* notifier = *iter;
120 if (!notifier->ItemChanged( item ))
121 ret = false;
122 }
123
124 return ret;
125 }
126
127 bool wxDataViewModel::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
128 {
129 bool ret = true;
130
131 wxDataViewModelNotifiers::iterator iter;
132 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
133 {
134 wxDataViewModelNotifier* notifier = *iter;
135 if (!notifier->ItemsAdded( parent, items ))
136 ret = false;
137 }
138
139 return ret;
140 }
141
142 bool wxDataViewModel::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
143 {
144 bool ret = true;
145
146 wxDataViewModelNotifiers::iterator iter;
147 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
148 {
149 wxDataViewModelNotifier* notifier = *iter;
150 if (!notifier->ItemsDeleted( parent, items ))
151 ret = false;
152 }
153
154 return ret;
155 }
156
157 bool wxDataViewModel::ItemsChanged( const wxDataViewItemArray &items )
158 {
159 bool ret = true;
160
161 wxDataViewModelNotifiers::iterator iter;
162 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
163 {
164 wxDataViewModelNotifier* notifier = *iter;
165 if (!notifier->ItemsChanged( items ))
166 ret = false;
167 }
168
169 return ret;
170 }
171
172 bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
173 {
174 bool ret = true;
175
176 wxDataViewModelNotifiers::iterator iter;
177 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
178 {
179 wxDataViewModelNotifier* notifier = *iter;
180 if (!notifier->ValueChanged( item, col ))
181 ret = false;
182 }
183
184 return ret;
185 }
186
187 bool wxDataViewModel::Cleared()
188 {
189 bool ret = true;
190
191 wxDataViewModelNotifiers::iterator iter;
192 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
193 {
194 wxDataViewModelNotifier* notifier = *iter;
195 if (!notifier->Cleared())
196 ret = false;
197 }
198
199 return ret;
200 }
201
202 void wxDataViewModel::Resort()
203 {
204 wxDataViewModelNotifiers::iterator iter;
205 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
206 {
207 wxDataViewModelNotifier* notifier = *iter;
208 notifier->Resort();
209 }
210 }
211
212 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
213 {
214 m_notifiers.push_back( notifier );
215 notifier->SetOwner( this );
216 }
217
218 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
219 {
220 m_notifiers.DeleteObject( notifier );
221 }
222
223 int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
224 unsigned int column, bool ascending )
225 {
226 // sort branches before leaves
227 bool item1_is_container = IsContainer(item1);
228 bool item2_is_container = IsContainer(item2);
229
230 if (item1_is_container && !item2_is_container)
231 return 1;
232 if (item2_is_container && !item1_is_container)
233 return -1;
234
235 wxVariant value1,value2;
236 GetValue( value1, item1, column );
237 GetValue( value2, item2, column );
238
239 if (!ascending)
240 {
241 wxVariant temp = value1;
242 value1 = value2;
243 value2 = temp;
244 }
245
246 if (value1.GetType() == wxT("string"))
247 {
248 wxString str1 = value1.GetString();
249 wxString str2 = value2.GetString();
250 int res = str1.Cmp( str2 );
251 if (res) return res;
252 } else
253 if (value1.GetType() == wxT("long"))
254 {
255 long l1 = value1.GetLong();
256 long l2 = value2.GetLong();
257 long res = l1-l2;
258 if (res) return res;
259 } else
260 if (value1.GetType() == wxT("double"))
261 {
262 double d1 = value1.GetDouble();
263 double d2 = value2.GetDouble();
264 if (d1 < d2) return 1;
265 if (d1 > d2) return -1;
266 } else
267 if (value1.GetType() == wxT("datetime"))
268 {
269 wxDateTime dt1 = value1.GetDateTime();
270 wxDateTime dt2 = value2.GetDateTime();
271 if (dt1.IsEarlierThan(dt2)) return 1;
272 if (dt2.IsEarlierThan(dt1)) return -11;
273 }
274
275 // items must be different
276 unsigned long litem1 = (unsigned long) item1.GetID();
277 unsigned long litem2 = (unsigned long) item2.GetID();
278
279 if (!ascending)
280 return litem2-litem2;
281
282 return litem1-litem2;
283 }
284
285 // ---------------------------------------------------------
286 // wxDataViewIndexListModel
287 // ---------------------------------------------------------
288
289 wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size )
290 {
291 // build initial index
292 unsigned int i;
293 for (i = 1; i < initial_size+1; i++)
294 m_hash.Add( (void*) i );
295 m_lastIndex = initial_size + 1;
296 }
297
298 wxDataViewIndexListModel::~wxDataViewIndexListModel()
299 {
300 }
301
302 void wxDataViewIndexListModel::RowPrepended()
303 {
304 unsigned int id = m_lastIndex++;
305 m_hash.Insert( (void*) id, 0 );
306 wxDataViewItem item( (void*) id );
307 ItemAdded( wxDataViewItem(0), item );
308 }
309
310 void wxDataViewIndexListModel::RowInserted( unsigned int before )
311 {
312 unsigned int id = m_lastIndex++;
313 m_hash.Insert( (void*) id, before );
314 wxDataViewItem item( (void*) id );
315 ItemAdded( wxDataViewItem(0), item );
316 }
317
318 void wxDataViewIndexListModel::RowAppended()
319 {
320 unsigned int id = m_lastIndex++;
321 m_hash.Add( (void*) id );
322 wxDataViewItem item( (void*) id );
323 ItemAdded( wxDataViewItem(0), item );
324 }
325
326 void wxDataViewIndexListModel::RowDeleted( unsigned int row )
327 {
328 wxDataViewItem item( m_hash[row] );
329 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item );
330 m_hash.RemoveAt( row );
331 }
332
333 void wxDataViewIndexListModel::RowChanged( unsigned int row )
334 {
335 wxDataViewModel::ItemChanged( GetItem(row) );
336 }
337
338 void wxDataViewIndexListModel::RowValueChanged( unsigned int row, unsigned int col )
339 {
340 wxDataViewModel::ValueChanged( GetItem(row), col );
341 }
342
343 unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem &item ) const
344 {
345 // assert for not found
346 return (unsigned int) m_hash.Index( item.GetID() );
347 }
348
349 wxDataViewItem wxDataViewIndexListModel::GetItem( unsigned int row ) const
350 {
351 wxASSERT( row < m_hash.GetCount() );
352 return wxDataViewItem( m_hash[row] );
353 }
354
355 int wxDataViewIndexListModel::Compare(const wxDataViewItem& item1,
356 const wxDataViewItem& item2,
357 unsigned int WXUNUSED(column),
358 bool ascending)
359 {
360 if (ascending)
361 return GetRow(item1) - GetRow(item2);
362
363 return GetRow(item2) - GetRow(item1);
364 }
365
366 void wxDataViewIndexListModel::GetValue( wxVariant &variant,
367 const wxDataViewItem &item, unsigned int col ) const
368 {
369 GetValue( variant, GetRow(item), col );
370 }
371
372 bool wxDataViewIndexListModel::SetValue( const wxVariant &variant,
373 const wxDataViewItem &item, unsigned int col )
374 {
375 return SetValue( variant, GetRow(item), col );
376 }
377
378 wxDataViewItem wxDataViewIndexListModel::GetParent( const wxDataViewItem & WXUNUSED(item) ) const
379 {
380 return wxDataViewItem(0);
381 }
382
383 bool wxDataViewIndexListModel::IsContainer( const wxDataViewItem &item ) const
384 {
385 // only the invisible root item has children
386 if (!item.IsOk())
387 return true;
388
389 return false;
390 }
391
392 unsigned int wxDataViewIndexListModel::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
393 {
394 if (item.IsOk())
395 return 0;
396
397 children = m_hash;
398
399 return m_hash.GetCount();
400 }
401
402 //-----------------------------------------------------------------------------
403 // wxDataViewIconText
404 //-----------------------------------------------------------------------------
405
406 IMPLEMENT_DYNAMIC_CLASS(wxDataViewIconText,wxObject)
407
408 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxDataViewIconText, WXDLLIMPEXP_ADV)
409
410 bool operator == (const wxDataViewIconText &one, const wxDataViewIconText &two)
411 {
412 if (one.GetText() != two.GetText()) return false;
413 if (one.IsSameAs(two)) return false;
414 return true;
415 }
416
417 // ---------------------------------------------------------
418 // wxDataViewRendererBase
419 // ---------------------------------------------------------
420
421 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
422
423 wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
424 wxDataViewCellMode WXUNUSED(mode),
425 int WXUNUSED(align) )
426 {
427 m_variantType = varianttype;
428 m_editorCtrl = NULL;
429 }
430
431 const wxDataViewCtrl* wxDataViewRendererBase::GetView() const
432 {
433 return wx_const_cast(wxDataViewRendererBase*, this)->GetOwner()->GetOwner();
434 }
435
436 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
437 {
438 m_item = item; // remember for later
439
440 unsigned int col = GetOwner()->GetModelColumn();
441 wxVariant value;
442 GetOwner()->GetOwner()->GetModel()->GetValue( value, item, col );
443
444 m_editorCtrl = CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect, value );
445
446 wxDataViewEditorCtrlEvtHandler *handler =
447 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
448
449 m_editorCtrl->PushEventHandler( handler );
450
451 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
452 handler->SetFocusOnIdle();
453 #else
454 m_editorCtrl->SetFocus();
455 #endif
456
457 // Now we should send Editing Started event
458 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, GetOwner()->GetOwner()->GetId() );
459 event.SetDataViewColumn( GetOwner() );
460 event.SetModel( GetOwner()->GetOwner()->GetModel() );
461 event.SetItem( item );
462 GetOwner()->GetOwner()->GetEventHandler()->ProcessEvent( event );
463
464 return true;
465 }
466
467 void wxDataViewRendererBase::CancelEditing()
468 {
469 wxPendingDelete.Append( m_editorCtrl );
470
471 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
472
473 // m_editorCtrl->PopEventHandler( true );
474 }
475
476 bool wxDataViewRendererBase::FinishEditing()
477 {
478 wxVariant value;
479 GetValueFromEditorCtrl( m_editorCtrl, value );
480
481 wxPendingDelete.Append( m_editorCtrl );
482
483 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
484
485 if (!Validate(value))
486 return false;
487
488 unsigned int col = GetOwner()->GetModelColumn();
489 GetOwner()->GetOwner()->GetModel()->SetValue( value, m_item, col );
490 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item, col );
491
492 // m_editorCtrl->PopEventHandler( true );
493
494 // Now we should send Editing Done event
495 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, GetOwner()->GetOwner()->GetId() );
496 event.SetDataViewColumn( GetOwner() );
497 event.SetModel( GetOwner()->GetOwner()->GetModel() );
498 event.SetItem( m_item );
499 GetOwner()->GetOwner()->GetEventHandler()->ProcessEvent( event );
500
501 return true;
502 }
503
504 //-----------------------------------------------------------------------------
505 // wxDataViewEditorCtrlEvtHandler
506 //-----------------------------------------------------------------------------
507
508 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
509 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
510 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
511 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
512 END_EVENT_TABLE()
513
514 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
515 wxControl *editorCtrl,
516 wxDataViewRenderer *owner )
517 {
518 m_owner = owner;
519 m_editorCtrl = editorCtrl;
520
521 m_finished = false;
522 }
523
524 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
525 {
526 if (m_focusOnIdle)
527 {
528 m_focusOnIdle = false;
529 if (wxWindow::FindFocus() != m_editorCtrl)
530 m_editorCtrl->SetFocus();
531 }
532
533 event.Skip();
534 }
535
536 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
537 {
538 switch ( event.m_keyCode )
539 {
540 case WXK_RETURN:
541 m_finished = true;
542 m_owner->FinishEditing();
543 break;
544
545 case WXK_ESCAPE:
546 m_finished = true;
547 m_owner->CancelEditing();
548 break;
549
550 default:
551 event.Skip();
552 }
553 }
554
555 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
556 {
557 if (!m_finished)
558 {
559 m_finished = true;
560 m_owner->FinishEditing();
561 }
562
563 event.Skip();
564 }
565
566 // ---------------------------------------------------------
567 // wxDataViewColumnBase
568 // ---------------------------------------------------------
569
570 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase, wxObject)
571
572 wxDataViewColumnBase::wxDataViewColumnBase(const wxString& WXUNUSED(title),
573 wxDataViewRenderer *renderer,
574 unsigned int model_column,
575 int WXUNUSED(width),
576 wxAlignment WXUNUSED(align),
577 int WXUNUSED(flags))
578 {
579 m_renderer = renderer;
580 m_model_column = model_column;
581 m_owner = NULL;
582 m_renderer->SetOwner( (wxDataViewColumn*) this );
583
584 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
585 // parameters inside the native control!
586 }
587
588 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap& bitmap,
589 wxDataViewRenderer *renderer,
590 unsigned int model_column,
591 int WXUNUSED(width),
592 wxAlignment WXUNUSED(align),
593 int WXUNUSED(flags) )
594 {
595 m_renderer = renderer;
596 m_model_column = model_column;
597 m_bitmap = bitmap;
598 m_owner = NULL;
599 m_renderer->SetOwner( (wxDataViewColumn*) this );
600 }
601
602 wxDataViewColumnBase::~wxDataViewColumnBase()
603 {
604 if (m_renderer)
605 delete m_renderer;
606 }
607
608 int wxDataViewColumnBase::GetFlags() const
609 {
610 int ret = 0;
611
612 if (IsSortable())
613 ret |= wxDATAVIEW_COL_SORTABLE;
614 if (IsResizeable())
615 ret |= wxDATAVIEW_COL_RESIZABLE;
616 if (IsHidden())
617 ret |= wxDATAVIEW_COL_HIDDEN;
618
619 return ret;
620 }
621
622 void wxDataViewColumnBase::SetFlags(int flags)
623 {
624 SetSortable((flags & wxDATAVIEW_COL_SORTABLE) != 0);
625 SetResizeable((flags & wxDATAVIEW_COL_RESIZABLE) != 0);
626 SetHidden((flags & wxDATAVIEW_COL_HIDDEN) != 0);
627 }
628
629 // ---------------------------------------------------------
630 // wxDataViewCtrlBase
631 // ---------------------------------------------------------
632
633 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
634
635 wxDataViewCtrlBase::wxDataViewCtrlBase()
636 {
637 m_model = NULL;
638 m_expander_column = 0;
639 m_indent = 8;
640 }
641
642 wxDataViewCtrlBase::~wxDataViewCtrlBase()
643 {
644 if (m_model)
645 {
646 m_model->DecRef();
647 m_model = NULL;
648 }
649 }
650
651 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
652 {
653 if (m_model)
654 {
655 m_model->DecRef(); // discard old model, if any
656 }
657
658 // add our own reference to the new model:
659 m_model = model;
660 if (m_model)
661 {
662 m_model->IncRef();
663 }
664
665 return true;
666 }
667
668 wxDataViewModel* wxDataViewCtrlBase::GetModel()
669 {
670 return m_model;
671 }
672
673 wxDataViewColumn *
674 wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
675 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
676 {
677 wxDataViewColumn *ret = new wxDataViewColumn( label,
678 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
679 model_column, width, align, flags );
680 AppendColumn( ret );
681 return ret;
682 }
683
684 wxDataViewColumn *
685 wxDataViewCtrlBase::AppendIconTextColumn( const wxString &label, unsigned int model_column,
686 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
687 {
688 wxDataViewColumn *ret = new wxDataViewColumn( label,
689 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode, (int)align ),
690 model_column, width, align, flags );
691 AppendColumn( ret );
692 return ret;
693 }
694
695 wxDataViewColumn *
696 wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
697 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
698 {
699
700 wxDataViewColumn *ret = new wxDataViewColumn( label,
701 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
702 model_column, width, align, flags );
703 AppendColumn( ret );
704 return ret;
705 }
706
707 wxDataViewColumn *
708 wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
709 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
710 {
711 wxDataViewColumn *ret = new wxDataViewColumn( label,
712 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
713 model_column, width, align, flags );
714 AppendColumn( ret );
715 return ret;
716 }
717
718 wxDataViewColumn *
719 wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
720 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
721 {
722 wxDataViewColumn *ret = new wxDataViewColumn( label,
723 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
724 model_column, width, align, flags );
725 AppendColumn( ret );
726 return ret;
727 }
728
729 wxDataViewColumn *
730 wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
731 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
732 {
733 wxDataViewColumn *ret = new wxDataViewColumn( label,
734 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
735 model_column, width, align, flags );
736 AppendColumn( ret );
737 return ret;
738 }
739
740 wxDataViewColumn *
741 wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
742 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
743 {
744 wxDataViewColumn *ret = new wxDataViewColumn( label,
745 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
746 model_column, width, align, flags );
747 AppendColumn( ret );
748 return ret;
749 }
750
751 wxDataViewColumn *
752 wxDataViewCtrlBase::AppendIconTextColumn( const wxBitmap &label, unsigned int model_column,
753 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
754 {
755 wxDataViewColumn *ret = new wxDataViewColumn( label,
756 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode, (int)align ),
757 model_column, width, align, flags );
758 AppendColumn( ret );
759 return ret;
760 }
761
762 wxDataViewColumn *
763 wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
764 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
765 {
766 wxDataViewColumn *ret = new wxDataViewColumn( label,
767 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
768 model_column, width, align, flags );
769 AppendColumn( ret );
770 return ret;
771 }
772
773 wxDataViewColumn *
774 wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
775 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
776 {
777 wxDataViewColumn *ret = new wxDataViewColumn( label,
778 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
779 model_column, width, align, flags );
780 AppendColumn( ret );
781 return ret;
782 }
783
784 wxDataViewColumn *
785 wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
786 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
787 {
788 wxDataViewColumn *ret = new wxDataViewColumn( label,
789 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
790 model_column, width, align, flags );
791 AppendColumn( ret );
792 return ret;
793 }
794
795 wxDataViewColumn *
796 wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
797 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
798 {
799 wxDataViewColumn *ret = new wxDataViewColumn( label,
800 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
801 model_column, width, align, flags );
802 AppendColumn( ret );
803 return ret;
804 }
805
806 bool
807 wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
808 {
809 col->SetOwner( (wxDataViewCtrl*) this );
810 return true;
811 }
812
813 // ---------------------------------------------------------
814 // wxDataViewEvent
815 // ---------------------------------------------------------
816
817 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
818
819 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED)
820
821 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED)
822 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING)
823 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED)
824 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING)
825 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED)
826 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED)
827 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE)
828 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED)
829
830 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK)
831 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK)
832 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED)
833
834 //-----------------------------------------------------------------------------
835 // wxDataViewTreeStore
836 //-----------------------------------------------------------------------------
837
838 wxDataViewTreeStoreNode::wxDataViewTreeStoreNode(
839 wxDataViewTreeStoreNode *parent,
840 const wxString &text, const wxIcon &icon, wxClientData *data )
841 {
842 m_parent = parent;
843 m_text = text;
844 m_icon = icon;
845 m_data = data;
846 }
847
848 wxDataViewTreeStoreNode::~wxDataViewTreeStoreNode()
849 {
850 if (m_data)
851 delete m_data;
852 }
853
854 #include "wx/listimpl.cpp"
855 WX_DEFINE_LIST(wxDataViewTreeStoreNodeList);
856
857 wxDataViewTreeStoreContainerNode::wxDataViewTreeStoreContainerNode(
858 wxDataViewTreeStoreNode *parent, const wxString &text,
859 const wxIcon &icon, const wxIcon &expanded, wxClientData *data ) :
860 wxDataViewTreeStoreNode( parent, text, icon, data )
861 {
862 m_iconExpanded = expanded;
863 m_children.DeleteContents(true);
864 }
865
866 wxDataViewTreeStoreContainerNode::~wxDataViewTreeStoreContainerNode()
867 {
868 }
869
870 //-----------------------------------------------------------------------------
871
872 wxDataViewTreeStore::wxDataViewTreeStore()
873 {
874 m_root = new wxDataViewTreeStoreContainerNode( NULL, wxEmptyString );
875 }
876
877 wxDataViewTreeStore::~wxDataViewTreeStore()
878 {
879 delete m_root;
880 }
881
882 wxDataViewItem wxDataViewTreeStore::AppendItem( const wxDataViewItem& parent,
883 const wxString &text, const wxIcon &icon, wxClientData *data )
884 {
885 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
886 if (!parent_node) return wxDataViewItem(0);
887
888 wxDataViewTreeStoreNode *node =
889 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
890 parent_node->GetChildren().Append( node );
891
892 // notify control
893 ItemAdded( parent, node->GetItem() );
894
895 return node->GetItem();
896 }
897
898 wxDataViewItem wxDataViewTreeStore::PrependItem( const wxDataViewItem& parent,
899 const wxString &text, const wxIcon &icon, wxClientData *data )
900 {
901 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
902 if (!parent_node) return wxDataViewItem(0);
903
904 wxDataViewTreeStoreNode *node =
905 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
906 parent_node->GetChildren().Insert( node );
907
908 // notify control
909 ItemAdded( parent, node->GetItem() );
910
911 return node->GetItem();
912 }
913
914 wxDataViewItem wxDataViewTreeStore::InsertItem( const wxDataViewItem& parent, const wxDataViewItem& previous,
915 const wxString &text, const wxIcon &icon, wxClientData *data )
916 {
917 return wxDataViewItem(0);
918 }
919
920 wxDataViewItem wxDataViewTreeStore::PrependContainer( const wxDataViewItem& parent,
921 const wxString &text, const wxIcon &icon, const wxIcon &expanded,
922 wxClientData *data )
923 {
924 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
925 if (!parent_node) return wxDataViewItem(0);
926
927 wxDataViewTreeStoreContainerNode *node =
928 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
929 parent_node->GetChildren().Insert( node );
930
931 // notify control
932 ItemAdded( parent, node->GetItem() );
933
934 return node->GetItem();
935 }
936
937 wxDataViewItem wxDataViewTreeStore::AppendContainer( const wxDataViewItem& parent,
938 const wxString &text, const wxIcon &icon, const wxIcon &expanded,
939 wxClientData *data )
940 {
941 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
942 if (!parent_node) return wxDataViewItem(0);
943
944 wxDataViewTreeStoreContainerNode *node =
945 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
946 parent_node->GetChildren().Append( node );
947
948 // notify control
949 ItemAdded( parent, node->GetItem() );
950
951 return node->GetItem();
952 }
953
954 wxDataViewItem wxDataViewTreeStore::InsertContainer( const wxDataViewItem& parent, const wxDataViewItem& previous,
955 const wxString &text, const wxIcon &icon, const wxIcon &expanded,
956 wxClientData *data )
957 {
958 return wxDataViewItem(0);
959 }
960
961 wxDataViewItem wxDataViewTreeStore::GetNthChild( const wxDataViewItem& parent, unsigned int pos ) const
962 {
963 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
964 if (!parent_node) return wxDataViewItem(0);
965
966 wxDataViewTreeStoreNodeList::compatibility_iterator node = parent_node->GetChildren().Item( pos );
967 if (node)
968 return node->GetData();
969
970 return wxDataViewItem(0);
971 }
972
973 int wxDataViewTreeStore::GetChildCount( const wxDataViewItem& parent ) const
974 {
975 wxDataViewTreeStoreNode *node = FindNode( parent );
976 if (!node) return -1;
977
978 if (!node->IsContainer())
979 return 0;
980
981 wxDataViewTreeStoreContainerNode *container_node = (wxDataViewTreeStoreContainerNode*) node;
982 return (int) container_node->GetChildren().GetCount();
983 }
984
985 void wxDataViewTreeStore::SetItemText( const wxDataViewItem& item, const wxString &text )
986 {
987 wxDataViewTreeStoreNode *node = FindNode( item );
988 if (!node) return;
989
990 node->SetText( text );
991
992 // notify control
993 ValueChanged( item, 0 );
994 }
995
996 wxString wxDataViewTreeStore::GetItemText( const wxDataViewItem& item ) const
997 {
998 wxDataViewTreeStoreNode *node = FindNode( item );
999 if (!node) return wxEmptyString;
1000
1001 return node->GetText();
1002 }
1003
1004 void wxDataViewTreeStore::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
1005 {
1006 wxDataViewTreeStoreNode *node = FindNode( item );
1007 if (!node) return;
1008
1009 node->SetIcon( icon );
1010
1011 // notify control
1012 ValueChanged( item, 0 );
1013 }
1014
1015 const wxIcon &wxDataViewTreeStore::GetItemIcon( const wxDataViewItem& item ) const
1016 {
1017 wxDataViewTreeStoreNode *node = FindNode( item );
1018 if (!node) return wxNullIcon;
1019
1020 return node->GetIcon();
1021 }
1022
1023 void wxDataViewTreeStore::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
1024 {
1025 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1026 if (!node) return;
1027
1028 node->SetExpandedIcon( icon );
1029
1030 // notify control
1031 ValueChanged( item, 0 );
1032 }
1033
1034 const wxIcon &wxDataViewTreeStore::GetItemExpandedIcon( const wxDataViewItem& item ) const
1035 {
1036 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1037 if (!node) return wxNullIcon;
1038
1039 return node->GetExpandedIcon();
1040 }
1041
1042 void wxDataViewTreeStore::SetItemData( const wxDataViewItem& item, wxClientData *data )
1043 {
1044 wxDataViewTreeStoreNode *node = FindNode( item );
1045 if (!node) return;
1046
1047 node->SetData( data );
1048
1049 // notify control? only sensible when sorting on client data
1050 // ValueChanged( item, 0 );
1051 }
1052
1053 wxClientData *wxDataViewTreeStore::GetItemData( const wxDataViewItem& item ) const
1054 {
1055 wxDataViewTreeStoreNode *node = FindNode( item );
1056 if (!node) return NULL;
1057
1058 return node->GetData();
1059 }
1060
1061 void wxDataViewTreeStore::DeleteItem( const wxDataViewItem& item )
1062 {
1063 if (!item.IsOk()) return;
1064
1065 wxDataViewItem parent_item = GetParent( item );
1066
1067 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent_item );
1068 if (!parent_node) return;
1069
1070 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1071 if (!node) return;
1072
1073 parent_node->GetChildren().DeleteObject( node );
1074
1075 // notify control
1076 ItemDeleted( parent_item, item );
1077 }
1078
1079 void wxDataViewTreeStore::DeleteChildren( const wxDataViewItem& item )
1080 {
1081 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1082 if (!node) return;
1083
1084 wxDataViewItemArray array;
1085 wxDataViewTreeStoreNodeList::iterator iter;
1086 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
1087 {
1088 wxDataViewTreeStoreNode* child = *iter;
1089 array.Add( child->GetItem() );
1090 }
1091
1092 node->GetChildren().clear();
1093
1094 // notify control
1095 ItemsDeleted( item, array );
1096 }
1097
1098 void wxDataViewTreeStore::DeleteAllItems()
1099 {
1100 // TODO
1101 }
1102
1103 void wxDataViewTreeStore::GetValue( wxVariant &variant,
1104 const wxDataViewItem &item, unsigned int col ) const
1105 {
1106 // if (col != 0) return;
1107
1108 wxDataViewTreeStoreNode *node = FindNode( item );
1109 if (!node) return;
1110
1111 wxDataViewIconText data( node->GetText(), node->GetIcon() );
1112
1113 variant << data;
1114 }
1115
1116 bool wxDataViewTreeStore::SetValue( const wxVariant &variant,
1117 const wxDataViewItem &item, unsigned int col )
1118 {
1119 // if (col != 0) return false;
1120
1121 wxDataViewTreeStoreNode *node = FindNode( item );
1122 if (!node) return false;
1123
1124 wxDataViewIconText data;
1125
1126 data << variant;
1127
1128 node->SetText( data.GetText() );
1129 node->SetIcon( data.GetIcon() );
1130
1131 return true;
1132 }
1133
1134 wxDataViewItem wxDataViewTreeStore::GetParent( const wxDataViewItem &item ) const
1135 {
1136 wxDataViewTreeStoreNode *node = FindNode( item );
1137 if (!node) return wxDataViewItem(0);
1138
1139 wxDataViewTreeStoreNode *parent = node->GetParent();
1140 if (!parent) return wxDataViewItem(0);
1141
1142 if (parent == m_root)
1143 return wxDataViewItem(0);
1144
1145 return parent->GetItem();
1146 }
1147
1148 bool wxDataViewTreeStore::IsContainer( const wxDataViewItem &item ) const
1149 {
1150 wxDataViewTreeStoreNode *node = FindNode( item );
1151 if (!node) return false;
1152
1153 return node->IsContainer();
1154 }
1155
1156 unsigned int wxDataViewTreeStore::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
1157 {
1158 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
1159 if (!node) return 0;
1160
1161 wxDataViewTreeStoreNodeList::iterator iter;
1162 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
1163 {
1164 wxDataViewTreeStoreNode* child = *iter;
1165 children.Add( child->GetItem() );
1166 }
1167
1168 return node->GetChildren().GetCount();
1169 }
1170
1171 int wxDataViewTreeStore::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
1172 unsigned int WXUNUSED(column), bool WXUNUSED(ascending) )
1173 {
1174 wxDataViewTreeStoreNode *node1 = FindNode( item1 );
1175 wxDataViewTreeStoreNode *node2 = FindNode( item2 );
1176
1177 if (!node1 || !node2)
1178 return 0;
1179
1180 wxDataViewTreeStoreContainerNode* parent1 =
1181 (wxDataViewTreeStoreContainerNode*) node1->GetParent();
1182 wxDataViewTreeStoreContainerNode* parent2 =
1183 (wxDataViewTreeStoreContainerNode*) node2->GetParent();
1184
1185 if (parent1 != parent2)
1186 {
1187 wxLogError( wxT("Comparing items with different parent.") );
1188 return 0;
1189 }
1190
1191 if (node1->IsContainer() && !!node2->IsContainer())
1192 return 1;
1193
1194 if (node2->IsContainer() && !!node1->IsContainer())
1195 return -1;
1196
1197 return parent1->GetChildren().IndexOf( node1 ) - parent1->GetChildren().IndexOf( node2 );
1198 }
1199
1200 wxDataViewTreeStoreNode *wxDataViewTreeStore::FindNode( const wxDataViewItem &item ) const
1201 {
1202 if (!item.IsOk())
1203 return m_root;
1204
1205 return (wxDataViewTreeStoreNode*) item.GetID();
1206 }
1207
1208 wxDataViewTreeStoreContainerNode *wxDataViewTreeStore::FindContainerNode( const wxDataViewItem &item ) const
1209 {
1210 if (!item.IsOk())
1211 return (wxDataViewTreeStoreContainerNode*) m_root;
1212
1213 wxDataViewTreeStoreNode* node = (wxDataViewTreeStoreNode*) item.GetID();
1214
1215 if (!node->IsContainer())
1216 return NULL;
1217
1218 return (wxDataViewTreeStoreContainerNode*) node;
1219 }
1220
1221 #endif
1222