]> git.saurik.com Git - wxWidgets.git/blob - src/common/datavcmn.cpp
The null byte at the end of the string should not be included in the
[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,value2;
241 model->GetValue( value1, col, row1 );
242 model->GetValue( value2, col, row2 );
243 if (value1.GetType() == wxT("string"))
244 {
245 wxString str1 = value1.GetString();
246 wxString str2 = value2.GetString();
247 return str1.Cmp( str2 );
248 }
249 if (value1.GetType() == wxT("long"))
250 {
251 long l1 = value1.GetLong();
252 long l2 = value2.GetLong();
253 return l1-l2;
254 }
255 if (value1.GetType() == wxT("double"))
256 {
257 double d1 = value1.GetDouble();
258 double d2 = value2.GetDouble();
259 if (d1 == d2) return 0;
260 if (d1 < d2) return 1;
261 return -1;
262 }
263 if (value1.GetType() == wxT("datetime"))
264 {
265 wxDateTime dt1 = value1.GetDateTime();
266 wxDateTime dt2 = value2.GetDateTime();
267 if (dt1.IsEqualTo(dt2)) return 0;
268 if (dt1.IsEarlierThan(dt2)) return 1;
269 return -1;
270 }
271
272 return 0;
273 }
274
275 static wxDataViewListModelCompare s_CmpFunc;
276 static wxDataViewListModel *s_CmpModel;
277 static size_t s_CmpCol;
278
279 int LINKAGEMODE wxDataViewIntermediateCmp( size_t row1, size_t row2 )
280 {
281 return s_CmpFunc( row1, row2, s_CmpCol, s_CmpModel );
282 }
283
284 // ---------------------------------------------------------
285 // wxDataViewSortedListModel
286 // ---------------------------------------------------------
287
288 IMPLEMENT_ABSTRACT_CLASS(wxDataViewSortedListModel, wxDataViewListModel)
289
290 wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel *child ) :
291 m_array( wxDataViewIntermediateCmp )
292 {
293 m_child = child;
294 s_CmpCol = 0;
295 s_CmpModel = child;
296 s_CmpFunc = wxDataViewListModelSortedDefaultCompare;
297
298 m_notifierOnChild = new wxDataViewSortedListModelNotifier( this );
299 m_child->AddNotifier( m_notifierOnChild );
300
301 Resort();
302 }
303
304 wxDataViewSortedListModel::~wxDataViewSortedListModel()
305 {
306 m_child->RemoveNotifier( m_notifierOnChild );
307 }
308
309 void wxDataViewSortedListModel::Resort()
310 {
311 m_array.Clear();
312 size_t n = m_child->GetNumberOfRows();
313 size_t i;
314 for (i = 0; i < n; i++)
315 m_array.Add( i );
316 }
317
318 #if 0
319 static void Dump( wxDataViewListModel *model, size_t col )
320 {
321 size_t n = model->GetNumberOfRows();
322 size_t i;
323 for (i = 0; i < n; i++)
324 {
325 wxVariant variant;
326 model->GetValue( variant, col, i );
327 wxString tmp;
328 tmp = variant.GetString();
329 wxPrintf( wxT("%d: %s\n"), (int) i, tmp.c_str() );
330 }
331 }
332 #endif
333
334 bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row )
335 {
336 size_t i;
337 size_t len = m_array.GetCount();
338
339 // Remove and readd sorted. Find out at which
340 // position it was and where it ended.
341 size_t start_pos = 0,end_pos = 0;
342 for (i = 0; i < len; i++)
343 if (m_array[i] == row)
344 {
345 start_pos = i;
346 break;
347 }
348 m_array.RemoveAt( start_pos );
349 m_array.Add( row );
350
351 for (i = 0; i < len; i++)
352 if (m_array[i] == row)
353 {
354 end_pos = i;
355 break;
356 }
357
358 if (end_pos == start_pos)
359 return wxDataViewListModel::ValueChanged( col, start_pos );
360
361 // Create an array where order[old] -> new_pos, so that
362 // if nothing changed order[0] -> 0 etc.
363 size_t *order = new size_t[ len ];
364 // Fill up initial values.
365 for (i = 0; i < len; i++)
366 order[i] = i;
367
368 if (start_pos < end_pos)
369 {
370 for (i = start_pos; i < end_pos; i++)
371 order[i] = order[i+1];
372 order[end_pos] = start_pos;
373 }
374 else
375 {
376 for (i = end_pos; i > start_pos; i--)
377 order[i] = order[i-1];
378 order[start_pos] = end_pos;
379 }
380
381 wxDataViewListModel::RowsReordered( order );
382
383 delete [] order;
384
385 return true;
386 }
387
388 size_t wxDataViewSortedListModel::GetNumberOfRows()
389 {
390 return m_array.GetCount();
391 }
392
393 size_t wxDataViewSortedListModel::GetNumberOfCols()
394 {
395 return m_child->GetNumberOfCols();
396 }
397
398 wxString wxDataViewSortedListModel::GetColType( size_t col )
399 {
400 return m_child->GetColType( col );
401 }
402
403 void wxDataViewSortedListModel::GetValue( wxVariant &variant, size_t col, size_t row )
404 {
405 size_t child_row = m_array[row];
406 m_child->GetValue( variant, col, child_row );
407 }
408
409 bool wxDataViewSortedListModel::SetValue( wxVariant &variant, size_t col, size_t row )
410 {
411 size_t child_row = m_array[row];
412 bool ret = m_child->SetValue( variant, col, child_row );
413
414 // Resort in ::ChildValueChanged() which gets reported back.
415
416 return ret;
417 }
418
419 bool wxDataViewSortedListModel::RowAppended()
420 {
421 // you can only append
422 bool ret = m_child->RowAppended();
423
424 // report RowInsrted
425
426 return ret;
427 }
428
429 bool wxDataViewSortedListModel::RowPrepended()
430 {
431 // you can only append
432 bool ret = m_child->RowAppended();
433
434 // report RowInsrted
435
436 return ret;
437 }
438
439 bool wxDataViewSortedListModel::RowInserted( size_t before )
440 {
441 // you can only append
442 bool ret = m_child->RowAppended();
443
444 // report different RowInsrted
445
446 return ret;
447 }
448
449 bool wxDataViewSortedListModel::RowDeleted( size_t row )
450 {
451 size_t child_row = m_array[row];
452
453 bool ret = m_child->RowDeleted( child_row );
454
455 // Do nothing here as the change in the
456 // child model will be reported back.
457
458 return ret;
459 }
460
461 bool wxDataViewSortedListModel::RowChanged( size_t row )
462 {
463 size_t child_row = m_array[row];
464 bool ret = m_child->RowChanged( child_row );
465
466 // Do nothing here as the change in the
467 // child model will be reported back.
468
469 return ret;
470 }
471
472 bool wxDataViewSortedListModel::ValueChanged( size_t col, size_t row )
473 {
474 size_t child_row = m_array[row];
475 bool ret = m_child->ValueChanged( col, child_row );
476
477 // Do nothing here as the change in the
478 // child model will be reported back.
479
480 return ret;
481 }
482
483 bool wxDataViewSortedListModel::RowsReordered( size_t *new_order )
484 {
485 // We sort them ourselves.
486
487 return false;
488 }
489
490 bool wxDataViewSortedListModel::Cleared()
491 {
492 bool ret = m_child->Cleared();
493
494 wxDataViewListModel::Cleared();
495
496 return ret;
497 }
498
499 // ---------------------------------------------------------
500 // wxDataViewCellBase
501 // ---------------------------------------------------------
502
503 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCellBase, wxObject)
504
505 wxDataViewCellBase::wxDataViewCellBase( const wxString &varianttype, wxDataViewCellMode mode )
506 {
507 m_variantType = varianttype;
508 m_mode = mode;
509 }
510
511 // ---------------------------------------------------------
512 // wxDataViewColumnBase
513 // ---------------------------------------------------------
514
515 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase, wxObject)
516
517 wxDataViewColumnBase::wxDataViewColumnBase( const wxString &title, wxDataViewCell *cell, size_t model_column, int flags)
518 {
519 m_cell = cell;
520 m_model_column = model_column;
521 m_flags = flags;
522 m_title = title;
523 m_owner = NULL;
524 m_cell->SetOwner( (wxDataViewColumn*) this );
525 }
526
527 wxDataViewColumnBase::~wxDataViewColumnBase()
528 {
529 if (m_cell)
530 delete m_cell;
531
532 if (GetOwner())
533 {
534 GetOwner()->GetModel()->RemoveViewingColumn( (wxDataViewColumn*) this );
535 }
536 }
537
538 void wxDataViewColumnBase::SetTitle( const wxString &title )
539 {
540 m_title = title;
541 }
542
543 wxString wxDataViewColumnBase::GetTitle()
544 {
545 return m_title;
546 }
547
548 // ---------------------------------------------------------
549 // wxDataViewCtrlBase
550 // ---------------------------------------------------------
551
552 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
553
554 wxDataViewCtrlBase::wxDataViewCtrlBase()
555 {
556 m_model = NULL;
557 m_cols.DeleteContents( true );
558 }
559
560 wxDataViewCtrlBase::~wxDataViewCtrlBase()
561 {
562 }
563
564 bool wxDataViewCtrlBase::AssociateModel( wxDataViewListModel *model )
565 {
566 m_model = model;
567
568 return true;
569 }
570
571 wxDataViewListModel* wxDataViewCtrlBase::GetModel()
572 {
573 return m_model;
574 }
575
576 bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, size_t model_column )
577 {
578 return AppendColumn( new wxDataViewColumn( label, new wxDataViewTextCell(), model_column ) );
579 }
580
581 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, size_t model_column )
582 {
583 return AppendColumn( new wxDataViewColumn( label, new wxDataViewToggleCell(), model_column ) );
584 }
585
586 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, size_t model_column )
587 {
588 return AppendColumn( new wxDataViewColumn( label, new wxDataViewProgressCell(), model_column ) );
589 }
590
591 bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, size_t model_column )
592 {
593 return AppendColumn( new wxDataViewColumn( label, new wxDataViewDateCell(), model_column ) );
594 }
595
596 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
597 {
598 m_cols.Append( (wxObject*) col );
599 col->SetOwner( (wxDataViewCtrl*) this );
600 m_model->AddViewingColumn( col, col->GetModelColumn() );
601 return true;
602 }
603
604 size_t wxDataViewCtrlBase::GetNumberOfColumns()
605 {
606 return m_cols.GetCount();
607 }
608
609 bool wxDataViewCtrlBase::DeleteColumn( size_t pos )
610 {
611 return false;
612 }
613
614 bool wxDataViewCtrlBase::ClearColumns()
615 {
616 return false;
617 }
618
619 wxDataViewColumn* wxDataViewCtrlBase::GetColumn( size_t pos )
620 {
621 return (wxDataViewColumn*) m_cols[ pos ];
622 }
623
624 #endif