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 );
48 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
52 wxDataViewModelNotifiers::iterator iter
;
53 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
55 wxDataViewModelNotifier
* notifier
= *iter
;
56 if (!notifier
->ItemAdded( parent
, item
))
63 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
67 wxDataViewModelNotifiers::iterator iter
;
68 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
70 wxDataViewModelNotifier
* notifier
= *iter
;
71 if (!notifier
->ItemDeleted( parent
, item
))
78 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
82 wxDataViewModelNotifiers::iterator iter
;
83 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
85 wxDataViewModelNotifier
* notifier
= *iter
;
86 if (!notifier
->ItemChanged( item
))
93 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
97 wxDataViewModelNotifiers::iterator iter
;
98 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
100 wxDataViewModelNotifier
* notifier
= *iter
;
101 if (!notifier
->ValueChanged( item
, col
))
108 bool wxDataViewModel::Cleared()
112 wxDataViewModelNotifiers::iterator iter
;
113 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
115 wxDataViewModelNotifier
* notifier
= *iter
;
116 if (!notifier
->Cleared())
123 void wxDataViewModel::Resort()
125 wxDataViewModelNotifiers::iterator iter
;
126 for (iter
= m_notifiers
.begin(); iter
!= m_notifiers
.end(); ++iter
)
128 wxDataViewModelNotifier
* notifier
= *iter
;
133 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
135 m_notifiers
.push_back( notifier
);
136 notifier
->SetOwner( this );
139 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
141 m_notifiers
.DeleteObject( notifier
);
144 int wxDataViewModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
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
, m_sortingColumn
);
157 GetValue( value2
, item2
, m_sortingColumn
);
159 if (value1
.GetType() == wxT("string"))
161 wxString str1
= value1
.GetString();
162 wxString str2
= value2
.GetString();
163 int res
= str1
.Cmp( str2
);
166 if (value1
.GetType() == wxT("long"))
168 long l1
= value1
.GetLong();
169 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 1;
178 if (d1
> d2
) return -1;
180 if (value1
.GetType() == wxT("datetime"))
182 wxDateTime dt1
= value1
.GetDateTime();
183 wxDateTime dt2
= value2
.GetDateTime();
184 if (dt1
.IsEarlierThan(dt2
)) return 1;
185 if (dt2
.IsEarlierThan(dt1
)) return -11;
188 // items must be different
189 unsigned long litem1
= (unsigned long) item1
.GetID();
190 unsigned long litem2
= (unsigned long) item2
.GetID();
192 return litem1
-litem2
;
195 // ---------------------------------------------------------
196 // wxDataViewIndexListModel
197 // ---------------------------------------------------------
199 wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size
)
201 // build initial index
203 for (i
= 1; i
< initial_size
+1; i
++)
204 m_hash
.Add( (void*) i
);
205 m_lastIndex
= initial_size
+ 1;
208 wxDataViewIndexListModel::~wxDataViewIndexListModel()
212 void wxDataViewIndexListModel::RowPrepended()
214 unsigned int id
= m_lastIndex
++;
215 m_hash
.Insert( (void*) id
, 0 );
216 wxDataViewItem
item( (void*) id
);
217 ItemAdded( wxDataViewItem(0), item
);
220 void wxDataViewIndexListModel::RowInserted( unsigned int before
)
222 unsigned int id
= m_lastIndex
++;
223 m_hash
.Insert( (void*) id
, before
);
224 wxDataViewItem
item( (void*) id
);
225 ItemAdded( wxDataViewItem(0), item
);
228 void wxDataViewIndexListModel::RowAppended()
230 unsigned int id
= m_lastIndex
++;
231 m_hash
.Add( (void*) id
);
232 wxDataViewItem
item( (void*) id
);
233 ItemAdded( wxDataViewItem(0), item
);
236 void wxDataViewIndexListModel::RowDeleted( unsigned int row
)
238 wxDataViewItem
item( m_hash
[row
] );
239 wxDataViewModel::ItemDeleted( wxDataViewItem(0), item
);
240 m_hash
.RemoveAt( row
);
243 void wxDataViewIndexListModel::RowChanged( unsigned int row
)
245 wxDataViewModel::ItemChanged( GetItem(row
) );
248 void wxDataViewIndexListModel::RowValueChanged( unsigned int row
, unsigned int col
)
250 wxDataViewModel::ValueChanged( GetItem(row
), col
);
253 unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem
&item
) const
255 // assert for not found
256 return (unsigned int) m_hash
.Index( item
.GetID() );
259 wxDataViewItem
wxDataViewIndexListModel::GetItem( unsigned int row
) const
261 return wxDataViewItem( m_hash
[row
] );
264 int wxDataViewIndexListModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
)
266 return GetRow(item1
) - GetRow(item2
);
269 void wxDataViewIndexListModel::GetValue( wxVariant
&variant
,
270 const wxDataViewItem
&item
, unsigned int col
) const
272 GetValue( variant
, GetRow(item
), col
);
275 bool wxDataViewIndexListModel::SetValue( const wxVariant
&variant
,
276 const wxDataViewItem
&item
, unsigned int col
)
278 return SetValue( variant
, GetRow(item
), col
);
281 wxDataViewItem
wxDataViewIndexListModel::GetParent( const wxDataViewItem
& WXUNUSED(item
) ) const
283 return wxDataViewItem(0);
286 bool wxDataViewIndexListModel::IsContainer( const wxDataViewItem
&item
) const
288 // only the invisible root item has children
295 wxDataViewItem
wxDataViewIndexListModel::GetFirstChild( const wxDataViewItem
&parent
) const
299 if (m_hash
.GetCount() == 0)
300 return wxDataViewItem(0);
302 return wxDataViewItem( m_hash
[0]);
305 return wxDataViewItem(0);
308 wxDataViewItem
wxDataViewIndexListModel::GetNextSibling( const wxDataViewItem
&item
) const
311 return wxDataViewItem(0);
313 int pos
= m_hash
.Index( item
.GetID() );
314 if ((pos
== wxNOT_FOUND
) || (pos
== (int) (m_hash
.GetCount()-1)))
315 return wxDataViewItem(0);
317 return wxDataViewItem( m_hash
[pos
+1] );
320 // ---------------------------------------------------------
321 // wxDataViewRendererBase
322 // ---------------------------------------------------------
324 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
326 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
327 wxDataViewCellMode
WXUNUSED(mode
),
328 int WXUNUSED(align
) )
330 m_variantType
= varianttype
;
334 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
336 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
339 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
341 m_item
= item
; // remember for later
343 unsigned int col
= GetOwner()->GetModelColumn();
345 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
347 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
349 wxDataViewEditorCtrlEvtHandler
*handler
=
350 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
352 m_editorCtrl
->PushEventHandler( handler
);
354 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
355 handler
->SetFocusOnIdle();
357 m_editorCtrl
->SetFocus();
363 void wxDataViewRendererBase::CancelEditing()
365 wxPendingDelete
.Append( m_editorCtrl
);
367 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
369 // m_editorCtrl->PopEventHandler( true );
372 bool wxDataViewRendererBase::FinishEditing()
375 GetValueFromEditorCtrl( m_editorCtrl
, value
);
377 wxPendingDelete
.Append( m_editorCtrl
);
379 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
381 if (!Validate(value
))
384 unsigned int col
= GetOwner()->GetModelColumn();
385 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
386 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
388 // m_editorCtrl->PopEventHandler( true );
393 //-----------------------------------------------------------------------------
394 // wxDataViewEditorCtrlEvtHandler
395 //-----------------------------------------------------------------------------
397 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
398 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
399 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
400 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
403 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
404 wxControl
*editorCtrl
,
405 wxDataViewRenderer
*owner
)
408 m_editorCtrl
= editorCtrl
;
413 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
417 m_focusOnIdle
= false;
418 if (wxWindow::FindFocus() != m_editorCtrl
)
419 m_editorCtrl
->SetFocus();
425 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
427 switch ( event
.m_keyCode
)
431 m_owner
->FinishEditing();
436 m_owner
->CancelEditing();
444 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
449 m_owner
->FinishEditing();
455 // ---------------------------------------------------------
456 // wxDataViewColumnBase
457 // ---------------------------------------------------------
459 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
461 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
462 wxDataViewRenderer
*renderer
,
463 unsigned int model_column
,
465 wxAlignment
WXUNUSED(align
),
468 m_renderer
= renderer
;
469 m_model_column
= model_column
;
471 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
473 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
474 // parameters inside the native control!
477 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
478 wxDataViewRenderer
*renderer
,
479 unsigned int model_column
,
481 wxAlignment
WXUNUSED(align
),
482 int WXUNUSED(flags
) )
484 m_renderer
= renderer
;
485 m_model_column
= model_column
;
488 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
491 wxDataViewColumnBase::~wxDataViewColumnBase()
497 int wxDataViewColumnBase::GetFlags() const
502 ret
|= wxDATAVIEW_COL_SORTABLE
;
504 ret
|= wxDATAVIEW_COL_RESIZABLE
;
506 ret
|= wxDATAVIEW_COL_HIDDEN
;
511 void wxDataViewColumnBase::SetFlags(int flags
)
513 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
514 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
515 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
518 // ---------------------------------------------------------
519 // wxDataViewCtrlBase
520 // ---------------------------------------------------------
522 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
524 wxDataViewCtrlBase::wxDataViewCtrlBase()
527 m_cols
.DeleteContents( true );
528 m_expander_column
= 0;
532 wxDataViewCtrlBase::~wxDataViewCtrlBase()
534 // IMPORTANT: before calling DecRef() on our model (since it may
535 // result in a free() call), erase all columns (since
536 // they hold a pointer to our model)
546 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
550 m_model
->DecRef(); // discard old model, if any
553 // add our own reference to the new model:
563 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
568 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
569 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
571 return AppendColumn( new wxDataViewColumn( label
,
572 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
573 model_column
, width
, align
, flags
) );
576 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
577 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
579 return AppendColumn( new wxDataViewColumn( label
,
580 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
581 model_column
, width
, align
, flags
) );
584 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
585 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
587 return AppendColumn( new wxDataViewColumn( label
,
588 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
589 model_column
, width
, align
, flags
) );
592 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
593 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
595 return AppendColumn( new wxDataViewColumn( label
,
596 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
597 model_column
, width
, align
, flags
) );
600 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
601 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
603 return AppendColumn( new wxDataViewColumn( label
,
604 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
605 model_column
, width
, align
, flags
) );
608 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
609 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
611 return AppendColumn( new wxDataViewColumn( label
,
612 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
613 model_column
, width
, align
, flags
) );
616 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
617 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
619 return AppendColumn( new wxDataViewColumn( label
,
620 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
621 model_column
, width
, align
, flags
) );
624 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
625 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
627 return AppendColumn( new wxDataViewColumn( label
,
628 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
629 model_column
, width
, align
, flags
) );
632 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
633 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
635 return AppendColumn( new wxDataViewColumn( label
,
636 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
637 model_column
, width
, align
, flags
) );
640 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
641 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
643 return AppendColumn( new wxDataViewColumn( label
,
644 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
645 model_column
, width
, align
, flags
) );
648 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
650 m_cols
.Append( (wxObject
*) col
);
651 col
->SetOwner( (wxDataViewCtrl
*) this );
655 unsigned int wxDataViewCtrlBase::GetColumnCount() const
657 return m_cols
.GetCount();
660 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
665 bool wxDataViewCtrlBase::ClearColumns()
670 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
672 return (wxDataViewColumn
*) m_cols
[ pos
];
675 // ---------------------------------------------------------
677 // ---------------------------------------------------------
679 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
681 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
682 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
683 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
684 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
685 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
687 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
688 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
689 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
690 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
691 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)