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
);
153 if (value1
.GetType() == wxT("string"))
155 wxString str1
= value1
.GetString();
156 wxString str2
= value2
.GetString();
157 return str1
.Cmp( str2
);
159 if (value1
.GetType() == wxT("long"))
161 long l1
= value1
.GetLong();
162 long l2
= value2
.GetLong();
165 if (value1
.GetType() == wxT("double"))
167 double d1
= value1
.GetDouble();
168 double d2
= value2
.GetDouble();
169 if (d1
== d2
) return 0;
170 if (d1
< d2
) return 1;
173 if (value1
.GetType() == wxT("datetime"))
175 wxDateTime dt1
= value1
.GetDateTime();
176 wxDateTime dt2
= value2
.GetDateTime();
177 if (dt1
.IsEqualTo(dt2
)) return 0;
178 if (dt1
.IsEarlierThan(dt2
)) return 1;
185 // ---------------------------------------------------------
186 // wxDataViewRendererBase
187 // ---------------------------------------------------------
189 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
191 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
192 wxDataViewCellMode
WXUNUSED(mode
),
193 int WXUNUSED(align
) )
195 m_variantType
= varianttype
;
199 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
201 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
204 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
206 m_item
= item
; // remember for later
208 unsigned int col
= GetOwner()->GetModelColumn();
210 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
212 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
214 wxDataViewEditorCtrlEvtHandler
*handler
=
215 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
217 m_editorCtrl
->PushEventHandler( handler
);
219 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
220 handler
->SetFocusOnIdle();
222 m_editorCtrl
->SetFocus();
228 void wxDataViewRendererBase::CancelEditing()
230 wxPendingDelete
.Append( m_editorCtrl
);
232 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
234 // m_editorCtrl->PopEventHandler( true );
237 bool wxDataViewRendererBase::FinishEditing()
240 GetValueFromEditorCtrl( m_editorCtrl
, value
);
242 wxPendingDelete
.Append( m_editorCtrl
);
244 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
246 if (!Validate(value
))
249 unsigned int col
= GetOwner()->GetModelColumn();
250 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
251 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
253 // m_editorCtrl->PopEventHandler( true );
258 //-----------------------------------------------------------------------------
259 // wxDataViewEditorCtrlEvtHandler
260 //-----------------------------------------------------------------------------
262 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
263 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
264 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
265 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
268 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
269 wxControl
*editorCtrl
,
270 wxDataViewRenderer
*owner
)
273 m_editorCtrl
= editorCtrl
;
278 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
282 m_focusOnIdle
= false;
283 if (wxWindow::FindFocus() != m_editorCtrl
)
284 m_editorCtrl
->SetFocus();
290 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
292 switch ( event
.m_keyCode
)
296 m_owner
->FinishEditing();
301 m_owner
->CancelEditing();
309 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
314 m_owner
->FinishEditing();
320 // ---------------------------------------------------------
321 // wxDataViewColumnBase
322 // ---------------------------------------------------------
324 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
326 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
327 wxDataViewRenderer
*renderer
,
328 unsigned int model_column
,
330 wxAlignment
WXUNUSED(align
),
333 m_renderer
= renderer
;
334 m_model_column
= model_column
;
336 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
338 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
339 // parameters inside the native control!
342 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
343 wxDataViewRenderer
*renderer
,
344 unsigned int model_column
,
346 wxAlignment
WXUNUSED(align
),
347 int WXUNUSED(flags
) )
349 m_renderer
= renderer
;
350 m_model_column
= model_column
;
353 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
356 wxDataViewColumnBase::~wxDataViewColumnBase()
362 int wxDataViewColumnBase::GetFlags() const
367 ret
|= wxDATAVIEW_COL_SORTABLE
;
369 ret
|= wxDATAVIEW_COL_RESIZABLE
;
371 ret
|= wxDATAVIEW_COL_HIDDEN
;
376 void wxDataViewColumnBase::SetFlags(int flags
)
378 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
379 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
380 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
383 // ---------------------------------------------------------
384 // wxDataViewEventModelNotifier
385 // ---------------------------------------------------------
387 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
390 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
392 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
394 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
395 event
.SetEventObject( m_ctrl
);
396 event
.SetModel( m_ctrl
->GetModel() );
397 event
.SetItem( item
);
398 event
.SetColumn( col
);
399 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
403 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
404 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
405 virtual bool ItemDeleted( const wxDataViewItem
&item
)
406 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
407 virtual bool ItemChanged( const wxDataViewItem
&item
)
408 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
409 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
410 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
411 virtual bool Cleared()
412 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
415 wxDataViewCtrl
*m_ctrl
;
419 // ---------------------------------------------------------
420 // wxDataViewCtrlBase
421 // ---------------------------------------------------------
423 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
425 wxDataViewCtrlBase::wxDataViewCtrlBase()
428 m_cols
.DeleteContents( true );
429 m_eventNotifier
= NULL
;
430 m_expander_column
= 0;
434 wxDataViewCtrlBase::~wxDataViewCtrlBase()
436 // IMPORTANT: before calling DecRef() on our model (since it may
437 // result in a free() call), erase all columns (since
438 // they hold a pointer to our model)
444 m_model
->RemoveNotifier( m_eventNotifier
);
445 m_eventNotifier
= NULL
;
452 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
457 m_model
->RemoveNotifier( m_eventNotifier
);
458 m_eventNotifier
= NULL
;
460 m_model
->DecRef(); // discard old model, if any
463 // add our own reference to the new model:
468 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
469 m_model
->AddNotifier( m_eventNotifier
);
475 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
480 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
481 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
483 return AppendColumn( new wxDataViewColumn( label
,
484 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
485 model_column
, width
, align
, flags
) );
488 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
489 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
491 return AppendColumn( new wxDataViewColumn( label
,
492 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
493 model_column
, width
, align
, flags
) );
496 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
497 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
499 return AppendColumn( new wxDataViewColumn( label
,
500 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
501 model_column
, width
, align
, flags
) );
504 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
505 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
507 return AppendColumn( new wxDataViewColumn( label
,
508 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
509 model_column
, width
, align
, flags
) );
512 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
513 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
515 return AppendColumn( new wxDataViewColumn( label
,
516 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
517 model_column
, width
, align
, flags
) );
520 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
521 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
523 return AppendColumn( new wxDataViewColumn( label
,
524 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
525 model_column
, width
, align
, flags
) );
528 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
529 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
531 return AppendColumn( new wxDataViewColumn( label
,
532 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
533 model_column
, width
, align
, flags
) );
536 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
537 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
539 return AppendColumn( new wxDataViewColumn( label
,
540 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
541 model_column
, width
, align
, flags
) );
544 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
545 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
547 return AppendColumn( new wxDataViewColumn( label
,
548 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
549 model_column
, width
, align
, flags
) );
552 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
553 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
555 return AppendColumn( new wxDataViewColumn( label
,
556 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
557 model_column
, width
, align
, flags
) );
560 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
562 m_cols
.Append( (wxObject
*) col
);
563 col
->SetOwner( (wxDataViewCtrl
*) this );
567 unsigned int wxDataViewCtrlBase::GetColumnCount() const
569 return m_cols
.GetCount();
572 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
577 bool wxDataViewCtrlBase::ClearColumns()
582 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
584 return (wxDataViewColumn
*) m_cols
[ pos
];
587 // ---------------------------------------------------------
589 // ---------------------------------------------------------
591 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
593 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
594 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
595 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
596 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
597 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
599 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
600 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
601 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
602 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
603 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)