1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/datavcmn.cpp
3 // Purpose: wxDataViewCtrl base classes and common parts
4 // Author: Robert Roebling
7 // Copyright: (c) 2006, Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #if wxUSE_DATAVIEWCTRL
20 #include "wx/dataview.h"
26 const wxChar wxDataViewCtrlNameStr
[] = wxT("dataviewCtrl");
29 bool operator == (const wxDataViewItem
&left
, const wxDataViewItem
&right
)
31 return (left
.GetID() == right
.GetID() );
35 // ---------------------------------------------------------
37 // ---------------------------------------------------------
39 wxDataViewModel::wxDataViewModel()
41 m_notifiers
.DeleteContents( true );
46 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
50 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
53 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
54 if (!notifier
->ItemAdded( parent
, item
))
56 node
= node
->GetNext();
62 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&item
)
66 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
69 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
70 if (!notifier
->ItemDeleted( item
))
72 node
= node
->GetNext();
78 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
82 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
85 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
86 if (!notifier
->ItemChanged( item
))
88 node
= node
->GetNext();
94 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
98 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
101 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
102 if (!notifier
->ValueChanged( item
, col
))
104 node
= node
->GetNext();
110 bool wxDataViewModel::Cleared()
114 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
117 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
118 if (!notifier
->Cleared())
120 node
= node
->GetNext();
126 void wxDataViewModel::Resort()
128 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
131 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
133 node
= node
->GetNext();
137 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
139 m_notifiers
.Append( notifier
);
140 notifier
->SetOwner( this );
143 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
145 m_notifiers
.DeleteObject( notifier
);
148 int wxDataViewModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
150 wxVariant value1
,value2
;
151 GetValue( value1
, item1
, m_sortingColumn
);
152 GetValue( value2
, item2
, m_sortingColumn
);
156 wxVariant temp
= value1
;
161 if (value1
.GetType() == wxT("string"))
163 wxString str1
= value1
.GetString();
164 wxString str2
= value2
.GetString();
165 int res
= str1
.Cmp( str2
);
168 // no difference, try 0th column
169 if (m_sortingColumn
!= 0)
171 unsigned int temp
= m_sortingColumn
;
173 res
= Compare( item1
, item2
);
174 m_sortingColumn
= temp
;
178 // still no difference, resort to desparate non-sense
179 long l1
= (long) item1
.GetID();
180 long l2
= (long) item2
.GetID();
186 if (value1
.GetType() == wxT("long"))
188 long l1
= value1
.GetLong();
189 long l2
= value2
.GetLong();
192 if (value1
.GetType() == wxT("double"))
194 double d1
= value1
.GetDouble();
195 double d2
= value2
.GetDouble();
196 if (d1
== d2
) return 0;
197 if (d1
< d2
) return 1;
200 if (value1
.GetType() == wxT("datetime"))
202 wxDateTime dt1
= value1
.GetDateTime();
203 wxDateTime dt2
= value2
.GetDateTime();
204 if (dt1
.IsEqualTo(dt2
)) return 0;
205 if (dt1
.IsEarlierThan(dt2
)) return 1;
214 // ---------------------------------------------------------
215 // wxDataViewRendererBase
216 // ---------------------------------------------------------
218 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
220 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
221 wxDataViewCellMode
WXUNUSED(mode
),
222 int WXUNUSED(align
) )
224 m_variantType
= varianttype
;
228 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
230 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
233 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
235 m_item
= item
; // remember for later
237 unsigned int col
= GetOwner()->GetModelColumn();
239 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
241 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
243 wxDataViewEditorCtrlEvtHandler
*handler
=
244 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
246 m_editorCtrl
->PushEventHandler( handler
);
248 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
249 handler
->SetFocusOnIdle();
251 m_editorCtrl
->SetFocus();
257 void wxDataViewRendererBase::CancelEditing()
259 wxPendingDelete
.Append( m_editorCtrl
);
261 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
263 // m_editorCtrl->PopEventHandler( true );
266 bool wxDataViewRendererBase::FinishEditing()
269 GetValueFromEditorCtrl( m_editorCtrl
, value
);
271 wxPendingDelete
.Append( m_editorCtrl
);
273 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
275 if (!Validate(value
))
278 unsigned int col
= GetOwner()->GetModelColumn();
279 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
280 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
282 // m_editorCtrl->PopEventHandler( true );
287 //-----------------------------------------------------------------------------
288 // wxDataViewEditorCtrlEvtHandler
289 //-----------------------------------------------------------------------------
291 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
292 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
293 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
294 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
297 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
298 wxControl
*editorCtrl
,
299 wxDataViewRenderer
*owner
)
302 m_editorCtrl
= editorCtrl
;
307 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
311 m_focusOnIdle
= false;
312 if (wxWindow::FindFocus() != m_editorCtrl
)
313 m_editorCtrl
->SetFocus();
319 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
321 switch ( event
.m_keyCode
)
325 m_owner
->FinishEditing();
330 m_owner
->CancelEditing();
338 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
343 m_owner
->FinishEditing();
349 // ---------------------------------------------------------
350 // wxDataViewColumnBase
351 // ---------------------------------------------------------
353 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
355 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
356 wxDataViewRenderer
*renderer
,
357 unsigned int model_column
,
359 wxAlignment
WXUNUSED(align
),
362 m_renderer
= renderer
;
363 m_model_column
= model_column
;
365 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
367 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
368 // parameters inside the native control!
371 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
372 wxDataViewRenderer
*renderer
,
373 unsigned int model_column
,
375 wxAlignment
WXUNUSED(align
),
376 int WXUNUSED(flags
) )
378 m_renderer
= renderer
;
379 m_model_column
= model_column
;
382 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
385 wxDataViewColumnBase::~wxDataViewColumnBase()
391 int wxDataViewColumnBase::GetFlags() const
396 ret
|= wxDATAVIEW_COL_SORTABLE
;
398 ret
|= wxDATAVIEW_COL_RESIZABLE
;
400 ret
|= wxDATAVIEW_COL_HIDDEN
;
405 void wxDataViewColumnBase::SetFlags(int flags
)
407 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
408 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
409 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
412 // ---------------------------------------------------------
413 // wxDataViewEventModelNotifier
414 // ---------------------------------------------------------
416 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
419 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
421 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
423 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
424 event
.SetEventObject( m_ctrl
);
425 event
.SetModel( m_ctrl
->GetModel() );
426 event
.SetItem( item
);
427 event
.SetColumn( col
);
428 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
432 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
433 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
434 virtual bool ItemDeleted( const wxDataViewItem
&item
)
435 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
436 virtual bool ItemChanged( const wxDataViewItem
&item
)
437 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
438 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
439 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
440 virtual bool Cleared()
441 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
444 wxDataViewCtrl
*m_ctrl
;
448 // ---------------------------------------------------------
449 // wxDataViewCtrlBase
450 // ---------------------------------------------------------
452 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
454 wxDataViewCtrlBase::wxDataViewCtrlBase()
457 m_cols
.DeleteContents( true );
458 m_eventNotifier
= NULL
;
459 m_expander_column
= 0;
463 wxDataViewCtrlBase::~wxDataViewCtrlBase()
465 // IMPORTANT: before calling DecRef() on our model (since it may
466 // result in a free() call), erase all columns (since
467 // they hold a pointer to our model)
473 m_model
->RemoveNotifier( m_eventNotifier
);
474 m_eventNotifier
= NULL
;
481 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
486 m_model
->RemoveNotifier( m_eventNotifier
);
487 m_eventNotifier
= NULL
;
489 m_model
->DecRef(); // discard old model, if any
492 // add our own reference to the new model:
497 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
498 m_model
->AddNotifier( m_eventNotifier
);
504 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
509 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
510 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
512 return AppendColumn( new wxDataViewColumn( label
,
513 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
514 model_column
, width
, align
, flags
) );
517 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
518 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
520 return AppendColumn( new wxDataViewColumn( label
,
521 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
522 model_column
, width
, align
, flags
) );
525 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
526 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
528 return AppendColumn( new wxDataViewColumn( label
,
529 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
530 model_column
, width
, align
, flags
) );
533 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
534 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
536 return AppendColumn( new wxDataViewColumn( label
,
537 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
538 model_column
, width
, align
, flags
) );
541 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
542 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
544 return AppendColumn( new wxDataViewColumn( label
,
545 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
546 model_column
, width
, align
, flags
) );
549 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
550 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
552 return AppendColumn( new wxDataViewColumn( label
,
553 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
554 model_column
, width
, align
, flags
) );
557 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
558 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
560 return AppendColumn( new wxDataViewColumn( label
,
561 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
562 model_column
, width
, align
, flags
) );
565 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
566 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
568 return AppendColumn( new wxDataViewColumn( label
,
569 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
570 model_column
, width
, align
, flags
) );
573 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
574 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
576 return AppendColumn( new wxDataViewColumn( label
,
577 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
578 model_column
, width
, align
, flags
) );
581 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
582 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
584 return AppendColumn( new wxDataViewColumn( label
,
585 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
586 model_column
, width
, align
, flags
) );
589 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
591 m_cols
.Append( (wxObject
*) col
);
592 col
->SetOwner( (wxDataViewCtrl
*) this );
596 unsigned int wxDataViewCtrlBase::GetColumnCount() const
598 return m_cols
.GetCount();
601 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
606 bool wxDataViewCtrlBase::ClearColumns()
611 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
613 return (wxDataViewColumn
*) m_cols
[ pos
];
616 // ---------------------------------------------------------
618 // ---------------------------------------------------------
620 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
622 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
623 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
624 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
625 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
626 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
628 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
629 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
630 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
631 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
632 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)