]> git.saurik.com Git - wxWidgets.git/blob - src/common/datavcmn.cpp
Add compare function to wxDataViewModel
[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 // ---------------------------------------------------------
30 // wxDataViewListModel
31 // ---------------------------------------------------------
32
33 wxDataViewModel::wxDataViewModel()
34 {
35 m_notifiers.DeleteContents( true );
36 m_cmpFunc = NULL;
37 }
38
39 bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
40 {
41 bool ret = true;
42
43 wxList::compatibility_iterator node = m_notifiers.GetFirst();
44 while (node)
45 {
46 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
47 if (!notifier->ItemAdded( parent, item ))
48 ret = false;
49 node = node->GetNext();
50 }
51
52 return ret;
53 }
54
55 bool wxDataViewModel::ItemDeleted( const wxDataViewItem &item )
56 {
57 bool ret = true;
58
59 wxList::compatibility_iterator node = m_notifiers.GetFirst();
60 while (node)
61 {
62 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
63 if (!notifier->ItemDeleted( item ))
64 ret = false;
65 node = node->GetNext();
66 }
67
68 return ret;
69 }
70
71 bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
72 {
73 bool ret = true;
74
75 wxList::compatibility_iterator node = m_notifiers.GetFirst();
76 while (node)
77 {
78 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
79 if (!notifier->ItemChanged( item ))
80 ret = false;
81 node = node->GetNext();
82 }
83
84 return ret;
85 }
86
87 bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
88 {
89 bool ret = true;
90
91 wxList::compatibility_iterator node = m_notifiers.GetFirst();
92 while (node)
93 {
94 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
95 if (!notifier->ValueChanged( item, col ))
96 ret = false;
97 node = node->GetNext();
98 }
99
100 return ret;
101 }
102
103 bool wxDataViewModel::Cleared()
104 {
105 bool ret = true;
106
107 wxList::compatibility_iterator node = m_notifiers.GetFirst();
108 while (node)
109 {
110 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
111 if (!notifier->Cleared())
112 ret = false;
113 node = node->GetNext();
114 }
115
116 return ret;
117 }
118
119 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
120 {
121 m_notifiers.Append( notifier );
122 notifier->SetOwner( this );
123 }
124
125 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
126 {
127 m_notifiers.DeleteObject( notifier );
128 }
129
130 // ---------------------------------------------------------
131 // wxDataViewRendererBase
132 // ---------------------------------------------------------
133
134 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
135
136 wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
137 wxDataViewCellMode WXUNUSED(mode),
138 int WXUNUSED(align) )
139 {
140 m_variantType = varianttype;
141 m_editorCtrl = NULL;
142 }
143
144 const wxDataViewCtrl* wxDataViewRendererBase::GetView() const
145 {
146 return wx_const_cast(wxDataViewRendererBase*, this)->GetOwner()->GetOwner();
147 }
148
149 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
150 {
151 m_item = item; // remember for later
152
153 unsigned int col = GetOwner()->GetModelColumn();
154 wxVariant value;
155 GetOwner()->GetOwner()->GetModel()->GetValue( value, item, col );
156
157 m_editorCtrl = CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect, value );
158
159 wxDataViewEditorCtrlEvtHandler *handler =
160 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
161
162 m_editorCtrl->PushEventHandler( handler );
163
164 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
165 handler->SetFocusOnIdle();
166 #else
167 m_editorCtrl->SetFocus();
168 #endif
169
170 return true;
171 }
172
173 void wxDataViewRendererBase::CancelEditing()
174 {
175 wxPendingDelete.Append( m_editorCtrl );
176
177 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
178
179 // m_editorCtrl->PopEventHandler( true );
180 }
181
182 bool wxDataViewRendererBase::FinishEditing()
183 {
184 wxVariant value;
185 GetValueFromEditorCtrl( m_editorCtrl, value );
186
187 wxPendingDelete.Append( m_editorCtrl );
188
189 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
190
191 if (!Validate(value))
192 return false;
193
194 unsigned int col = GetOwner()->GetModelColumn();
195 GetOwner()->GetOwner()->GetModel()->SetValue( value, m_item, col );
196 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item, col );
197
198 // m_editorCtrl->PopEventHandler( true );
199
200 return true;
201 }
202
203 //-----------------------------------------------------------------------------
204 // wxDataViewEditorCtrlEvtHandler
205 //-----------------------------------------------------------------------------
206
207 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
208 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
209 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
210 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
211 END_EVENT_TABLE()
212
213 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
214 wxControl *editorCtrl,
215 wxDataViewRenderer *owner )
216 {
217 m_owner = owner;
218 m_editorCtrl = editorCtrl;
219
220 m_finished = false;
221 }
222
223 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
224 {
225 if (m_focusOnIdle)
226 {
227 m_focusOnIdle = false;
228 if (wxWindow::FindFocus() != m_editorCtrl)
229 m_editorCtrl->SetFocus();
230 }
231
232 event.Skip();
233 }
234
235 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
236 {
237 switch ( event.m_keyCode )
238 {
239 case WXK_RETURN:
240 m_finished = true;
241 m_owner->FinishEditing();
242 break;
243
244 case WXK_ESCAPE:
245 m_finished = true;
246 m_owner->CancelEditing();
247 break;
248
249 default:
250 event.Skip();
251 }
252 }
253
254 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
255 {
256 if (!m_finished)
257 {
258 m_finished = true;
259 m_owner->FinishEditing();
260 }
261
262 event.Skip();
263 }
264
265 // ---------------------------------------------------------
266 // wxDataViewColumnBase
267 // ---------------------------------------------------------
268
269 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase, wxObject)
270
271 wxDataViewColumnBase::wxDataViewColumnBase(const wxString& WXUNUSED(title),
272 wxDataViewRenderer *renderer,
273 unsigned int model_column,
274 int WXUNUSED(width),
275 wxAlignment WXUNUSED(align),
276 int WXUNUSED(flags))
277 {
278 m_renderer = renderer;
279 m_model_column = model_column;
280 m_owner = NULL;
281 m_renderer->SetOwner( (wxDataViewColumn*) this );
282
283 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
284 // parameters inside the native control!
285 }
286
287 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap& bitmap,
288 wxDataViewRenderer *renderer,
289 unsigned int model_column,
290 int WXUNUSED(width),
291 wxAlignment WXUNUSED(align),
292 int WXUNUSED(flags) )
293 {
294 m_renderer = renderer;
295 m_model_column = model_column;
296 m_bitmap = bitmap;
297 m_owner = NULL;
298 m_renderer->SetOwner( (wxDataViewColumn*) this );
299 }
300
301 wxDataViewColumnBase::~wxDataViewColumnBase()
302 {
303 if (m_renderer)
304 delete m_renderer;
305 }
306
307 int wxDataViewColumnBase::GetFlags() const
308 {
309 int ret = 0;
310
311 if (IsSortable())
312 ret |= wxDATAVIEW_COL_SORTABLE;
313 if (IsResizeable())
314 ret |= wxDATAVIEW_COL_RESIZABLE;
315 if (IsHidden())
316 ret |= wxDATAVIEW_COL_HIDDEN;
317
318 return ret;
319 }
320
321 void wxDataViewColumnBase::SetFlags(int flags)
322 {
323 SetSortable((flags & wxDATAVIEW_COL_SORTABLE) != 0);
324 SetResizeable((flags & wxDATAVIEW_COL_RESIZABLE) != 0);
325 SetHidden((flags & wxDATAVIEW_COL_HIDDEN) != 0);
326 }
327
328 // ---------------------------------------------------------
329 // wxDataViewEventModelNotifier
330 // ---------------------------------------------------------
331
332 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier: public wxDataViewModelNotifier
333 {
334 public:
335 wxDataViewEventModelNotifier( wxDataViewCtrl *ctrl ) { m_ctrl = ctrl; }
336
337 bool SendEvent( wxEventType event_type, const wxDataViewItem &item, unsigned int col = 0 )
338 {
339 wxDataViewEvent event( event_type, m_ctrl->GetId() );
340 event.SetEventObject( m_ctrl );
341 event.SetModel( m_ctrl->GetModel() );
342 event.SetItem( item );
343 event.SetColumn( col );
344 m_ctrl->GetEventHandler()->ProcessEvent( event );
345 return true;
346 }
347
348 virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
349 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED, item ); }
350 virtual bool ItemDeleted( const wxDataViewItem &item )
351 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED, item ); }
352 virtual bool ItemChanged( const wxDataViewItem &item )
353 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED, item ); }
354 virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col )
355 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED, item, col ); }
356 virtual bool Cleared()
357 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED, wxDataViewItem(0) ); }
358
359 private:
360 wxDataViewCtrl *m_ctrl;
361 };
362
363
364 // ---------------------------------------------------------
365 // wxDataViewCtrlBase
366 // ---------------------------------------------------------
367
368 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
369
370 wxDataViewCtrlBase::wxDataViewCtrlBase()
371 {
372 m_model = NULL;
373 m_cols.DeleteContents( true );
374 m_eventNotifier = NULL;
375 }
376
377 wxDataViewCtrlBase::~wxDataViewCtrlBase()
378 {
379 // IMPORTANT: before calling DecRef() on our model (since it may
380 // result in a free() call), erase all columns (since
381 // they hold a pointer to our model)
382 m_cols.Clear();
383
384 if (m_model)
385 {
386 if (m_eventNotifier)
387 m_model->RemoveNotifier( m_eventNotifier );
388 m_eventNotifier = NULL;
389
390 m_model->DecRef();
391 m_model = NULL;
392 }
393 }
394
395 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
396 {
397 if (m_model)
398 {
399 if (m_eventNotifier)
400 m_model->RemoveNotifier( m_eventNotifier );
401 m_eventNotifier = NULL;
402
403 m_model->DecRef(); // discard old model, if any
404 }
405
406 // add our own reference to the new model:
407 m_model = model;
408 if (m_model)
409 {
410 m_model->IncRef();
411 m_eventNotifier = new wxDataViewEventModelNotifier( (wxDataViewCtrl*) this );
412 m_model->AddNotifier( m_eventNotifier );
413 }
414
415 return true;
416 }
417
418 wxDataViewModel* wxDataViewCtrlBase::GetModel()
419 {
420 return m_model;
421 }
422
423 bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
424 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
425 {
426 return AppendColumn( new wxDataViewColumn( label,
427 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
428 model_column, width, align, flags ) );
429 }
430
431 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
432 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
433 {
434 return AppendColumn( new wxDataViewColumn( label,
435 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
436 model_column, width, align, flags ) );
437 }
438
439 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
440 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
441 {
442 return AppendColumn( new wxDataViewColumn( label,
443 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
444 model_column, width, align, flags ) );
445 }
446
447 bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
448 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
449 {
450 return AppendColumn( new wxDataViewColumn( label,
451 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
452 model_column, width, align, flags ) );
453 }
454
455 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
456 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
457 {
458 return AppendColumn( new wxDataViewColumn( label,
459 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
460 model_column, width, align, flags ) );
461 }
462
463 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
464 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
465 {
466 return AppendColumn( new wxDataViewColumn( label,
467 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
468 model_column, width, align, flags ) );
469 }
470
471 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
472 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
473 {
474 return AppendColumn( new wxDataViewColumn( label,
475 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
476 model_column, width, align, flags ) );
477 }
478
479 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
480 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
481 {
482 return AppendColumn( new wxDataViewColumn( label,
483 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
484 model_column, width, align, flags ) );
485 }
486
487 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
488 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
489 {
490 return AppendColumn( new wxDataViewColumn( label,
491 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
492 model_column, width, align, flags ) );
493 }
494
495 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
496 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
497 {
498 return AppendColumn( new wxDataViewColumn( label,
499 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
500 model_column, width, align, flags ) );
501 }
502
503 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
504 {
505 m_cols.Append( (wxObject*) col );
506 col->SetOwner( (wxDataViewCtrl*) this );
507 return true;
508 }
509
510 unsigned int wxDataViewCtrlBase::GetColumnCount() const
511 {
512 return m_cols.GetCount();
513 }
514
515 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos) )
516 {
517 return false;
518 }
519
520 bool wxDataViewCtrlBase::ClearColumns()
521 {
522 return false;
523 }
524
525 wxDataViewColumn* wxDataViewCtrlBase::GetColumn( unsigned int pos )
526 {
527 return (wxDataViewColumn*) m_cols[ pos ];
528 }
529
530 // ---------------------------------------------------------
531 // wxDataViewEvent
532 // ---------------------------------------------------------
533
534 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
535
536 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED)
537 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED)
538 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK)
539 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK)
540 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED)
541
542 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED)
543 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED)
544 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED)
545 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED)
546 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED)
547
548 #endif