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