]> git.saurik.com Git - wxWidgets.git/blob - src/common/datavcmn.cpp
ec05414d7e3d9227d2ca5732083023037f34be65
[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 #include "wx/defs.h"
19
20 #if wxUSE_DATAVIEWCTRL
21
22 #include "wx/object.h"
23 #include "wx/dataview.h"
24 #include "wx/log.h"
25 #include "wx/image.h"
26
27 // ---------------------------------------------------------
28 // wxDataViewModel
29 // ---------------------------------------------------------
30
31 IMPLEMENT_ABSTRACT_CLASS(wxDataViewModel, wxObject)
32
33 // ---------------------------------------------------------
34 // wxDataViewListModel
35 // ---------------------------------------------------------
36
37 IMPLEMENT_ABSTRACT_CLASS(wxDataViewListModel, wxDataViewModel)
38
39 wxDataViewListModel::wxDataViewListModel()
40 {
41 m_viewingColumns.DeleteContents( true );
42 m_notifiers.DeleteContents( true );
43 }
44
45 wxDataViewListModel::~wxDataViewListModel()
46 {
47 }
48
49 bool wxDataViewListModel::RowAppended()
50 {
51 bool ret = true;
52
53 wxNode *node = m_notifiers.GetFirst();
54 while (node)
55 {
56 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
57 if (!notifier->RowAppended())
58 ret = false;
59 node = node->GetNext();
60 }
61
62 return ret;
63 }
64
65 bool wxDataViewListModel::RowPrepended()
66 {
67 bool ret = true;
68
69 wxNode *node = m_notifiers.GetFirst();
70 while (node)
71 {
72 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
73 if (!notifier->RowPrepended())
74 ret = false;
75 node = node->GetNext();
76 }
77
78 return ret;
79 }
80
81 bool wxDataViewListModel::RowInserted( size_t before )
82 {
83 bool ret = true;
84
85 wxNode *node = m_notifiers.GetFirst();
86 while (node)
87 {
88 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
89 if (!notifier->RowInserted(before))
90 ret = false;
91 node = node->GetNext();
92 }
93
94 return ret;
95 }
96
97 bool wxDataViewListModel::RowDeleted( size_t row )
98 {
99 bool ret = true;
100
101 wxNode *node = m_notifiers.GetFirst();
102 while (node)
103 {
104 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
105 if (!notifier->RowDeleted( row ))
106 ret = false;
107 node = node->GetNext();
108 }
109
110 return ret;
111 }
112
113 bool wxDataViewListModel::RowChanged( size_t row )
114 {
115 bool ret = true;
116
117 wxNode *node = m_notifiers.GetFirst();
118 while (node)
119 {
120 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
121 if (!notifier->RowChanged( row ))
122 ret = false;
123 node = node->GetNext();
124 }
125
126 return ret;
127 }
128
129 bool wxDataViewListModel::ValueChanged( size_t col, size_t row )
130 {
131 bool ret = true;
132
133 wxNode *node = m_notifiers.GetFirst();
134 while (node)
135 {
136 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
137 if (!notifier->ValueChanged( col, row ))
138 ret = false;
139 node = node->GetNext();
140 }
141
142 return ret;
143 }
144
145 bool wxDataViewListModel::RowsReordered( size_t *new_order )
146 {
147 bool ret = true;
148
149 wxNode *node = m_notifiers.GetFirst();
150 while (node)
151 {
152 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
153 if (!notifier->RowsReordered( new_order ))
154 ret = false;
155 node = node->GetNext();
156 }
157
158 return ret;
159 }
160
161 bool wxDataViewListModel::Cleared()
162 {
163 bool ret = true;
164
165 wxNode *node = m_notifiers.GetFirst();
166 while (node)
167 {
168 wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
169 if (!notifier->Cleared())
170 ret = false;
171 node = node->GetNext();
172 }
173
174 return ret;
175 }
176
177 void wxDataViewListModel::AddViewingColumn( wxDataViewColumn *view_column, size_t model_column )
178 {
179 m_viewingColumns.Append( new wxDataViewViewingColumn( view_column, model_column ) );
180 }
181
182 void wxDataViewListModel::RemoveViewingColumn( wxDataViewColumn *column )
183 {
184 wxNode *node = m_viewingColumns.GetFirst();
185 while (node)
186 {
187 wxDataViewViewingColumn* tmp = (wxDataViewViewingColumn*) node->GetData();
188
189 if (tmp->m_viewColumn == column)
190 {
191 m_viewingColumns.DeleteObject( tmp );
192 return;
193 }
194
195 node = node->GetNext();
196 }
197 }
198
199 void wxDataViewListModel::AddNotifier( wxDataViewListModelNotifier *notifier )
200 {
201 m_notifiers.Append( notifier );
202 notifier->SetOwner( this );
203 }
204
205 void wxDataViewListModel::RemoveNotifier( wxDataViewListModelNotifier *notifier )
206 {
207 m_notifiers.DeleteObject( notifier );
208 }
209
210 // ---------------------------------------------------------
211 // wxDataViewSortedListModelNotifier
212 // ---------------------------------------------------------
213
214 class wxDataViewSortedListModelNotifier: public wxDataViewListModelNotifier
215 {
216 public:
217 wxDataViewSortedListModelNotifier( wxDataViewSortedListModel *model )
218 { m_model = model; }
219
220 virtual bool RowAppended() { return true; }
221 virtual bool RowPrepended() { return true; }
222 virtual bool RowInserted( size_t before ) { return true; }
223 virtual bool RowDeleted( size_t row ) { return true; }
224 virtual bool RowChanged( size_t row ) { return true; }
225 virtual bool ValueChanged( size_t col, size_t row )
226 { return m_model->ChildValueChanged( col, row); }
227 virtual bool RowsReordered( size_t *new_order ) { return true; }
228 virtual bool Cleared() { return true; }
229
230 wxDataViewSortedListModel *m_model;
231 };
232
233 // ---------------------------------------------------------
234 // wxDataViewSortedListModel compare function
235 // ---------------------------------------------------------
236
237 int wxCALLBACK wxDataViewListModelSortedDefaultCompare
238 (size_t row1, size_t row2, size_t col, wxDataViewListModel* model )
239 {
240 wxVariant value1 = model->GetValue( col, row1 );
241 wxVariant value2 = model->GetValue( col, row2 );
242 if (value1.GetType() == wxT("string"))
243 {
244 wxString str1 = value1.GetString();
245 wxString str2 = value2.GetString();
246 return str1.Cmp( str2 );
247 }
248 if (value1.GetType() == wxT("long"))
249 {
250 long l1 = value1.GetLong();
251 long l2 = value2.GetLong();
252 return l1-l2;
253 }
254 if (value1.GetType() == wxT("double"))
255 {
256 double d1 = value1.GetDouble();
257 double d2 = value2.GetDouble();
258 if (d1 == d2) return 0;
259 if (d1 < d2) return 1;
260 return -1;
261 }
262 if (value1.GetType() == wxT("datetime"))
263 {
264 wxDateTime dt1 = value1.GetDateTime();
265 wxDateTime dt2 = value2.GetDateTime();
266 if (dt1.IsEqualTo(dt2)) return 0;
267 if (dt1.IsEarlierThan(dt2)) return 1;
268 return -1;
269 }
270
271 return 0;
272 }
273
274 static wxDataViewListModelCompare s_CmpFunc;
275 static wxDataViewListModel *s_CmpModel;
276 static size_t s_CmpCol;
277
278 int LINKAGEMODE wxDataViewIntermediateCmp( size_t row1, size_t row2 )
279 {
280 return s_CmpFunc( row1, row2, s_CmpCol, s_CmpModel );
281 }
282
283 // ---------------------------------------------------------
284 // wxDataViewSortedListModel
285 // ---------------------------------------------------------
286
287 IMPLEMENT_ABSTRACT_CLASS(wxDataViewSortedListModel, wxDataViewListModel)
288
289 wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel *child ) :
290 m_array( wxDataViewIntermediateCmp )
291 {
292 m_child = child;
293 s_CmpCol = 0;
294 s_CmpModel = child;
295 s_CmpFunc = wxDataViewListModelSortedDefaultCompare;
296
297 m_notifierOnChild = new wxDataViewSortedListModelNotifier( this );
298 m_child->AddNotifier( m_notifierOnChild );
299
300 Resort();
301 }
302
303 wxDataViewSortedListModel::~wxDataViewSortedListModel()
304 {
305 m_child->RemoveNotifier( m_notifierOnChild );
306 }
307
308 void wxDataViewSortedListModel::Resort()
309 {
310 m_array.Clear();
311 size_t n = m_child->GetNumberOfRows();
312 size_t i;
313 for (i = 0; i < n; i++)
314 m_array.Add( i );
315 }
316
317 bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row )
318 {
319 size_t i;
320 size_t len = m_array.GetCount();
321
322 // Remove and readd sorted. Find out at which
323 // position it was and where it ended.
324 size_t start_pos = 0,end_pos = 0;
325 for (i = 0; i < len; i++)
326 if (m_array[i] == row)
327 {
328 start_pos = i;
329 break;
330 }
331 m_array.Remove( row );
332 m_array.Add( row );
333 for (i = 0; i < len; i++)
334 if (m_array[i] == row)
335 {
336 end_pos = i;
337 break;
338 }
339
340 if (end_pos == start_pos)
341 return wxDataViewListModel::ValueChanged( col, start_pos );
342
343 // Create an array where order[old] -> new_pos, so that
344 // if nothing changed order[0] -> 0 etc.
345 size_t *order = new size_t[ len ];
346 // Fill up initial values.
347 for (i = 0; i < len; i++)
348 order[i] = i;
349
350 if (start_pos < end_pos)
351 {
352 for (i = start_pos; i < end_pos; i++)
353 order[i] = order[i+1];
354 order[end_pos] = start_pos;
355 }
356 else
357 {
358 for (i = end_pos; i > start_pos; i--)
359 order[i] = order[i-1];
360 order[start_pos] = end_pos;
361 }
362
363 RowsReordered( order );
364
365 delete [] order;
366
367 return true;
368 }
369
370 size_t wxDataViewSortedListModel::GetNumberOfRows()
371 {
372 return m_child->GetNumberOfRows();
373 }
374
375 size_t wxDataViewSortedListModel::GetNumberOfCols()
376 {
377 return m_child->GetNumberOfCols();
378 }
379
380 wxString wxDataViewSortedListModel::GetColType( size_t col )
381 {
382 return m_child->GetColType( col );
383 }
384
385 wxVariant wxDataViewSortedListModel::GetValue( size_t col, size_t row )
386 {
387 size_t child_row = m_array[row];
388 return m_child->GetValue( col, child_row );
389 }
390
391 bool wxDataViewSortedListModel::SetValue( wxVariant &variant, size_t col, size_t row )
392 {
393 size_t child_row = m_array[row];
394 bool ret = m_child->SetValue( variant, col, child_row );
395
396 // Resort in ::ChildValueChanged() which gets reported back.
397
398 return ret;
399 }
400
401 bool wxDataViewSortedListModel::RowAppended()
402 {
403 // you can only append
404 bool ret = m_child->RowAppended();
405
406 // report RowInsrted
407
408 return ret;
409 }
410
411 bool wxDataViewSortedListModel::RowPrepended()
412 {
413 // you can only append
414 bool ret = m_child->RowAppended();
415
416 // report RowInsrted
417
418 return ret;
419 }
420
421 bool wxDataViewSortedListModel::RowInserted( size_t before )
422 {
423 // you can only append
424 bool ret = m_child->RowAppended();
425
426 // report different RowInsrted
427
428 return ret;
429 }
430
431 bool wxDataViewSortedListModel::RowDeleted( size_t row )
432 {
433 size_t child_row = m_array[row];
434
435 bool ret = m_child->RowDeleted( child_row );
436
437 // Do nothing here as the change in the
438 // child model will be reported back.
439
440 return ret;
441 }
442
443 bool wxDataViewSortedListModel::RowChanged( size_t row )
444 {
445 size_t child_row = m_array[row];
446 bool ret = m_child->RowChanged( child_row );
447
448 // Do nothing here as the change in the
449 // child model will be reported back.
450
451 return ret;
452 }
453
454 bool wxDataViewSortedListModel::ValueChanged( size_t col, size_t row )
455 {
456 size_t child_row = m_array[row];
457 bool ret = m_child->ValueChanged( col, child_row );
458
459 // Do nothing here as the change in the
460 // child model will be reported back.
461
462 return ret;
463 }
464
465 bool wxDataViewSortedListModel::RowsReordered( size_t *new_order )
466 {
467 // We sort them ourselves.
468
469 return false;
470 }
471
472 bool wxDataViewSortedListModel::Cleared()
473 {
474 bool ret = m_child->Cleared();
475
476 wxDataViewListModel::Cleared();
477
478 return ret;
479 }
480
481 // ---------------------------------------------------------
482 // wxDataViewCellBase
483 // ---------------------------------------------------------
484
485 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCellBase, wxObject)
486
487 wxDataViewCellBase::wxDataViewCellBase( const wxString &varianttype, wxDataViewCellMode mode )
488 {
489 m_variantType = varianttype;
490 m_mode = mode;
491 }
492
493 // ---------------------------------------------------------
494 // wxDataViewColumnBase
495 // ---------------------------------------------------------
496
497 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase, wxObject)
498
499 wxDataViewColumnBase::wxDataViewColumnBase( const wxString &title, wxDataViewCell *cell, size_t model_column, int flags)
500 {
501 m_cell = cell;
502 m_model_column = model_column;
503 m_flags = flags;
504 m_title = title;
505 m_owner = NULL;
506 m_cell->SetOwner( (wxDataViewColumn*) this );
507 }
508
509 wxDataViewColumnBase::~wxDataViewColumnBase()
510 {
511 if (m_cell)
512 delete m_cell;
513
514 if (GetOwner())
515 {
516 GetOwner()->GetModel()->RemoveViewingColumn( (wxDataViewColumn*) this );
517 }
518 }
519
520 void wxDataViewColumnBase::SetTitle( const wxString &title )
521 {
522 m_title = title;
523 }
524
525 wxString wxDataViewColumnBase::GetTitle()
526 {
527 return m_title;
528 }
529
530 // ---------------------------------------------------------
531 // wxDataViewCtrlBase
532 // ---------------------------------------------------------
533
534 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
535
536 wxDataViewCtrlBase::wxDataViewCtrlBase()
537 {
538 m_model = NULL;
539 m_cols.DeleteContents( true );
540 }
541
542 wxDataViewCtrlBase::~wxDataViewCtrlBase()
543 {
544 }
545
546 bool wxDataViewCtrlBase::AssociateModel( wxDataViewListModel *model )
547 {
548 m_model = model;
549
550 return true;
551 }
552
553 wxDataViewListModel* wxDataViewCtrlBase::GetModel()
554 {
555 return m_model;
556 }
557
558 bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, size_t model_column )
559 {
560 return AppendColumn( new wxDataViewColumn( label, new wxDataViewTextCell(), model_column ) );
561 }
562
563 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, size_t model_column )
564 {
565 return AppendColumn( new wxDataViewColumn( label, new wxDataViewToggleCell(), model_column ) );
566 }
567
568 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, size_t model_column )
569 {
570 return AppendColumn( new wxDataViewColumn( label, new wxDataViewProgressCell(), model_column ) );
571 }
572
573 bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, size_t model_column )
574 {
575 return AppendColumn( new wxDataViewColumn( label, new wxDataViewDateCell(), model_column ) );
576 }
577
578 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
579 {
580 m_cols.Append( (wxObject*) col );
581 col->SetOwner( (wxDataViewCtrl*) this );
582 m_model->AddViewingColumn( col, col->GetModelColumn() );
583 return true;
584 }
585
586 size_t wxDataViewCtrlBase::GetNumberOfColumns()
587 {
588 return m_cols.GetCount();
589 }
590
591 bool wxDataViewCtrlBase::DeleteColumn( size_t pos )
592 {
593 return false;
594 }
595
596 bool wxDataViewCtrlBase::ClearColumns()
597 {
598 return false;
599 }
600
601 wxDataViewColumn* wxDataViewCtrlBase::GetColumn( size_t pos )
602 {
603 return (wxDataViewColumn*) m_cols[ pos ];
604 }
605
606 #endif