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