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
21 #include "wx/object.h"
26 #include "wx/dataview.h"
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 wxNode
*node
= m_notifiers
.GetFirst();
57 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
58 if (!notifier
->RowAppended())
60 node
= node
->GetNext();
66 bool wxDataViewListModel::RowPrepended()
70 wxNode
*node
= m_notifiers
.GetFirst();
73 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
74 if (!notifier
->RowPrepended())
76 node
= node
->GetNext();
82 bool wxDataViewListModel::RowInserted( size_t before
)
86 wxNode
*node
= m_notifiers
.GetFirst();
89 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
90 if (!notifier
->RowInserted(before
))
92 node
= node
->GetNext();
98 bool wxDataViewListModel::RowDeleted( size_t row
)
102 wxNode
*node
= m_notifiers
.GetFirst();
105 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
106 if (!notifier
->RowDeleted( row
))
108 node
= node
->GetNext();
114 bool wxDataViewListModel::RowChanged( size_t row
)
118 wxNode
*node
= m_notifiers
.GetFirst();
121 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
122 if (!notifier
->RowChanged( row
))
124 node
= node
->GetNext();
130 bool wxDataViewListModel::ValueChanged( size_t col
, size_t row
)
134 wxNode
*node
= m_notifiers
.GetFirst();
137 wxDataViewListModelNotifier
* notifier
= (wxDataViewListModelNotifier
*) node
->GetData();
138 if (!notifier
->ValueChanged( col
, row
))
140 node
= node
->GetNext();
146 bool wxDataViewListModel::RowsReordered( size_t *new_order
)
150 wxNode
*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 wxNode
*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
, size_t model_column
)
180 m_viewingColumns
.Append( new wxDataViewViewingColumn( view_column
, model_column
) );
183 void wxDataViewListModel::RemoveViewingColumn( wxDataViewColumn
*column
)
185 wxNode
*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() { return true; }
222 virtual bool RowPrepended() { return true; }
223 virtual bool RowInserted( size_t WXUNUSED(before
) ) { return true; }
224 virtual bool RowDeleted( size_t WXUNUSED(row
) ) { return true; }
225 virtual bool RowChanged( size_t WXUNUSED(row
) ) { return true; }
226 virtual bool ValueChanged( size_t col
, size_t row
)
227 { return m_model
->ChildValueChanged( col
, row
); }
228 virtual bool RowsReordered( size_t *WXUNUSED(new_order
) ) { return true; }
229 virtual bool Cleared() { return true; }
231 wxDataViewSortedListModel
*m_model
;
234 // ---------------------------------------------------------
235 // wxDataViewSortedListModel compare function
236 // ---------------------------------------------------------
238 int wxCALLBACK wxDataViewListModelSortedDefaultCompare
239 (size_t row1
, size_t row2
, size_t col
, wxDataViewListModel
* model
)
241 wxVariant value1
,value2
;
242 model
->GetValue( value1
, col
, row1
);
243 model
->GetValue( value2
, col
, row2
);
244 if (value1
.GetType() == wxT("string"))
246 wxString str1
= value1
.GetString();
247 wxString str2
= value2
.GetString();
248 return str1
.Cmp( str2
);
250 if (value1
.GetType() == wxT("long"))
252 long l1
= value1
.GetLong();
253 long l2
= value2
.GetLong();
256 if (value1
.GetType() == wxT("double"))
258 double d1
= value1
.GetDouble();
259 double d2
= value2
.GetDouble();
260 if (d1
== d2
) return 0;
261 if (d1
< d2
) return 1;
264 if (value1
.GetType() == wxT("datetime"))
266 wxDateTime dt1
= value1
.GetDateTime();
267 wxDateTime dt2
= value2
.GetDateTime();
268 if (dt1
.IsEqualTo(dt2
)) return 0;
269 if (dt1
.IsEarlierThan(dt2
)) return 1;
276 static wxDataViewListModelCompare s_CmpFunc
;
277 static wxDataViewListModel
*s_CmpModel
;
278 static size_t s_CmpCol
;
280 int LINKAGEMODE
wxDataViewIntermediateCmp( size_t row1
, size_t row2
)
282 return s_CmpFunc( row1
, row2
, s_CmpCol
, s_CmpModel
);
285 // ---------------------------------------------------------
286 // wxDataViewSortedListModel
287 // ---------------------------------------------------------
289 IMPLEMENT_ABSTRACT_CLASS(wxDataViewSortedListModel
, wxDataViewListModel
)
291 wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel
*child
) :
292 m_array( wxDataViewIntermediateCmp
)
297 s_CmpFunc
= wxDataViewListModelSortedDefaultCompare
;
299 m_notifierOnChild
= new wxDataViewSortedListModelNotifier( this );
300 m_child
->AddNotifier( m_notifierOnChild
);
305 wxDataViewSortedListModel::~wxDataViewSortedListModel()
307 m_child
->RemoveNotifier( m_notifierOnChild
);
310 void wxDataViewSortedListModel::Resort()
313 size_t n
= m_child
->GetNumberOfRows();
315 for (i
= 0; i
< n
; i
++)
320 static void Dump( wxDataViewListModel
*model
, size_t col
)
322 size_t n
= model
->GetNumberOfRows();
324 for (i
= 0; i
< n
; i
++)
327 model
->GetValue( variant
, col
, i
);
329 tmp
= variant
.GetString();
330 wxPrintf( wxT("%d: %s\n"), (int) i
, tmp
.c_str() );
335 bool wxDataViewSortedListModel::ChildValueChanged( size_t col
, size_t row
)
338 size_t len
= m_array
.GetCount();
340 // Remove and readd sorted. Find out at which
341 // position it was and where it ended.
342 size_t start_pos
= 0,end_pos
= 0;
343 for (i
= 0; i
< len
; i
++)
344 if (m_array
[i
] == row
)
349 m_array
.RemoveAt( start_pos
);
352 for (i
= 0; i
< len
; i
++)
353 if (m_array
[i
] == row
)
359 if (end_pos
== start_pos
)
360 return wxDataViewListModel::ValueChanged( col
, start_pos
);
362 // Create an array where order[old] -> new_pos, so that
363 // if nothing changed order[0] -> 0 etc.
364 size_t *order
= new size_t[ len
];
365 // Fill up initial values.
366 for (i
= 0; i
< len
; i
++)
369 if (start_pos
< end_pos
)
371 for (i
= start_pos
; i
< end_pos
; i
++)
372 order
[i
] = order
[i
+1];
373 order
[end_pos
] = start_pos
;
377 for (i
= end_pos
; i
> start_pos
; i
--)
378 order
[i
] = order
[i
-1];
379 order
[start_pos
] = end_pos
;
382 wxDataViewListModel::RowsReordered( order
);
389 size_t wxDataViewSortedListModel::GetNumberOfRows()
391 return m_array
.GetCount();
394 size_t wxDataViewSortedListModel::GetNumberOfCols()
396 return m_child
->GetNumberOfCols();
399 wxString
wxDataViewSortedListModel::GetColType( size_t col
)
401 return m_child
->GetColType( col
);
404 void wxDataViewSortedListModel::GetValue( wxVariant
&variant
, size_t col
, size_t row
)
406 size_t child_row
= m_array
[row
];
407 m_child
->GetValue( variant
, col
, child_row
);
410 bool wxDataViewSortedListModel::SetValue( wxVariant
&variant
, size_t col
, size_t row
)
412 size_t child_row
= m_array
[row
];
413 bool ret
= m_child
->SetValue( variant
, col
, child_row
);
415 // Resort in ::ChildValueChanged() which gets reported back.
420 bool wxDataViewSortedListModel::RowAppended()
422 // you can only append
423 bool ret
= m_child
->RowAppended();
430 bool wxDataViewSortedListModel::RowPrepended()
432 // you can only append
433 bool ret
= m_child
->RowAppended();
440 bool wxDataViewSortedListModel::RowInserted( size_t WXUNUSED(before
) )
442 // you can only append
443 bool ret
= m_child
->RowAppended();
445 // report different RowInsrted
450 bool wxDataViewSortedListModel::RowDeleted( size_t row
)
452 size_t child_row
= m_array
[row
];
454 bool ret
= m_child
->RowDeleted( child_row
);
456 // Do nothing here as the change in the
457 // child model will be reported back.
462 bool wxDataViewSortedListModel::RowChanged( size_t row
)
464 size_t child_row
= m_array
[row
];
465 bool ret
= m_child
->RowChanged( child_row
);
467 // Do nothing here as the change in the
468 // child model will be reported back.
473 bool wxDataViewSortedListModel::ValueChanged( size_t col
, size_t row
)
475 size_t child_row
= m_array
[row
];
476 bool ret
= m_child
->ValueChanged( col
, child_row
);
478 // Do nothing here as the change in the
479 // child model will be reported back.
484 bool wxDataViewSortedListModel::RowsReordered( size_t *WXUNUSED(new_order
) )
486 // We sort them ourselves.
491 bool wxDataViewSortedListModel::Cleared()
493 bool ret
= m_child
->Cleared();
495 wxDataViewListModel::Cleared();
500 // ---------------------------------------------------------
501 // wxDataViewCellBase
502 // ---------------------------------------------------------
504 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCellBase
, wxObject
)
506 wxDataViewCellBase::wxDataViewCellBase( const wxString
&varianttype
, wxDataViewCellMode mode
)
508 m_variantType
= varianttype
;
512 // ---------------------------------------------------------
513 // wxDataViewColumnBase
514 // ---------------------------------------------------------
516 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
518 wxDataViewColumnBase::wxDataViewColumnBase( const wxString
&title
, wxDataViewCell
*cell
, size_t model_column
, int flags
)
521 m_model_column
= model_column
;
525 m_cell
->SetOwner( (wxDataViewColumn
*) this );
528 wxDataViewColumnBase::~wxDataViewColumnBase()
535 GetOwner()->GetModel()->RemoveViewingColumn( (wxDataViewColumn
*) this );
539 void wxDataViewColumnBase::SetTitle( const wxString
&title
)
544 wxString
wxDataViewColumnBase::GetTitle()
549 // ---------------------------------------------------------
550 // wxDataViewCtrlBase
551 // ---------------------------------------------------------
553 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
555 wxDataViewCtrlBase::wxDataViewCtrlBase()
558 m_cols
.DeleteContents( true );
561 wxDataViewCtrlBase::~wxDataViewCtrlBase()
565 bool wxDataViewCtrlBase::AssociateModel( wxDataViewListModel
*model
)
572 wxDataViewListModel
* wxDataViewCtrlBase::GetModel()
577 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, size_t model_column
)
579 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewTextCell(), model_column
) );
582 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, size_t model_column
)
584 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewToggleCell(), model_column
) );
587 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, size_t model_column
)
589 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewProgressCell(), model_column
) );
592 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, size_t model_column
)
594 return AppendColumn( new wxDataViewColumn( label
, new wxDataViewDateCell(), model_column
) );
597 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
599 m_cols
.Append( (wxObject
*) col
);
600 col
->SetOwner( (wxDataViewCtrl
*) this );
601 m_model
->AddViewingColumn( col
, col
->GetModelColumn() );
605 size_t wxDataViewCtrlBase::GetNumberOfColumns()
607 return m_cols
.GetCount();
610 bool wxDataViewCtrlBase::DeleteColumn( size_t WXUNUSED(pos
) )
615 bool wxDataViewCtrlBase::ClearColumns()
620 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( size_t pos
)
622 return (wxDataViewColumn
*) m_cols
[ pos
];