1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/datavcmn.cpp
3 // Purpose: wxDataViewCtrl base classes and common parts
4 // Author: Robert Roebling
7 // Copyright: (c) 2006, Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #if wxUSE_DATAVIEWCTRL
20 #include "wx/dataview.h"
26 const wxChar wxDataViewCtrlNameStr
[] = wxT("dataviewCtrl");
28 // ---------------------------------------------------------
30 // ---------------------------------------------------------
32 IMPLEMENT_ABSTRACT_CLASS(wxDataViewModel
, wxObject
)
34 // ---------------------------------------------------------
35 // wxDataViewListModel
36 // ---------------------------------------------------------
38 IMPLEMENT_ABSTRACT_CLASS(wxDataViewListModel
, wxDataViewModel
)
40 wxDataViewListModel::wxDataViewListModel()
42 m_viewingColumns
.DeleteContents( true );
43 m_notifiers
.DeleteContents( true );
46 wxDataViewListModel::~wxDataViewListModel()
50 bool wxDataViewListModel::RowAppended()
54 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
57 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
58 if (!notifier
->RowAppended())
60 node
= node
->GetNext();
66 bool wxDataViewListModel::RowPrepended()
70 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
73 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
74 if (!notifier
->RowPrepended())
76 node
= node
->GetNext();
82 bool wxDataViewListModel::RowInserted( unsigned int before
)
86 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
89 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
90 if (!notifier
->RowInserted(before
))
92 node
= node
->GetNext();
98 bool wxDataViewListModel::RowDeleted( unsigned int row
)
102 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
105 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
106 if (!notifier
->RowDeleted( row
))
108 node
= node
->GetNext();
114 bool wxDataViewListModel::RowChanged( unsigned int row
)
118 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
121 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
122 if (!notifier
->RowChanged( row
))
124 node
= node
->GetNext();
130 bool wxDataViewListModel::ValueChanged( unsigned int col
, unsigned int row
)
134 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
137 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
138 if (!notifier
->ValueChanged( col
, row
))
140 node
= node
->GetNext();
146 bool wxDataViewListModel::RowsReordered( unsigned int *new_order
)
150 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
153 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
154 if (!notifier
->RowsReordered( new_order
))
156 node
= node
->GetNext();
162 bool wxDataViewListModel::Cleared()
166 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
169 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
170 if (!notifier
->Cleared())
172 node
= node
->GetNext();
178 void wxDataViewListModel::AddViewingColumn( wxDataViewColumn
*view_column
, unsigned int model_column
)
180 m_viewingColumns
.Append( new wxDataViewViewingColumn( view_column
, model_column
) );
183 void wxDataViewListModel::RemoveViewingColumn( wxDataViewColumn
*column
)
185 wxList::compatibility_iterator node
= m_viewingColumns
.GetFirst();
188 wxDataViewViewingColumn
* tmp
= (wxDataViewViewingColumn
*) node
->GetData();
190 if (tmp
->m_viewColumn
== column
)
192 m_viewingColumns
.DeleteObject( tmp
);
196 node
= node
->GetNext();
200 void wxDataViewListModel::AddNotifier( wxDataViewListModelNotifier
*notifier
)
202 m_notifiers
.Append( notifier
);
203 notifier
->SetOwner( this );
206 void wxDataViewListModel::RemoveNotifier( wxDataViewListModelNotifier
*notifier
)
208 m_notifiers
.DeleteObject( notifier
);
211 // ---------------------------------------------------------
212 // wxDataViewSortedListModelNotifier
213 // ---------------------------------------------------------
215 class wxDataViewSortedListModelNotifier
: public wxDataViewListModelNotifier
218 wxDataViewSortedListModelNotifier( wxDataViewSortedListModel
*model
)
221 virtual bool RowAppended()
222 { return m_model
->ChildRowAppended(); }
224 virtual bool RowPrepended()
225 { return m_model
->ChildRowPrepended(); }
227 virtual bool RowInserted( unsigned int before
)
228 { return m_model
->ChildRowInserted( before
); }
230 virtual bool RowDeleted( unsigned int row
)
231 { return m_model
->ChildRowDeleted( row
); }
233 virtual bool RowChanged( unsigned int row
)
234 { return m_model
->ChildRowChanged( row
); }
236 virtual bool ValueChanged( unsigned int col
, unsigned int row
)
237 { return m_model
->ChildValueChanged( col
, row
); }
239 virtual bool RowsReordered( unsigned int *new_order
)
240 { return m_model
->ChildRowsReordered( new_order
); }
242 virtual bool Cleared()
243 { return m_model
->ChildCleared(); }
245 wxDataViewSortedListModel
*m_model
;
248 // ---------------------------------------------------------
249 // wxDataViewSortedListModel compare function
250 // ---------------------------------------------------------
252 int wxCALLBACK wxDataViewListModelSortedDefaultCompare
253 (unsigned int row1
, unsigned int row2
, unsigned int col
, wxDataViewListModel
* model
)
255 wxVariant value1
,value2
;
256 model
->GetValue( value1
, col
, row1
);
257 model
->GetValue( value2
, col
, row2
);
258 if (value1
.GetType() == wxT("string"))
260 wxString str1
= value1
.GetString();
261 wxString str2
= value2
.GetString();
262 return str1
.Cmp( str2
);
264 if (value1
.GetType() == wxT("long"))
266 long l1
= value1
.GetLong();
267 long l2
= value2
.GetLong();
270 if (value1
.GetType() == wxT("double"))
272 double d1
= value1
.GetDouble();
273 double d2
= value2
.GetDouble();
274 if (d1
== d2
) return 0;
275 if (d1
< d2
) return 1;
278 if (value1
.GetType() == wxT("datetime"))
280 wxDateTime dt1
= value1
.GetDateTime();
281 wxDateTime dt2
= value2
.GetDateTime();
282 if (dt1
.IsEqualTo(dt2
)) return 0;
283 if (dt1
.IsEarlierThan(dt2
)) return 1;
290 int wxCALLBACK wxDataViewListModelSortedDefaultCompareDescending
291 (unsigned int row1
, unsigned int row2
, unsigned int col
, wxDataViewListModel
* model
)
293 return wxDataViewListModelSortedDefaultCompare( row2
, row1
, col
, model
);
296 static wxDataViewListModelCompare s_CmpFunc
;
297 static wxDataViewListModel
*s_CmpModel
;
298 static unsigned int s_CmpCol
;
300 int LINKAGEMODE
wxDataViewIntermediateCmp( unsigned int row1
, unsigned int row2
)
302 return s_CmpFunc( row1
, row2
, s_CmpCol
, s_CmpModel
);
305 // ---------------------------------------------------------
306 // wxDataViewSortedListModel
307 // ---------------------------------------------------------
309 IMPLEMENT_ABSTRACT_CLASS(wxDataViewSortedListModel
, wxDataViewListModel
)
311 wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel
*child
) :
312 m_array( wxDataViewIntermediateCmp
)
318 m_notifierOnChild
= new wxDataViewSortedListModelNotifier( this );
319 m_child
->AddNotifier( m_notifierOnChild
);
324 wxDataViewSortedListModel::~wxDataViewSortedListModel()
326 m_child
->RemoveNotifier( m_notifierOnChild
);
330 void wxDataViewSortedListModel::InitStatics()
333 s_CmpModel
= m_child
;
335 s_CmpFunc
= wxDataViewListModelSortedDefaultCompare
;
337 s_CmpFunc
= wxDataViewListModelSortedDefaultCompareDescending
;
340 void wxDataViewSortedListModel::Resort()
345 unsigned int n
= m_child
->GetNumberOfRows();
347 for (i
= 0; i
< n
; i
++)
352 static void Dump( wxDataViewListModel
*model
, unsigned int col
)
354 unsigned int n
= model
->GetNumberOfRows();
356 for (i
= 0; i
< n
; i
++)
359 model
->GetValue( variant
, col
, i
);
361 tmp
= variant
.GetString();
362 wxPrintf( wxT("%d: %s\n"), (int) i
, tmp
.c_str() );
367 bool wxDataViewSortedListModel::ChildRowAppended()
369 // no need to fix up array
371 unsigned int len
= m_array
.GetCount();
373 unsigned int pos
= m_array
.Add( len
);
376 return wxDataViewListModel::RowPrepended();
379 return wxDataViewListModel::RowAppended();
381 return wxDataViewListModel::RowInserted( pos
);
384 bool wxDataViewSortedListModel::ChildRowPrepended()
388 unsigned int len
= m_array
.GetCount();
389 for (i
= 0; i
< len
; i
++)
391 unsigned int value
= m_array
[i
];
392 m_array
[i
] = value
+1;
395 unsigned int pos
= m_array
.Add( 0 );
398 return wxDataViewListModel::RowPrepended();
401 return wxDataViewListModel::RowAppended();
403 return wxDataViewListModel::RowInserted( pos
);
406 bool wxDataViewSortedListModel::ChildRowInserted( unsigned int before
)
410 unsigned int len
= m_array
.GetCount();
411 for (i
= 0; i
< len
; i
++)
413 unsigned int value
= m_array
[i
];
415 m_array
[i
] = value
+1;
418 unsigned int pos
= m_array
.Add( before
);
421 return wxDataViewListModel::RowPrepended();
424 return wxDataViewListModel::RowAppended();
426 return wxDataViewListModel::RowInserted( pos
);
429 bool wxDataViewSortedListModel::ChildRowDeleted( unsigned int row
)
432 unsigned int len
= m_array
.GetCount();
434 for (i
= 0; i
< len
; i
++)
436 unsigned int value
= m_array
[i
];
446 m_array
[i
] = value
-1;
451 return false; // we should probably assert
454 m_array
.RemoveAt( (unsigned int) pos
);
456 return wxDataViewListModel::RowDeleted( (unsigned int) pos
);
459 bool wxDataViewSortedListModel::ChildRowChanged( unsigned int row
)
462 unsigned int len
= m_array
.GetCount();
464 // Remove and readd sorted. Find out at which
465 // position it was and where it ended.
466 unsigned int start_pos
= 0,end_pos
= 0;
467 for (i
= 0; i
< len
; i
++)
468 if (m_array
[i
] == row
)
473 m_array
.RemoveAt( start_pos
);
476 for (i
= 0; i
< len
; i
++)
477 if (m_array
[i
] == row
)
483 if (end_pos
== start_pos
)
484 return wxDataViewListModel::RowChanged( start_pos
);
486 // Create an array where order[old] -> new_pos, so that
487 // if nothing changed order[0] -> 0 etc.
488 unsigned int *order
= new unsigned int[ len
];
489 // Fill up initial values.
490 for (i
= 0; i
< len
; i
++)
493 if (start_pos
< end_pos
)
495 for (i
= start_pos
; i
< end_pos
; i
++)
496 order
[i
] = order
[i
+1];
497 order
[end_pos
] = start_pos
;
501 for (i
= end_pos
; i
> start_pos
; i
--)
502 order
[i
] = order
[i
-1];
503 order
[start_pos
] = end_pos
;
506 wxDataViewListModel::RowsReordered( order
);
513 bool wxDataViewSortedListModel::ChildValueChanged( unsigned int col
, unsigned int row
)
516 unsigned int len
= m_array
.GetCount();
518 // Remove and readd sorted. Find out at which
519 // position it was and where it ended.
520 unsigned int start_pos
= 0,end_pos
= 0;
521 for (i
= 0; i
< len
; i
++)
522 if (m_array
[i
] == row
)
527 m_array
.RemoveAt( start_pos
);
530 for (i
= 0; i
< len
; i
++)
531 if (m_array
[i
] == row
)
537 if (end_pos
== start_pos
)
538 return wxDataViewListModel::ValueChanged( col
, start_pos
);
540 // Create an array where order[old] -> new_pos, so that
541 // if nothing changed order[0] -> 0 etc.
542 unsigned int *order
= new unsigned int[ len
];
543 // Fill up initial values.
544 for (i
= 0; i
< len
; i
++)
547 if (start_pos
< end_pos
)
549 for (i
= start_pos
; i
< end_pos
; i
++)
550 order
[i
] = order
[i
+1];
551 order
[end_pos
] = start_pos
;
555 for (i
= end_pos
; i
> start_pos
; i
--)
556 order
[i
] = order
[i
-1];
557 order
[start_pos
] = end_pos
;
560 wxDataViewListModel::RowsReordered( order
);
567 bool wxDataViewSortedListModel::ChildRowsReordered( unsigned int *WXUNUSED(new_order
) )
569 // Nothing needs to be done. If the sort criteria
570 // of this list don't change, the order of the
571 // items of the child list isn't relevant.
575 bool wxDataViewSortedListModel::ChildCleared()
577 return wxDataViewListModel::Cleared();
580 unsigned int wxDataViewSortedListModel::GetNumberOfRows()
582 return m_array
.GetCount();
585 unsigned int wxDataViewSortedListModel::GetNumberOfCols()
587 return m_child
->GetNumberOfCols();
590 wxString
wxDataViewSortedListModel::GetColType( unsigned int col
)
592 return m_child
->GetColType( col
);
595 void wxDataViewSortedListModel::GetValue( wxVariant
&variant
, unsigned int col
, unsigned int row
)
597 unsigned int child_row
= m_array
[row
];
598 m_child
->GetValue( variant
, col
, child_row
);
601 bool wxDataViewSortedListModel::SetValue( wxVariant
&variant
, unsigned int col
, unsigned int row
)
603 unsigned int child_row
= m_array
[row
];
604 bool ret
= m_child
->SetValue( variant
, col
, child_row
);
606 // Do nothing here as the change in the
607 // child model will be reported back.
612 bool wxDataViewSortedListModel::RowAppended()
614 // you can only append
615 bool ret
= m_child
->RowAppended();
617 // Do nothing here as the change in the
618 // child model will be reported back.
623 bool wxDataViewSortedListModel::RowPrepended()
625 // you can only append
626 bool ret
= m_child
->RowAppended();
628 // Do nothing here as the change in the
629 // child model will be reported back.
634 bool wxDataViewSortedListModel::RowInserted( unsigned int WXUNUSED(before
) )
636 // you can only append
637 bool ret
= m_child
->RowAppended();
639 // Do nothing here as the change in the
640 // child model will be reported back.
645 bool wxDataViewSortedListModel::RowDeleted( unsigned int row
)
647 unsigned int child_row
= m_array
[row
];
649 bool ret
= m_child
->RowDeleted( child_row
);
651 // Do nothing here as the change in the
652 // child model will be reported back.
657 bool wxDataViewSortedListModel::RowChanged( unsigned int row
)
659 unsigned int child_row
= m_array
[row
];
660 bool ret
= m_child
->RowChanged( child_row
);
662 // Do nothing here as the change in the
663 // child model will be reported back.
668 bool wxDataViewSortedListModel::ValueChanged( unsigned int col
, unsigned int row
)
670 unsigned int child_row
= m_array
[row
];
671 bool ret
= m_child
->ValueChanged( col
, child_row
);
673 // Do nothing here as the change in the
674 // child model will be reported back.
679 bool wxDataViewSortedListModel::RowsReordered( unsigned int *WXUNUSED(new_order
) )
681 // We sort them ourselves.
686 bool wxDataViewSortedListModel::Cleared()
688 bool ret
= m_child
->Cleared();
690 // Do nothing here as the change in the
691 // child model will be reported back.
696 // ---------------------------------------------------------
697 // wxDataViewRendererBase
698 // ---------------------------------------------------------
700 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
702 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
, wxDataViewCellMode mode
)
704 m_variantType
= varianttype
;
708 // ---------------------------------------------------------
709 // wxDataViewColumnBase
710 // ---------------------------------------------------------
712 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
714 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& title
,
715 wxDataViewRenderer
*renderer
,
716 unsigned int model_column
,
720 m_renderer
= renderer
;
721 m_model_column
= model_column
;
725 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
728 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
729 wxDataViewRenderer
*renderer
,
730 unsigned int model_column
,
734 m_renderer
= renderer
;
735 m_model_column
= model_column
;
739 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
742 wxDataViewColumnBase::~wxDataViewColumnBase()
749 GetOwner()->GetModel()->RemoveViewingColumn( (wxDataViewColumn
*) this );
753 void wxDataViewColumnBase::SetTitle( const wxString
&title
)
758 wxString
wxDataViewColumnBase::GetTitle()
763 void wxDataViewColumnBase::SetBitmap( const wxBitmap
&bitmap
)
768 const wxBitmap
&wxDataViewColumnBase::GetBitmap()
773 // ---------------------------------------------------------
774 // wxDataViewCtrlBase
775 // ---------------------------------------------------------
777 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
779 wxDataViewCtrlBase::wxDataViewCtrlBase()
782 m_cols
.DeleteContents( true );
785 wxDataViewCtrlBase::~wxDataViewCtrlBase()
789 bool wxDataViewCtrlBase::AssociateModel( wxDataViewListModel
*model
)
796 wxDataViewListModel
* wxDataViewCtrlBase::GetModel()
801 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
)
803 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewTextRenderer(), model_column
) );
806 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
)
808 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewToggleRenderer(), model_column
, 30 ) );
811 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
)
813 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewProgressRenderer(), model_column
, 70 ) );
816 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
)
818 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewDateRenderer(), model_column
) );
821 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
)
823 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewBitmapRenderer(), model_column
) );
826 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
)
828 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewTextRenderer(), model_column
) );
831 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
)
833 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewToggleRenderer(), model_column
, 30 ) );
836 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
)
838 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewProgressRenderer(), model_column
, 70 ) );
841 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
)
843 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewDateRenderer(), model_column
) );
846 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
)
848 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewBitmapRenderer(), model_column
) );
851 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
853 m_cols
.Append( (wxObject
*) col
);
854 col
->SetOwner( (wxDataViewCtrl
*) this );
855 m_model
->AddViewingColumn( col
, col
->GetModelColumn() );
859 unsigned int wxDataViewCtrlBase::GetNumberOfColumns()
861 return m_cols
.GetCount();
864 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
869 bool wxDataViewCtrlBase::ClearColumns()
874 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
876 return (wxDataViewColumn
*) m_cols
[ pos
];
879 // ---------------------------------------------------------
881 // ---------------------------------------------------------
883 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
885 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_SELECTED
)
886 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_ACTIVATED
)
887 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
888 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)