]> git.saurik.com Git - wxWidgets.git/blob - src/common/datavcmn.cpp
Bo's patch for generic code, more sorting code, WIP
[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 m_expander_column = 0;
376 m_indent = 8;
377 }
378
379 wxDataViewCtrlBase::~wxDataViewCtrlBase()
380 {
381 // IMPORTANT: before calling DecRef() on our model (since it may
382 // result in a free() call), erase all columns (since
383 // they hold a pointer to our model)
384 m_cols.Clear();
385
386 if (m_model)
387 {
388 if (m_eventNotifier)
389 m_model->RemoveNotifier( m_eventNotifier );
390 m_eventNotifier = NULL;
391
392 m_model->DecRef();
393 m_model = NULL;
394 }
395 }
396
397 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
398 {
399 if (m_model)
400 {
401 if (m_eventNotifier)
402 m_model->RemoveNotifier( m_eventNotifier );
403 m_eventNotifier = NULL;
404
405 m_model->DecRef(); // discard old model, if any
406 }
407
408 // add our own reference to the new model:
409 m_model = model;
410 if (m_model)
411 {
412 m_model->IncRef();
413 m_eventNotifier = new wxDataViewEventModelNotifier( (wxDataViewCtrl*) this );
414 m_model->AddNotifier( m_eventNotifier );
415 }
416
417 return true;
418 }
419
420 wxDataViewModel* wxDataViewCtrlBase::GetModel()
421 {
422 return m_model;
423 }
424
425 bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
426 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
427 {
428 return AppendColumn( new wxDataViewColumn( label,
429 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
430 model_column, width, align, flags ) );
431 }
432
433 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
434 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
435 {
436 return AppendColumn( new wxDataViewColumn( label,
437 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
438 model_column, width, align, flags ) );
439 }
440
441 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
442 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
443 {
444 return AppendColumn( new wxDataViewColumn( label,
445 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
446 model_column, width, align, flags ) );
447 }
448
449 bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
450 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
451 {
452 return AppendColumn( new wxDataViewColumn( label,
453 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
454 model_column, width, align, flags ) );
455 }
456
457 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
458 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
459 {
460 return AppendColumn( new wxDataViewColumn( label,
461 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
462 model_column, width, align, flags ) );
463 }
464
465 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
466 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
467 {
468 return AppendColumn( new wxDataViewColumn( label,
469 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
470 model_column, width, align, flags ) );
471 }
472
473 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
474 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
475 {
476 return AppendColumn( new wxDataViewColumn( label,
477 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
478 model_column, width, align, flags ) );
479 }
480
481 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
482 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
483 {
484 return AppendColumn( new wxDataViewColumn( label,
485 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
486 model_column, width, align, flags ) );
487 }
488
489 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
490 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
491 {
492 return AppendColumn( new wxDataViewColumn( label,
493 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
494 model_column, width, align, flags ) );
495 }
496
497 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
498 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
499 {
500 return AppendColumn( new wxDataViewColumn( label,
501 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
502 model_column, width, align, flags ) );
503 }
504
505 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
506 {
507 m_cols.Append( (wxObject*) col );
508 col->SetOwner( (wxDataViewCtrl*) this );
509 return true;
510 }
511
512 unsigned int wxDataViewCtrlBase::GetColumnCount() const
513 {
514 return m_cols.GetCount();
515 }
516
517 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos) )
518 {
519 return false;
520 }
521
522 bool wxDataViewCtrlBase::ClearColumns()
523 {
524 return false;
525 }
526
527 wxDataViewColumn* wxDataViewCtrlBase::GetColumn( unsigned int pos )
528 {
529 return (wxDataViewColumn*) m_cols[ pos ];
530 }
531
532 // ---------------------------------------------------------
533 // wxDataViewEvent
534 // ---------------------------------------------------------
535
536 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
537
538 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED)
539 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED)
540 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK)
541 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK)
542 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED)
543
544 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED)
545 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED)
546 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED)
547 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED)
548 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED)
549
550 #endif