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 return str1
.Cmp( str2
);
167 if (value1
.GetType() == wxT("long"))
169 long l1
= value1
.GetLong();
170 long l2
= value2
.GetLong();
173 if (value1
.GetType() == wxT("double"))
175 double d1
= value1
.GetDouble();
176 double d2
= value2
.GetDouble();
177 if (d1
== d2
) return 0;
178 if (d1
< d2
) return 1;
181 if (value1
.GetType() == wxT("datetime"))
183 wxDateTime dt1
= value1
.GetDateTime();
184 wxDateTime dt2
= value2
.GetDateTime();
185 if (dt1
.IsEqualTo(dt2
)) return 0;
186 if (dt1
.IsEarlierThan(dt2
)) return 1;
193 // ---------------------------------------------------------
194 // wxDataViewRendererBase
195 // ---------------------------------------------------------
197 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
199 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
200 wxDataViewCellMode
WXUNUSED(mode
),
201 int WXUNUSED(align
) )
203 m_variantType
= varianttype
;
207 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
209 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
212 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
214 m_item
= item
; // remember for later
216 unsigned int col
= GetOwner()->GetModelColumn();
218 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
220 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
222 wxDataViewEditorCtrlEvtHandler
*handler
=
223 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
225 m_editorCtrl
->PushEventHandler( handler
);
227 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
228 handler
->SetFocusOnIdle();
230 m_editorCtrl
->SetFocus();
236 void wxDataViewRendererBase::CancelEditing()
238 wxPendingDelete
.Append( m_editorCtrl
);
240 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
242 // m_editorCtrl->PopEventHandler( true );
245 bool wxDataViewRendererBase::FinishEditing()
248 GetValueFromEditorCtrl( m_editorCtrl
, value
);
250 wxPendingDelete
.Append( m_editorCtrl
);
252 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
254 if (!Validate(value
))
257 unsigned int col
= GetOwner()->GetModelColumn();
258 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
259 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
261 // m_editorCtrl->PopEventHandler( true );
266 //-----------------------------------------------------------------------------
267 // wxDataViewEditorCtrlEvtHandler
268 //-----------------------------------------------------------------------------
270 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
271 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
272 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
273 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
276 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
277 wxControl
*editorCtrl
,
278 wxDataViewRenderer
*owner
)
281 m_editorCtrl
= editorCtrl
;
286 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
290 m_focusOnIdle
= false;
291 if (wxWindow::FindFocus() != m_editorCtrl
)
292 m_editorCtrl
->SetFocus();
298 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
300 switch ( event
.m_keyCode
)
304 m_owner
->FinishEditing();
309 m_owner
->CancelEditing();
317 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
322 m_owner
->FinishEditing();
328 // ---------------------------------------------------------
329 // wxDataViewColumnBase
330 // ---------------------------------------------------------
332 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
334 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
335 wxDataViewRenderer
*renderer
,
336 unsigned int model_column
,
338 wxAlignment
WXUNUSED(align
),
341 m_renderer
= renderer
;
342 m_model_column
= model_column
;
344 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
346 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
347 // parameters inside the native control!
350 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
351 wxDataViewRenderer
*renderer
,
352 unsigned int model_column
,
354 wxAlignment
WXUNUSED(align
),
355 int WXUNUSED(flags
) )
357 m_renderer
= renderer
;
358 m_model_column
= model_column
;
361 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
364 wxDataViewColumnBase::~wxDataViewColumnBase()
370 int wxDataViewColumnBase::GetFlags() const
375 ret
|= wxDATAVIEW_COL_SORTABLE
;
377 ret
|= wxDATAVIEW_COL_RESIZABLE
;
379 ret
|= wxDATAVIEW_COL_HIDDEN
;
384 void wxDataViewColumnBase::SetFlags(int flags
)
386 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
387 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
388 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
391 // ---------------------------------------------------------
392 // wxDataViewEventModelNotifier
393 // ---------------------------------------------------------
395 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
398 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
400 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
402 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
403 event
.SetEventObject( m_ctrl
);
404 event
.SetModel( m_ctrl
->GetModel() );
405 event
.SetItem( item
);
406 event
.SetColumn( col
);
407 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
411 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
412 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
413 virtual bool ItemDeleted( const wxDataViewItem
&item
)
414 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
415 virtual bool ItemChanged( const wxDataViewItem
&item
)
416 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
417 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
418 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
419 virtual bool Cleared()
420 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
423 wxDataViewCtrl
*m_ctrl
;
427 // ---------------------------------------------------------
428 // wxDataViewCtrlBase
429 // ---------------------------------------------------------
431 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
433 wxDataViewCtrlBase::wxDataViewCtrlBase()
436 m_cols
.DeleteContents( true );
437 m_eventNotifier
= NULL
;
438 m_expander_column
= 0;
442 wxDataViewCtrlBase::~wxDataViewCtrlBase()
444 // IMPORTANT: before calling DecRef() on our model (since it may
445 // result in a free() call), erase all columns (since
446 // they hold a pointer to our model)
452 m_model
->RemoveNotifier( m_eventNotifier
);
453 m_eventNotifier
= NULL
;
460 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
465 m_model
->RemoveNotifier( m_eventNotifier
);
466 m_eventNotifier
= NULL
;
468 m_model
->DecRef(); // discard old model, if any
471 // add our own reference to the new model:
476 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
477 m_model
->AddNotifier( m_eventNotifier
);
483 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
488 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
489 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
491 return AppendColumn( new wxDataViewColumn( label
,
492 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
493 model_column
, width
, align
, flags
) );
496 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
497 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
499 return AppendColumn( new wxDataViewColumn( label
,
500 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
501 model_column
, width
, align
, flags
) );
504 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
505 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
507 return AppendColumn( new wxDataViewColumn( label
,
508 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
509 model_column
, width
, align
, flags
) );
512 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
513 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
515 return AppendColumn( new wxDataViewColumn( label
,
516 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
517 model_column
, width
, align
, flags
) );
520 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
521 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
523 return AppendColumn( new wxDataViewColumn( label
,
524 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
525 model_column
, width
, align
, flags
) );
528 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
529 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
531 return AppendColumn( new wxDataViewColumn( label
,
532 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
533 model_column
, width
, align
, flags
) );
536 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
537 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
539 return AppendColumn( new wxDataViewColumn( label
,
540 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
541 model_column
, width
, align
, flags
) );
544 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
545 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
547 return AppendColumn( new wxDataViewColumn( label
,
548 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
549 model_column
, width
, align
, flags
) );
552 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
553 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
555 return AppendColumn( new wxDataViewColumn( label
,
556 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
557 model_column
, width
, align
, flags
) );
560 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
561 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
563 return AppendColumn( new wxDataViewColumn( label
,
564 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
565 model_column
, width
, align
, flags
) );
568 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
570 m_cols
.Append( (wxObject
*) col
);
571 col
->SetOwner( (wxDataViewCtrl
*) this );
575 unsigned int wxDataViewCtrlBase::GetColumnCount() const
577 return m_cols
.GetCount();
580 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
585 bool wxDataViewCtrlBase::ClearColumns()
590 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
592 return (wxDataViewColumn
*) m_cols
[ pos
];
595 // ---------------------------------------------------------
597 // ---------------------------------------------------------
599 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
601 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
602 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
603 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
604 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
605 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
607 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
608 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
609 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
610 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
611 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)