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 #include "wx/listimpl.cpp"
40 WX_DEFINE_LIST(wxDataViewModelNotifiers
);
42 wxDataViewModel::wxDataViewModel()
44 m_notifiers
.DeleteContents( true );
47 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
51 wxDataViewModelNotifiers::iterator iter
;
52 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
54 wxDataViewModelNotifier
* notifier
= *iter
;
55 if (!notifier
->ItemAdded( parent
, item
))
62 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
66 wxDataViewModelNotifiers::iterator iter
;
67 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
69 wxDataViewModelNotifier
* notifier
= *iter
;
70 if (!notifier
->ItemDeleted( parent
, item
))
77 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
81 wxDataViewModelNotifiers::iterator iter
;
82 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
84 wxDataViewModelNotifier
* notifier
= *iter
;
85 if (!notifier
->ItemChanged( item
))
92 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
96 wxDataViewModelNotifiers::iterator iter
;
97 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
99 wxDataViewModelNotifier
* notifier
= *iter
;
100 if (!notifier
->ValueChanged( item
, col
))
107 bool wxDataViewModel::Cleared()
111 wxDataViewModelNotifiers::iterator iter
;
112 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
114 wxDataViewModelNotifier
* notifier
= *iter
;
115 if (!notifier
->Cleared())
122 void wxDataViewModel::Resort()
124 wxDataViewModelNotifiers::iterator iter
;
125 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
127 wxDataViewModelNotifier
* notifier
= *iter
;
132 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
134 m_notifiers
.push_back( notifier
);
135 notifier
->SetOwner( this );
138 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
140 m_notifiers
.DeleteObject( notifier
);
143 int wxDataViewModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
,
144 unsigned int column
, bool ascending
)
146 // sort branches before leaves
147 bool item1_is_container
= IsContainer(item1
);
148 bool item2_is_container
= IsContainer(item2
);
150 if (item1_is_container
&& !item2_is_container
)
152 if (item2_is_container
&& !item1_is_container
)
155 wxVariant value1
,value2
;
156 GetValue( value1
, item1
, column
);
157 GetValue( value2
, item2
, column
);
161 wxVariant temp
= value1
;
166 if (value1
.GetType() == wxT("string"))
168 wxString str1
= value1
.GetString();
169 wxString str2
= value2
.GetString();
170 int res
= str1
.Cmp( str2
);
173 if (value1
.GetType() == wxT("long"))
175 long l1
= value1
.GetLong();
176 long l2
= value2
.GetLong();
180 if (value1
.GetType() == wxT("double"))
182 double d1
= value1
.GetDouble();
183 double d2
= value2
.GetDouble();
184 if (d1
< d2
) return 1;
185 if (d1
> d2
) return -1;
187 if (value1
.GetType() == wxT("datetime"))
189 wxDateTime dt1
= value1
.GetDateTime();
190 wxDateTime dt2
= value2
.GetDateTime();
191 if (dt1
.IsEarlierThan(dt2
)) return 1;
192 if (dt2
.IsEarlierThan(dt1
)) return -11;
195 // items must be different
196 unsigned long litem1
= (unsigned long) item1
.GetID();
197 unsigned long litem2
= (unsigned long) item2
.GetID();
200 return litem2
-litem2
;
202 return litem1
-litem2
;
205 // ---------------------------------------------------------
206 // wxDataViewIndexListModel
207 // ---------------------------------------------------------
209 wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size
)
211 // build initial index
213 for (i
= 1; i
< initial_size
+1; i
++)
214 m_hash
.Add( (void*) i
);
215 m_lastIndex
= initial_size
+ 1;
218 wxDataViewIndexListModel::~wxDataViewIndexListModel()
222 void wxDataViewIndexListModel::RowPrepended()
224 unsigned int id
= m_lastIndex
++;
225 m_hash
.Insert( (void*) id
, 0 );
226 wxDataViewItem
item( (void*) id
);
227 ItemAdded( wxDataViewItem(0), item
);
230 void wxDataViewIndexListModel::RowInserted( unsigned int before
)
232 unsigned int id
= m_lastIndex
++;
233 m_hash
.Insert( (void*) id
, before
);
234 wxDataViewItem
item( (void*) id
);
235 ItemAdded( wxDataViewItem(0), item
);
238 void wxDataViewIndexListModel::RowAppended()
240 unsigned int id
= m_lastIndex
++;
241 m_hash
.Add( (void*) id
);
242 wxDataViewItem
item( (void*) id
);
243 ItemAdded( wxDataViewItem(0), item
);
246 void wxDataViewIndexListModel::RowDeleted( unsigned int row
)
248 wxDataViewItem
item( m_hash
[row
] );
249 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item
);
250 m_hash
.RemoveAt( row
);
253 void wxDataViewIndexListModel::RowChanged( unsigned int row
)
255 wxDataViewModel::ItemChanged( GetItem(row
) );
258 void wxDataViewIndexListModel::RowValueChanged( unsigned int row
, unsigned int col
)
260 wxDataViewModel::ValueChanged( GetItem(row
), col
);
263 unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem
&item
) const
265 // assert for not found
266 return (unsigned int) m_hash
.Index( item
.GetID() );
269 wxDataViewItem
wxDataViewIndexListModel::GetItem( unsigned int row
) const
271 wxASSERT( row
< m_hash
.GetCount() );
272 return wxDataViewItem( m_hash
[row
] );
275 int wxDataViewIndexListModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
,
276 unsigned int column
, bool ascending
)
279 return GetRow(item1
) - GetRow(item2
);
281 return GetRow(item2
) - GetRow(item1
);
284 void wxDataViewIndexListModel::GetValue( wxVariant
&variant
,
285 const wxDataViewItem
&item
, unsigned int col
) const
287 GetValue( variant
, GetRow(item
), col
);
290 bool wxDataViewIndexListModel::SetValue( const wxVariant
&variant
,
291 const wxDataViewItem
&item
, unsigned int col
)
293 return SetValue( variant
, GetRow(item
), col
);
296 wxDataViewItem
wxDataViewIndexListModel::GetParent( const wxDataViewItem
& WXUNUSED(item
) ) const
298 return wxDataViewItem(0);
301 bool wxDataViewIndexListModel::IsContainer( const wxDataViewItem
&item
) const
303 // only the invisible root item has children
310 unsigned int wxDataViewIndexListModel::GetChildren( const wxDataViewItem
&item
, wxDataViewItemArray
&children
) const
317 return m_hash
.GetCount();
320 //-----------------------------------------------------------------------------
321 // wxDataViewIconText
322 //-----------------------------------------------------------------------------
324 IMPLEMENT_DYNAMIC_CLASS(wxDataViewIconText
,wxObject
)
326 IMPLEMENT_VARIANT_OBJECT(wxDataViewIconText
)
328 bool operator == (const wxDataViewIconText
&one
, const wxDataViewIconText
&two
)
330 if (one
.GetText() != two
.GetText()) return false;
331 if (one
.IsSameAs(two
)) return false;
335 // ---------------------------------------------------------
336 // wxDataViewRendererBase
337 // ---------------------------------------------------------
339 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
341 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
342 wxDataViewCellMode
WXUNUSED(mode
),
343 int WXUNUSED(align
) )
345 m_variantType
= varianttype
;
349 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
351 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
354 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
356 m_item
= item
; // remember for later
358 unsigned int col
= GetOwner()->GetModelColumn();
360 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
362 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
364 wxDataViewEditorCtrlEvtHandler
*handler
=
365 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
367 m_editorCtrl
->PushEventHandler( handler
);
369 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
370 handler
->SetFocusOnIdle();
372 m_editorCtrl
->SetFocus();
375 // Now we should send Editing Started event
376 wxDataViewEvent
event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED
, GetOwner()->GetOwner()->GetId() );
377 event
.SetDataViewColumn( GetOwner() );
378 event
.SetModel( GetOwner()->GetOwner()->GetModel() );
379 event
.SetItem( item
);
380 GetOwner()->GetOwner()->GetEventHandler()->ProcessEvent( event
);
385 void wxDataViewRendererBase::CancelEditing()
387 wxPendingDelete
.Append( m_editorCtrl
);
389 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
391 // m_editorCtrl->PopEventHandler( true );
394 bool wxDataViewRendererBase::FinishEditing()
397 GetValueFromEditorCtrl( m_editorCtrl
, value
);
399 wxPendingDelete
.Append( m_editorCtrl
);
401 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
403 if (!Validate(value
))
406 unsigned int col
= GetOwner()->GetModelColumn();
407 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
408 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
410 // m_editorCtrl->PopEventHandler( true );
412 // Now we should send Editing Done event
413 wxDataViewEvent
event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE
, GetOwner()->GetOwner()->GetId() );
414 event
.SetDataViewColumn( GetOwner() );
415 event
.SetModel( GetOwner()->GetOwner()->GetModel() );
416 event
.SetItem( m_item
);
417 GetOwner()->GetOwner()->GetEventHandler()->ProcessEvent( event
);
422 //-----------------------------------------------------------------------------
423 // wxDataViewEditorCtrlEvtHandler
424 //-----------------------------------------------------------------------------
426 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
427 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
428 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
429 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
432 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
433 wxControl
*editorCtrl
,
434 wxDataViewRenderer
*owner
)
437 m_editorCtrl
= editorCtrl
;
442 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
446 m_focusOnIdle
= false;
447 if (wxWindow::FindFocus() != m_editorCtrl
)
448 m_editorCtrl
->SetFocus();
454 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
456 switch ( event
.m_keyCode
)
460 m_owner
->FinishEditing();
465 m_owner
->CancelEditing();
473 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
478 m_owner
->FinishEditing();
484 // ---------------------------------------------------------
485 // wxDataViewColumnBase
486 // ---------------------------------------------------------
488 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
490 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
491 wxDataViewRenderer
*renderer
,
492 unsigned int model_column
,
494 wxAlignment
WXUNUSED(align
),
497 m_renderer
= renderer
;
498 m_model_column
= model_column
;
500 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
502 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
503 // parameters inside the native control!
506 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
507 wxDataViewRenderer
*renderer
,
508 unsigned int model_column
,
510 wxAlignment
WXUNUSED(align
),
511 int WXUNUSED(flags
) )
513 m_renderer
= renderer
;
514 m_model_column
= model_column
;
517 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
520 wxDataViewColumnBase::~wxDataViewColumnBase()
526 int wxDataViewColumnBase::GetFlags() const
531 ret
|= wxDATAVIEW_COL_SORTABLE
;
533 ret
|= wxDATAVIEW_COL_RESIZABLE
;
535 ret
|= wxDATAVIEW_COL_HIDDEN
;
540 void wxDataViewColumnBase::SetFlags(int flags
)
542 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
543 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
544 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
547 // ---------------------------------------------------------
548 // wxDataViewCtrlBase
549 // ---------------------------------------------------------
551 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
553 wxDataViewCtrlBase::wxDataViewCtrlBase()
556 m_expander_column
= 0;
560 wxDataViewCtrlBase::~wxDataViewCtrlBase()
569 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
573 m_model
->DecRef(); // discard old model, if any
576 // add our own reference to the new model:
586 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
592 wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
593 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
595 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
596 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
597 model_column
, width
, align
, flags
);
603 wxDataViewCtrlBase::AppendIconTextColumn( const wxString
&label
, unsigned int model_column
,
604 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
606 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
607 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode
, (int)align
),
608 model_column
, width
, align
, flags
);
614 wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
615 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
618 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
619 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
620 model_column
, width
, align
, flags
);
626 wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
627 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
629 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
630 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
631 model_column
, width
, align
, flags
);
637 wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
638 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
640 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
641 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
642 model_column
, width
, align
, flags
);
648 wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
649 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
651 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
652 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
653 model_column
, width
, align
, flags
);
659 wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
660 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
662 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
663 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
664 model_column
, width
, align
, flags
);
670 wxDataViewCtrlBase::AppendIconTextColumn( const wxBitmap
&label
, unsigned int model_column
,
671 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
673 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
674 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode
, (int)align
),
675 model_column
, width
, align
, flags
);
681 wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
682 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
684 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
685 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
686 model_column
, width
, align
, flags
);
692 wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
693 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
695 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
696 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
697 model_column
, width
, align
, flags
);
703 wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
704 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
706 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
707 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
708 model_column
, width
, align
, flags
);
714 wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
715 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
717 wxDataViewColumn
*ret
= new wxDataViewColumn( label
,
718 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
719 model_column
, width
, align
, flags
);
725 wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
727 col
->SetOwner( (wxDataViewCtrl
*) this );
731 // ---------------------------------------------------------
733 // ---------------------------------------------------------
735 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
737 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
738 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_DESELECTED
)
739 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
740 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING
)
741 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED
)
742 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING
)
743 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED
)
744 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED
)
745 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE
)
747 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
748 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
749 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
751 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
752 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
753 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
754 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
755 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)