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 );
45 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
49 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
52 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
53 if (!notifier
->ItemAdded( parent
, item
))
55 node
= node
->GetNext();
61 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&item
)
65 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
68 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
69 if (!notifier
->ItemDeleted( item
))
71 node
= node
->GetNext();
77 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
81 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
84 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
85 if (!notifier
->ItemChanged( item
))
87 node
= node
->GetNext();
93 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
97 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
100 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
101 if (!notifier
->ValueChanged( item
, col
))
103 node
= node
->GetNext();
109 bool wxDataViewModel::Cleared()
113 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
116 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
117 if (!notifier
->Cleared())
119 node
= node
->GetNext();
125 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
127 m_notifiers
.Append( notifier
);
128 notifier
->SetOwner( this );
131 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
133 m_notifiers
.DeleteObject( notifier
);
136 // ---------------------------------------------------------
137 // wxDataViewRendererBase
138 // ---------------------------------------------------------
140 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
142 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
143 wxDataViewCellMode
WXUNUSED(mode
),
144 int WXUNUSED(align
) )
146 m_variantType
= varianttype
;
150 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
152 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
155 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
157 m_item
= item
; // remember for later
159 unsigned int col
= GetOwner()->GetModelColumn();
161 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
163 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
165 wxDataViewEditorCtrlEvtHandler
*handler
=
166 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
168 m_editorCtrl
->PushEventHandler( handler
);
170 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
171 handler
->SetFocusOnIdle();
173 m_editorCtrl
->SetFocus();
179 void wxDataViewRendererBase::CancelEditing()
181 wxPendingDelete
.Append( m_editorCtrl
);
183 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
185 // m_editorCtrl->PopEventHandler( true );
188 bool wxDataViewRendererBase::FinishEditing()
191 GetValueFromEditorCtrl( m_editorCtrl
, value
);
193 wxPendingDelete
.Append( m_editorCtrl
);
195 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
197 if (!Validate(value
))
200 unsigned int col
= GetOwner()->GetModelColumn();
201 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
202 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
204 // m_editorCtrl->PopEventHandler( true );
209 //-----------------------------------------------------------------------------
210 // wxDataViewEditorCtrlEvtHandler
211 //-----------------------------------------------------------------------------
213 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
214 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
215 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
216 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
219 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
220 wxControl
*editorCtrl
,
221 wxDataViewRenderer
*owner
)
224 m_editorCtrl
= editorCtrl
;
229 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
233 m_focusOnIdle
= false;
234 if (wxWindow::FindFocus() != m_editorCtrl
)
235 m_editorCtrl
->SetFocus();
241 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
243 switch ( event
.m_keyCode
)
247 m_owner
->FinishEditing();
252 m_owner
->CancelEditing();
260 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
265 m_owner
->FinishEditing();
271 // ---------------------------------------------------------
272 // wxDataViewColumnBase
273 // ---------------------------------------------------------
275 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
277 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
278 wxDataViewRenderer
*renderer
,
279 unsigned int model_column
,
281 wxAlignment
WXUNUSED(align
),
284 m_renderer
= renderer
;
285 m_model_column
= model_column
;
287 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
289 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
290 // parameters inside the native control!
293 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
294 wxDataViewRenderer
*renderer
,
295 unsigned int model_column
,
297 wxAlignment
WXUNUSED(align
),
298 int WXUNUSED(flags
) )
300 m_renderer
= renderer
;
301 m_model_column
= model_column
;
304 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
307 wxDataViewColumnBase::~wxDataViewColumnBase()
313 int wxDataViewColumnBase::GetFlags() const
318 ret
|= wxDATAVIEW_COL_SORTABLE
;
320 ret
|= wxDATAVIEW_COL_RESIZABLE
;
322 ret
|= wxDATAVIEW_COL_HIDDEN
;
327 void wxDataViewColumnBase::SetFlags(int flags
)
329 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
330 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
331 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
334 // ---------------------------------------------------------
335 // wxDataViewEventModelNotifier
336 // ---------------------------------------------------------
338 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
341 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
343 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
345 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
346 event
.SetEventObject( m_ctrl
);
347 event
.SetModel( m_ctrl
->GetModel() );
348 event
.SetItem( item
);
349 event
.SetColumn( col
);
350 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
354 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
355 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
356 virtual bool ItemDeleted( const wxDataViewItem
&item
)
357 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
358 virtual bool ItemChanged( const wxDataViewItem
&item
)
359 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
360 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
361 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
362 virtual bool Cleared()
363 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
366 wxDataViewCtrl
*m_ctrl
;
370 // ---------------------------------------------------------
371 // wxDataViewCtrlBase
372 // ---------------------------------------------------------
374 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
376 wxDataViewCtrlBase::wxDataViewCtrlBase()
379 m_cols
.DeleteContents( true );
380 m_eventNotifier
= NULL
;
381 m_expander_column
= 0;
385 wxDataViewCtrlBase::~wxDataViewCtrlBase()
387 // IMPORTANT: before calling DecRef() on our model (since it may
388 // result in a free() call), erase all columns (since
389 // they hold a pointer to our model)
395 m_model
->RemoveNotifier( m_eventNotifier
);
396 m_eventNotifier
= NULL
;
403 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
408 m_model
->RemoveNotifier( m_eventNotifier
);
409 m_eventNotifier
= NULL
;
411 m_model
->DecRef(); // discard old model, if any
414 // add our own reference to the new model:
419 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
420 m_model
->AddNotifier( m_eventNotifier
);
426 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
431 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
432 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
434 return AppendColumn( new wxDataViewColumn( label
,
435 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
436 model_column
, width
, align
, flags
) );
439 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
440 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
442 return AppendColumn( new wxDataViewColumn( label
,
443 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
444 model_column
, width
, align
, flags
) );
447 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
448 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
450 return AppendColumn( new wxDataViewColumn( label
,
451 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
452 model_column
, width
, align
, flags
) );
455 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
456 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
458 return AppendColumn( new wxDataViewColumn( label
,
459 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
460 model_column
, width
, align
, flags
) );
463 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
464 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
466 return AppendColumn( new wxDataViewColumn( label
,
467 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
468 model_column
, width
, align
, flags
) );
471 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
472 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
474 return AppendColumn( new wxDataViewColumn( label
,
475 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
476 model_column
, width
, align
, flags
) );
479 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
480 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
482 return AppendColumn( new wxDataViewColumn( label
,
483 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
484 model_column
, width
, align
, flags
) );
487 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
488 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
490 return AppendColumn( new wxDataViewColumn( label
,
491 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
492 model_column
, width
, align
, flags
) );
495 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
496 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
498 return AppendColumn( new wxDataViewColumn( label
,
499 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
500 model_column
, width
, align
, flags
) );
503 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
504 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
506 return AppendColumn( new wxDataViewColumn( label
,
507 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
508 model_column
, width
, align
, flags
) );
511 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
513 m_cols
.Append( (wxObject
*) col
);
514 col
->SetOwner( (wxDataViewCtrl
*) this );
518 unsigned int wxDataViewCtrlBase::GetColumnCount() const
520 return m_cols
.GetCount();
523 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
528 bool wxDataViewCtrlBase::ClearColumns()
533 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
535 return (wxDataViewColumn
*) m_cols
[ pos
];
538 // ---------------------------------------------------------
540 // ---------------------------------------------------------
542 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
544 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
545 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
546 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
547 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
548 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
550 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
551 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
552 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
553 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
554 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)