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 // sort branches before leaves
151 bool item1_is_container
= IsContainer(item1
);
152 bool item2_is_container
= IsContainer(item2
);
154 if (item1_is_container
&& !item2_is_container
)
156 if (item2_is_container
&& !item1_is_container
)
159 wxVariant value1
,value2
;
160 GetValue( value1
, item1
, m_sortingColumn
);
161 GetValue( value2
, item2
, m_sortingColumn
);
165 wxVariant temp
= value1
;
170 if (value1
.GetType() == wxT("string"))
172 wxString str1
= value1
.GetString();
173 wxString str2
= value2
.GetString();
174 int res
= str1
.Cmp( str2
);
177 if (value1
.GetType() == wxT("long"))
179 long l1
= value1
.GetLong();
180 long l2
= value2
.GetLong();
184 if (value1
.GetType() == wxT("double"))
186 double d1
= value1
.GetDouble();
187 double d2
= value2
.GetDouble();
188 if (d1
< d2
) return 1;
189 if (d1
> d2
) return -1;
191 if (value1
.GetType() == wxT("datetime"))
193 wxDateTime dt1
= value1
.GetDateTime();
194 wxDateTime dt2
= value2
.GetDateTime();
195 if (dt1
.IsEarlierThan(dt2
)) return 1;
196 if (dt2
.IsEarlierThan(dt1
)) return -11;
199 // items must be different
200 unsigned long litem1
= (unsigned long) item1
.GetID();
201 unsigned long litem2
= (unsigned long) item2
.GetID();
204 return litem2
-litem1
;
205 return litem1
-litem2
;
208 // ---------------------------------------------------------
209 // wxDataViewRendererBase
210 // ---------------------------------------------------------
212 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
214 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
215 wxDataViewCellMode
WXUNUSED(mode
),
216 int WXUNUSED(align
) )
218 m_variantType
= varianttype
;
222 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
224 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
227 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
229 m_item
= item
; // remember for later
231 unsigned int col
= GetOwner()->GetModelColumn();
233 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
235 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
237 wxDataViewEditorCtrlEvtHandler
*handler
=
238 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
240 m_editorCtrl
->PushEventHandler( handler
);
242 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
243 handler
->SetFocusOnIdle();
245 m_editorCtrl
->SetFocus();
251 void wxDataViewRendererBase::CancelEditing()
253 wxPendingDelete
.Append( m_editorCtrl
);
255 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
257 // m_editorCtrl->PopEventHandler( true );
260 bool wxDataViewRendererBase::FinishEditing()
263 GetValueFromEditorCtrl( m_editorCtrl
, value
);
265 wxPendingDelete
.Append( m_editorCtrl
);
267 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
269 if (!Validate(value
))
272 unsigned int col
= GetOwner()->GetModelColumn();
273 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
274 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
276 // m_editorCtrl->PopEventHandler( true );
281 //-----------------------------------------------------------------------------
282 // wxDataViewEditorCtrlEvtHandler
283 //-----------------------------------------------------------------------------
285 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
286 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
287 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
288 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
291 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
292 wxControl
*editorCtrl
,
293 wxDataViewRenderer
*owner
)
296 m_editorCtrl
= editorCtrl
;
301 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
305 m_focusOnIdle
= false;
306 if (wxWindow::FindFocus() != m_editorCtrl
)
307 m_editorCtrl
->SetFocus();
313 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
315 switch ( event
.m_keyCode
)
319 m_owner
->FinishEditing();
324 m_owner
->CancelEditing();
332 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
337 m_owner
->FinishEditing();
343 // ---------------------------------------------------------
344 // wxDataViewColumnBase
345 // ---------------------------------------------------------
347 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
349 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
350 wxDataViewRenderer
*renderer
,
351 unsigned int model_column
,
353 wxAlignment
WXUNUSED(align
),
356 m_renderer
= renderer
;
357 m_model_column
= model_column
;
359 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
361 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
362 // parameters inside the native control!
365 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
366 wxDataViewRenderer
*renderer
,
367 unsigned int model_column
,
369 wxAlignment
WXUNUSED(align
),
370 int WXUNUSED(flags
) )
372 m_renderer
= renderer
;
373 m_model_column
= model_column
;
376 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
379 wxDataViewColumnBase::~wxDataViewColumnBase()
385 int wxDataViewColumnBase::GetFlags() const
390 ret
|= wxDATAVIEW_COL_SORTABLE
;
392 ret
|= wxDATAVIEW_COL_RESIZABLE
;
394 ret
|= wxDATAVIEW_COL_HIDDEN
;
399 void wxDataViewColumnBase::SetFlags(int flags
)
401 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
402 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
403 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
406 // ---------------------------------------------------------
407 // wxDataViewEventModelNotifier
408 // ---------------------------------------------------------
410 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
413 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
415 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
417 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
418 event
.SetEventObject( m_ctrl
);
419 event
.SetModel( m_ctrl
->GetModel() );
420 event
.SetItem( item
);
421 event
.SetColumn( col
);
422 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
426 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
427 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
428 virtual bool ItemDeleted( const wxDataViewItem
&item
)
429 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
430 virtual bool ItemChanged( const wxDataViewItem
&item
)
431 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
432 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
433 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
434 virtual bool Cleared()
435 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
438 wxDataViewCtrl
*m_ctrl
;
442 // ---------------------------------------------------------
443 // wxDataViewCtrlBase
444 // ---------------------------------------------------------
446 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
448 wxDataViewCtrlBase::wxDataViewCtrlBase()
451 m_cols
.DeleteContents( true );
452 m_eventNotifier
= NULL
;
453 m_expander_column
= 0;
457 wxDataViewCtrlBase::~wxDataViewCtrlBase()
459 // IMPORTANT: before calling DecRef() on our model (since it may
460 // result in a free() call), erase all columns (since
461 // they hold a pointer to our model)
467 m_model
->RemoveNotifier( m_eventNotifier
);
468 m_eventNotifier
= NULL
;
475 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
480 m_model
->RemoveNotifier( m_eventNotifier
);
481 m_eventNotifier
= NULL
;
483 m_model
->DecRef(); // discard old model, if any
486 // add our own reference to the new model:
491 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
492 m_model
->AddNotifier( m_eventNotifier
);
498 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
503 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
504 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
506 return AppendColumn( new wxDataViewColumn( label
,
507 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
508 model_column
, width
, align
, flags
) );
511 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
512 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
514 return AppendColumn( new wxDataViewColumn( label
,
515 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
516 model_column
, width
, align
, flags
) );
519 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
520 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
522 return AppendColumn( new wxDataViewColumn( label
,
523 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
524 model_column
, width
, align
, flags
) );
527 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
528 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
530 return AppendColumn( new wxDataViewColumn( label
,
531 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
532 model_column
, width
, align
, flags
) );
535 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
536 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
538 return AppendColumn( new wxDataViewColumn( label
,
539 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
540 model_column
, width
, align
, flags
) );
543 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
544 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
546 return AppendColumn( new wxDataViewColumn( label
,
547 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
548 model_column
, width
, align
, flags
) );
551 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
552 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
554 return AppendColumn( new wxDataViewColumn( label
,
555 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
556 model_column
, width
, align
, flags
) );
559 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
560 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
562 return AppendColumn( new wxDataViewColumn( label
,
563 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
564 model_column
, width
, align
, flags
) );
567 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
568 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
570 return AppendColumn( new wxDataViewColumn( label
,
571 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
572 model_column
, width
, align
, flags
) );
575 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
576 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
578 return AppendColumn( new wxDataViewColumn( label
,
579 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
580 model_column
, width
, align
, flags
) );
583 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
585 m_cols
.Append( (wxObject
*) col
);
586 col
->SetOwner( (wxDataViewCtrl
*) this );
590 unsigned int wxDataViewCtrlBase::GetColumnCount() const
592 return m_cols
.GetCount();
595 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
600 bool wxDataViewCtrlBase::ClearColumns()
605 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
607 return (wxDataViewColumn
*) m_cols
[ pos
];
610 // ---------------------------------------------------------
612 // ---------------------------------------------------------
614 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
616 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
617 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
618 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
619 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
620 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
622 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
623 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
624 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
625 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
626 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)