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 );
49 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
53 wxDataViewModelNotifiers::iterator iter
;
54 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
56 wxDataViewModelNotifier
* notifier
= *iter
;
57 if (!notifier
->ItemAdded( parent
, item
))
64 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
68 wxDataViewModelNotifiers::iterator iter
;
69 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
71 wxDataViewModelNotifier
* notifier
= *iter
;
72 if (!notifier
->ItemDeleted( parent
, item
))
79 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
83 wxDataViewModelNotifiers::iterator iter
;
84 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
86 wxDataViewModelNotifier
* notifier
= *iter
;
87 if (!notifier
->ItemChanged( item
))
94 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
98 wxDataViewModelNotifiers::iterator iter
;
99 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
101 wxDataViewModelNotifier
* notifier
= *iter
;
102 if (!notifier
->ValueChanged( item
, col
))
109 bool wxDataViewModel::Cleared()
113 wxDataViewModelNotifiers::iterator iter
;
114 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
116 wxDataViewModelNotifier
* notifier
= *iter
;
117 if (!notifier
->Cleared())
124 void wxDataViewModel::Resort()
126 wxDataViewModelNotifiers::iterator iter
;
127 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
129 wxDataViewModelNotifier
* notifier
= *iter
;
134 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
136 m_notifiers
.push_back( notifier
);
137 notifier
->SetOwner( this );
140 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
142 m_notifiers
.DeleteObject( notifier
);
145 int wxDataViewModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
147 // sort branches before leaves
148 bool item1_is_container
= IsContainer(item1
);
149 bool item2_is_container
= IsContainer(item2
);
151 if (item1_is_container
&& !item2_is_container
)
153 if (item2_is_container
&& !item1_is_container
)
156 wxVariant value1
,value2
;
157 GetValue( value1
, item1
, m_sortingColumn
);
158 GetValue( value2
, item2
, m_sortingColumn
);
162 wxVariant temp
= value1
;
167 if (value1
.GetType() == wxT("string"))
169 wxString str1
= value1
.GetString();
170 wxString str2
= value2
.GetString();
171 int res
= str1
.Cmp( str2
);
174 if (value1
.GetType() == wxT("long"))
176 long l1
= value1
.GetLong();
177 long l2
= value2
.GetLong();
181 if (value1
.GetType() == wxT("double"))
183 double d1
= value1
.GetDouble();
184 double d2
= value2
.GetDouble();
185 if (d1
< d2
) return 1;
186 if (d1
> d2
) return -1;
188 if (value1
.GetType() == wxT("datetime"))
190 wxDateTime dt1
= value1
.GetDateTime();
191 wxDateTime dt2
= value2
.GetDateTime();
192 if (dt1
.IsEarlierThan(dt2
)) return 1;
193 if (dt2
.IsEarlierThan(dt1
)) return -11;
196 // items must be different
197 unsigned long litem1
= (unsigned long) item1
.GetID();
198 unsigned long litem2
= (unsigned long) item2
.GetID();
201 return litem2
-litem1
;
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 m_hash
.RemoveAt( row
);
250 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item
);
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 return wxDataViewItem( m_hash
[row
] );
274 int wxDataViewIndexListModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
276 return GetRow(item1
) - GetRow(item2
);
279 void wxDataViewIndexListModel::GetValue( wxVariant
&variant
,
280 const wxDataViewItem
&item
, unsigned int col
) const
282 return GetValue( variant
, GetRow(item
), col
);
285 bool wxDataViewIndexListModel::SetValue( const wxVariant
&variant
,
286 const wxDataViewItem
&item
, unsigned int col
)
288 return SetValue( variant
, GetRow(item
), col
);
291 wxDataViewItem
wxDataViewIndexListModel::GetParent( const wxDataViewItem
&item
) const
293 return wxDataViewItem(0);
296 bool wxDataViewIndexListModel::IsContainer( const wxDataViewItem
&item
) const
298 // only the invisible root item has children
305 wxDataViewItem
wxDataViewIndexListModel::GetFirstChild( const wxDataViewItem
&parent
) const
309 if (m_hash
.GetCount() == 0)
310 return wxDataViewItem(0);
312 return wxDataViewItem( m_hash
[0]);
315 return wxDataViewItem(0);
318 wxDataViewItem
wxDataViewIndexListModel::GetNextSibling( const wxDataViewItem
&item
) const
321 return wxDataViewItem(0);
323 int pos
= m_hash
.Index( item
.GetID() );
324 if ((pos
== wxNOT_FOUND
) || (pos
== m_hash
.GetCount()-1))
325 return wxDataViewItem(0);
327 return wxDataViewItem( m_hash
[pos
+1] );
330 // ---------------------------------------------------------
331 // wxDataViewRendererBase
332 // ---------------------------------------------------------
334 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
336 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
337 wxDataViewCellMode
WXUNUSED(mode
),
338 int WXUNUSED(align
) )
340 m_variantType
= varianttype
;
344 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
346 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
349 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
351 m_item
= item
; // remember for later
353 unsigned int col
= GetOwner()->GetModelColumn();
355 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
357 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
359 wxDataViewEditorCtrlEvtHandler
*handler
=
360 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
362 m_editorCtrl
->PushEventHandler( handler
);
364 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
365 handler
->SetFocusOnIdle();
367 m_editorCtrl
->SetFocus();
373 void wxDataViewRendererBase::CancelEditing()
375 wxPendingDelete
.Append( m_editorCtrl
);
377 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
379 // m_editorCtrl->PopEventHandler( true );
382 bool wxDataViewRendererBase::FinishEditing()
385 GetValueFromEditorCtrl( m_editorCtrl
, value
);
387 wxPendingDelete
.Append( m_editorCtrl
);
389 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
391 if (!Validate(value
))
394 unsigned int col
= GetOwner()->GetModelColumn();
395 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
396 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
398 // m_editorCtrl->PopEventHandler( true );
403 //-----------------------------------------------------------------------------
404 // wxDataViewEditorCtrlEvtHandler
405 //-----------------------------------------------------------------------------
407 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
408 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
409 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
410 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
413 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
414 wxControl
*editorCtrl
,
415 wxDataViewRenderer
*owner
)
418 m_editorCtrl
= editorCtrl
;
423 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
427 m_focusOnIdle
= false;
428 if (wxWindow::FindFocus() != m_editorCtrl
)
429 m_editorCtrl
->SetFocus();
435 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
437 switch ( event
.m_keyCode
)
441 m_owner
->FinishEditing();
446 m_owner
->CancelEditing();
454 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
459 m_owner
->FinishEditing();
465 // ---------------------------------------------------------
466 // wxDataViewColumnBase
467 // ---------------------------------------------------------
469 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
471 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
472 wxDataViewRenderer
*renderer
,
473 unsigned int model_column
,
475 wxAlignment
WXUNUSED(align
),
478 m_renderer
= renderer
;
479 m_model_column
= model_column
;
481 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
483 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
484 // parameters inside the native control!
487 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
488 wxDataViewRenderer
*renderer
,
489 unsigned int model_column
,
491 wxAlignment
WXUNUSED(align
),
492 int WXUNUSED(flags
) )
494 m_renderer
= renderer
;
495 m_model_column
= model_column
;
498 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
501 wxDataViewColumnBase::~wxDataViewColumnBase()
507 int wxDataViewColumnBase::GetFlags() const
512 ret
|= wxDATAVIEW_COL_SORTABLE
;
514 ret
|= wxDATAVIEW_COL_RESIZABLE
;
516 ret
|= wxDATAVIEW_COL_HIDDEN
;
521 void wxDataViewColumnBase::SetFlags(int flags
)
523 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
524 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
525 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
528 // ---------------------------------------------------------
529 // wxDataViewCtrlBase
530 // ---------------------------------------------------------
532 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
534 wxDataViewCtrlBase::wxDataViewCtrlBase()
537 m_cols
.DeleteContents( true );
538 m_expander_column
= 0;
542 wxDataViewCtrlBase::~wxDataViewCtrlBase()
544 // IMPORTANT: before calling DecRef() on our model (since it may
545 // result in a free() call), erase all columns (since
546 // they hold a pointer to our model)
556 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
560 m_model
->DecRef(); // discard old model, if any
563 // add our own reference to the new model:
573 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
578 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
579 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
581 return AppendColumn( new wxDataViewColumn( label
,
582 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
583 model_column
, width
, align
, flags
) );
586 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
587 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
589 return AppendColumn( new wxDataViewColumn( label
,
590 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
591 model_column
, width
, align
, flags
) );
594 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
595 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
597 return AppendColumn( new wxDataViewColumn( label
,
598 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
599 model_column
, width
, align
, flags
) );
602 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
603 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
605 return AppendColumn( new wxDataViewColumn( label
,
606 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
607 model_column
, width
, align
, flags
) );
610 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
611 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
613 return AppendColumn( new wxDataViewColumn( label
,
614 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
615 model_column
, width
, align
, flags
) );
618 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
619 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
621 return AppendColumn( new wxDataViewColumn( label
,
622 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
623 model_column
, width
, align
, flags
) );
626 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
627 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
629 return AppendColumn( new wxDataViewColumn( label
,
630 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
631 model_column
, width
, align
, flags
) );
634 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
635 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
637 return AppendColumn( new wxDataViewColumn( label
,
638 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
639 model_column
, width
, align
, flags
) );
642 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
643 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
645 return AppendColumn( new wxDataViewColumn( label
,
646 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
647 model_column
, width
, align
, flags
) );
650 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
651 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
653 return AppendColumn( new wxDataViewColumn( label
,
654 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
655 model_column
, width
, align
, flags
) );
658 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
660 m_cols
.Append( (wxObject
*) col
);
661 col
->SetOwner( (wxDataViewCtrl
*) this );
665 unsigned int wxDataViewCtrlBase::GetColumnCount() const
667 return m_cols
.GetCount();
670 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
675 bool wxDataViewCtrlBase::ClearColumns()
680 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
682 return (wxDataViewColumn
*) m_cols
[ pos
];
685 // ---------------------------------------------------------
687 // ---------------------------------------------------------
689 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
691 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
692 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
693 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
694 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
695 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
697 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
698 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
699 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
700 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
701 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)