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 );
45 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
49 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
52 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
53 if (!notifier
->ItemAdded( parent
, item
))
55 node
= node
->GetNext();
61 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&item
)
65 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
68 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
69 if (!notifier
->ItemDeleted( item
))
71 node
= node
->GetNext();
77 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
81 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
84 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
85 if (!notifier
->ItemChanged( item
))
87 node
= node
->GetNext();
93 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
97 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
100 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
101 if (!notifier
->ValueChanged( item
, col
))
103 node
= node
->GetNext();
109 bool wxDataViewModel::Cleared()
113 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
116 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
117 if (!notifier
->Cleared())
119 node
= node
->GetNext();
125 void wxDataViewModel::Resort()
127 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
130 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
132 node
= node
->GetNext();
136 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
138 m_notifiers
.Append( notifier
);
139 notifier
->SetOwner( this );
142 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
144 m_notifiers
.DeleteObject( notifier
);
147 int wxDataViewModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
149 wxVariant value1
,value2
;
150 GetValue( value1
, item1
, m_sortingColumn
);
151 GetValue( value2
, item2
, m_sortingColumn
);
152 if (value1
.GetType() == wxT("string"))
154 wxString str1
= value1
.GetString();
155 wxString str2
= value2
.GetString();
156 return str1
.Cmp( str2
);
158 if (value1
.GetType() == wxT("long"))
160 long l1
= value1
.GetLong();
161 long l2
= value2
.GetLong();
164 if (value1
.GetType() == wxT("double"))
166 double d1
= value1
.GetDouble();
167 double d2
= value2
.GetDouble();
168 if (d1
== d2
) return 0;
169 if (d1
< d2
) return 1;
172 if (value1
.GetType() == wxT("datetime"))
174 wxDateTime dt1
= value1
.GetDateTime();
175 wxDateTime dt2
= value2
.GetDateTime();
176 if (dt1
.IsEqualTo(dt2
)) return 0;
177 if (dt1
.IsEarlierThan(dt2
)) return 1;
184 // ---------------------------------------------------------
185 // wxDataViewRendererBase
186 // ---------------------------------------------------------
188 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
190 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
191 wxDataViewCellMode
WXUNUSED(mode
),
192 int WXUNUSED(align
) )
194 m_variantType
= varianttype
;
198 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
200 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
203 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
205 m_item
= item
; // remember for later
207 unsigned int col
= GetOwner()->GetModelColumn();
209 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
211 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
213 wxDataViewEditorCtrlEvtHandler
*handler
=
214 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
216 m_editorCtrl
->PushEventHandler( handler
);
218 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
219 handler
->SetFocusOnIdle();
221 m_editorCtrl
->SetFocus();
227 void wxDataViewRendererBase::CancelEditing()
229 wxPendingDelete
.Append( m_editorCtrl
);
231 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
233 // m_editorCtrl->PopEventHandler( true );
236 bool wxDataViewRendererBase::FinishEditing()
239 GetValueFromEditorCtrl( m_editorCtrl
, value
);
241 wxPendingDelete
.Append( m_editorCtrl
);
243 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
245 if (!Validate(value
))
248 unsigned int col
= GetOwner()->GetModelColumn();
249 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
250 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
252 // m_editorCtrl->PopEventHandler( true );
257 //-----------------------------------------------------------------------------
258 // wxDataViewEditorCtrlEvtHandler
259 //-----------------------------------------------------------------------------
261 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
262 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
263 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
264 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
267 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
268 wxControl
*editorCtrl
,
269 wxDataViewRenderer
*owner
)
272 m_editorCtrl
= editorCtrl
;
277 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
281 m_focusOnIdle
= false;
282 if (wxWindow::FindFocus() != m_editorCtrl
)
283 m_editorCtrl
->SetFocus();
289 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
291 switch ( event
.m_keyCode
)
295 m_owner
->FinishEditing();
300 m_owner
->CancelEditing();
308 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
313 m_owner
->FinishEditing();
319 // ---------------------------------------------------------
320 // wxDataViewColumnBase
321 // ---------------------------------------------------------
323 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
325 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
326 wxDataViewRenderer
*renderer
,
327 unsigned int model_column
,
329 wxAlignment
WXUNUSED(align
),
332 m_renderer
= renderer
;
333 m_model_column
= model_column
;
335 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
337 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
338 // parameters inside the native control!
341 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
342 wxDataViewRenderer
*renderer
,
343 unsigned int model_column
,
345 wxAlignment
WXUNUSED(align
),
346 int WXUNUSED(flags
) )
348 m_renderer
= renderer
;
349 m_model_column
= model_column
;
352 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
355 wxDataViewColumnBase::~wxDataViewColumnBase()
361 int wxDataViewColumnBase::GetFlags() const
366 ret
|= wxDATAVIEW_COL_SORTABLE
;
368 ret
|= wxDATAVIEW_COL_RESIZABLE
;
370 ret
|= wxDATAVIEW_COL_HIDDEN
;
375 void wxDataViewColumnBase::SetFlags(int flags
)
377 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
378 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
379 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
382 // ---------------------------------------------------------
383 // wxDataViewEventModelNotifier
384 // ---------------------------------------------------------
386 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
389 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
391 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
393 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
394 event
.SetEventObject( m_ctrl
);
395 event
.SetModel( m_ctrl
->GetModel() );
396 event
.SetItem( item
);
397 event
.SetColumn( col
);
398 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
402 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
403 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
404 virtual bool ItemDeleted( const wxDataViewItem
&item
)
405 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
406 virtual bool ItemChanged( const wxDataViewItem
&item
)
407 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
408 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
409 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
410 virtual bool Cleared()
411 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
414 wxDataViewCtrl
*m_ctrl
;
418 // ---------------------------------------------------------
419 // wxDataViewCtrlBase
420 // ---------------------------------------------------------
422 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
424 wxDataViewCtrlBase::wxDataViewCtrlBase()
427 m_cols
.DeleteContents( true );
428 m_eventNotifier
= NULL
;
429 m_expander_column
= 0;
433 wxDataViewCtrlBase::~wxDataViewCtrlBase()
435 // IMPORTANT: before calling DecRef() on our model (since it may
436 // result in a free() call), erase all columns (since
437 // they hold a pointer to our model)
443 m_model
->RemoveNotifier( m_eventNotifier
);
444 m_eventNotifier
= NULL
;
451 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
456 m_model
->RemoveNotifier( m_eventNotifier
);
457 m_eventNotifier
= NULL
;
459 m_model
->DecRef(); // discard old model, if any
462 // add our own reference to the new model:
467 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
468 m_model
->AddNotifier( m_eventNotifier
);
474 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
479 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
480 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
482 return AppendColumn( new wxDataViewColumn( label
,
483 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
484 model_column
, width
, align
, flags
) );
487 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
488 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
490 return AppendColumn( new wxDataViewColumn( label
,
491 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
492 model_column
, width
, align
, flags
) );
495 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
496 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
498 return AppendColumn( new wxDataViewColumn( label
,
499 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
500 model_column
, width
, align
, flags
) );
503 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
504 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
506 return AppendColumn( new wxDataViewColumn( label
,
507 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
508 model_column
, width
, align
, flags
) );
511 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
512 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
514 return AppendColumn( new wxDataViewColumn( label
,
515 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
516 model_column
, width
, align
, flags
) );
519 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
520 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
522 return AppendColumn( new wxDataViewColumn( label
,
523 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
524 model_column
, width
, align
, flags
) );
527 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
528 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
530 return AppendColumn( new wxDataViewColumn( label
,
531 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
532 model_column
, width
, align
, flags
) );
535 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
536 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
538 return AppendColumn( new wxDataViewColumn( label
,
539 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
540 model_column
, width
, align
, flags
) );
543 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
544 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
546 return AppendColumn( new wxDataViewColumn( label
,
547 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
548 model_column
, width
, align
, flags
) );
551 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
552 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
554 return AppendColumn( new wxDataViewColumn( label
,
555 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
556 model_column
, width
, align
, flags
) );
559 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
561 m_cols
.Append( (wxObject
*) col
);
562 col
->SetOwner( (wxDataViewCtrl
*) this );
566 unsigned int wxDataViewCtrlBase::GetColumnCount() const
568 return m_cols
.GetCount();
571 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
576 bool wxDataViewCtrlBase::ClearColumns()
581 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
583 return (wxDataViewColumn
*) m_cols
[ pos
];
586 // ---------------------------------------------------------
588 // ---------------------------------------------------------
590 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
592 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
593 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
594 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
595 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
596 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
598 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
599 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
600 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
601 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
602 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)