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 // ---------------------------------------------------------
30 // wxDataViewListModel
31 // ---------------------------------------------------------
33 wxDataViewModel::wxDataViewModel()
35 m_notifiers
.DeleteContents( true );
39 bool wxDataViewModel::ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
43 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
46 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
47 if (!notifier
->ItemAdded( parent
, item
))
49 node
= node
->GetNext();
55 bool wxDataViewModel::ItemDeleted( const wxDataViewItem
&item
)
59 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
62 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
63 if (!notifier
->ItemDeleted( item
))
65 node
= node
->GetNext();
71 bool wxDataViewModel::ItemChanged( const wxDataViewItem
&item
)
75 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
78 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
79 if (!notifier
->ItemChanged( item
))
81 node
= node
->GetNext();
87 bool wxDataViewModel::ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
91 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
94 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
95 if (!notifier
->ValueChanged( item
, col
))
97 node
= node
->GetNext();
103 bool wxDataViewModel::Cleared()
107 wxList::compatibility_iterator node
= m_notifiers
.GetFirst();
110 wxDataViewModelNotifier
* notifier
= (wxDataViewModelNotifier
*) node
->GetData();
111 if (!notifier
->Cleared())
113 node
= node
->GetNext();
119 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier
*notifier
)
121 m_notifiers
.Append( notifier
);
122 notifier
->SetOwner( this );
125 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier
*notifier
)
127 m_notifiers
.DeleteObject( notifier
);
130 // ---------------------------------------------------------
131 // wxDataViewRendererBase
132 // ---------------------------------------------------------
134 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase
, wxObject
)
136 wxDataViewRendererBase::wxDataViewRendererBase( const wxString
&varianttype
,
137 wxDataViewCellMode
WXUNUSED(mode
),
138 int WXUNUSED(align
) )
140 m_variantType
= varianttype
;
144 const wxDataViewCtrl
* wxDataViewRendererBase::GetView() const
146 return wx_const_cast(wxDataViewRendererBase
*, this)->GetOwner()->GetOwner();
149 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem
&item
, wxRect labelRect
)
151 m_item
= item
; // remember for later
153 unsigned int col
= GetOwner()->GetModelColumn();
155 GetOwner()->GetOwner()->GetModel()->GetValue( value
, item
, col
);
157 m_editorCtrl
= CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect
, value
);
159 wxDataViewEditorCtrlEvtHandler
*handler
=
160 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl
, (wxDataViewRenderer
*) this );
162 m_editorCtrl
->PushEventHandler( handler
);
164 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
165 handler
->SetFocusOnIdle();
167 m_editorCtrl
->SetFocus();
173 void wxDataViewRendererBase::CancelEditing()
175 wxPendingDelete
.Append( m_editorCtrl
);
177 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
179 // m_editorCtrl->PopEventHandler( true );
182 bool wxDataViewRendererBase::FinishEditing()
185 GetValueFromEditorCtrl( m_editorCtrl
, value
);
187 wxPendingDelete
.Append( m_editorCtrl
);
189 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
191 if (!Validate(value
))
194 unsigned int col
= GetOwner()->GetModelColumn();
195 GetOwner()->GetOwner()->GetModel()->SetValue( value
, m_item
, col
);
196 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item
, col
);
198 // m_editorCtrl->PopEventHandler( true );
203 //-----------------------------------------------------------------------------
204 // wxDataViewEditorCtrlEvtHandler
205 //-----------------------------------------------------------------------------
207 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler
, wxEvtHandler
)
208 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar
)
209 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus
)
210 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle
)
213 wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
214 wxControl
*editorCtrl
,
215 wxDataViewRenderer
*owner
)
218 m_editorCtrl
= editorCtrl
;
223 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent
&event
)
227 m_focusOnIdle
= false;
228 if (wxWindow::FindFocus() != m_editorCtrl
)
229 m_editorCtrl
->SetFocus();
235 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent
&event
)
237 switch ( event
.m_keyCode
)
241 m_owner
->FinishEditing();
246 m_owner
->CancelEditing();
254 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent
&event
)
259 m_owner
->FinishEditing();
265 // ---------------------------------------------------------
266 // wxDataViewColumnBase
267 // ---------------------------------------------------------
269 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase
, wxObject
)
271 wxDataViewColumnBase::wxDataViewColumnBase(const wxString
& WXUNUSED(title
),
272 wxDataViewRenderer
*renderer
,
273 unsigned int model_column
,
275 wxAlignment
WXUNUSED(align
),
278 m_renderer
= renderer
;
279 m_model_column
= model_column
;
281 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
283 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
284 // parameters inside the native control!
287 wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap
& bitmap
,
288 wxDataViewRenderer
*renderer
,
289 unsigned int model_column
,
291 wxAlignment
WXUNUSED(align
),
292 int WXUNUSED(flags
) )
294 m_renderer
= renderer
;
295 m_model_column
= model_column
;
298 m_renderer
->SetOwner( (wxDataViewColumn
*) this );
301 wxDataViewColumnBase::~wxDataViewColumnBase()
307 int wxDataViewColumnBase::GetFlags() const
312 ret
|= wxDATAVIEW_COL_SORTABLE
;
314 ret
|= wxDATAVIEW_COL_RESIZABLE
;
316 ret
|= wxDATAVIEW_COL_HIDDEN
;
321 void wxDataViewColumnBase::SetFlags(int flags
)
323 SetSortable((flags
& wxDATAVIEW_COL_SORTABLE
) != 0);
324 SetResizeable((flags
& wxDATAVIEW_COL_RESIZABLE
) != 0);
325 SetHidden((flags
& wxDATAVIEW_COL_HIDDEN
) != 0);
328 // ---------------------------------------------------------
329 // wxDataViewEventModelNotifier
330 // ---------------------------------------------------------
332 class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier
: public wxDataViewModelNotifier
335 wxDataViewEventModelNotifier( wxDataViewCtrl
*ctrl
) { m_ctrl
= ctrl
; }
337 bool SendEvent( wxEventType event_type
, const wxDataViewItem
&item
, unsigned int col
= 0 )
339 wxDataViewEvent
event( event_type
, m_ctrl
->GetId() );
340 event
.SetEventObject( m_ctrl
);
341 event
.SetModel( m_ctrl
->GetModel() );
342 event
.SetItem( item
);
343 event
.SetColumn( col
);
344 m_ctrl
->GetEventHandler()->ProcessEvent( event
);
348 virtual bool ItemAdded( const wxDataViewItem
&parent
, const wxDataViewItem
&item
)
349 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
, item
); }
350 virtual bool ItemDeleted( const wxDataViewItem
&item
)
351 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
, item
); }
352 virtual bool ItemChanged( const wxDataViewItem
&item
)
353 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
, item
); }
354 virtual bool ValueChanged( const wxDataViewItem
&item
, unsigned int col
)
355 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
, item
, col
); }
356 virtual bool Cleared()
357 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
, wxDataViewItem(0) ); }
360 wxDataViewCtrl
*m_ctrl
;
364 // ---------------------------------------------------------
365 // wxDataViewCtrlBase
366 // ---------------------------------------------------------
368 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase
, wxControl
)
370 wxDataViewCtrlBase::wxDataViewCtrlBase()
373 m_cols
.DeleteContents( true );
374 m_eventNotifier
= NULL
;
375 m_expander_column
= 0;
379 wxDataViewCtrlBase::~wxDataViewCtrlBase()
381 // IMPORTANT: before calling DecRef() on our model (since it may
382 // result in a free() call), erase all columns (since
383 // they hold a pointer to our model)
389 m_model
->RemoveNotifier( m_eventNotifier
);
390 m_eventNotifier
= NULL
;
397 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel
*model
)
402 m_model
->RemoveNotifier( m_eventNotifier
);
403 m_eventNotifier
= NULL
;
405 m_model
->DecRef(); // discard old model, if any
408 // add our own reference to the new model:
413 m_eventNotifier
= new wxDataViewEventModelNotifier( (wxDataViewCtrl
*) this );
414 m_model
->AddNotifier( m_eventNotifier
);
420 wxDataViewModel
* wxDataViewCtrlBase::GetModel()
425 bool wxDataViewCtrlBase::AppendTextColumn( const wxString
&label
, unsigned int model_column
,
426 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
428 return AppendColumn( new wxDataViewColumn( label
,
429 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
430 model_column
, width
, align
, flags
) );
433 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString
&label
, unsigned int model_column
,
434 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
436 return AppendColumn( new wxDataViewColumn( label
,
437 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
438 model_column
, width
, align
, flags
) );
441 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString
&label
, unsigned int model_column
,
442 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
444 return AppendColumn( new wxDataViewColumn( label
,
445 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
446 model_column
, width
, align
, flags
) );
449 bool wxDataViewCtrlBase::AppendDateColumn( const wxString
&label
, unsigned int model_column
,
450 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
452 return AppendColumn( new wxDataViewColumn( label
,
453 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
454 model_column
, width
, align
, flags
) );
457 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString
&label
, unsigned int model_column
,
458 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
460 return AppendColumn( new wxDataViewColumn( label
,
461 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
462 model_column
, width
, align
, flags
) );
465 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap
&label
, unsigned int model_column
,
466 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
468 return AppendColumn( new wxDataViewColumn( label
,
469 new wxDataViewTextRenderer( wxT("string"), mode
, (int)align
),
470 model_column
, width
, align
, flags
) );
473 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap
&label
, unsigned int model_column
,
474 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
476 return AppendColumn( new wxDataViewColumn( label
,
477 new wxDataViewToggleRenderer( wxT("bool"), mode
, (int)align
),
478 model_column
, width
, align
, flags
) );
481 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap
&label
, unsigned int model_column
,
482 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
484 return AppendColumn( new wxDataViewColumn( label
,
485 new wxDataViewProgressRenderer( wxEmptyString
, wxT("long"), mode
, (int)align
),
486 model_column
, width
, align
, flags
) );
489 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap
&label
, unsigned int model_column
,
490 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
492 return AppendColumn( new wxDataViewColumn( label
,
493 new wxDataViewDateRenderer( wxT("datetime"), mode
, (int)align
),
494 model_column
, width
, align
, flags
) );
497 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap
&label
, unsigned int model_column
,
498 wxDataViewCellMode mode
, int width
, wxAlignment align
, int flags
)
500 return AppendColumn( new wxDataViewColumn( label
,
501 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode
, (int)align
),
502 model_column
, width
, align
, flags
) );
505 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn
*col
)
507 m_cols
.Append( (wxObject
*) col
);
508 col
->SetOwner( (wxDataViewCtrl
*) this );
512 unsigned int wxDataViewCtrlBase::GetColumnCount() const
514 return m_cols
.GetCount();
517 bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos
) )
522 bool wxDataViewCtrlBase::ClearColumns()
527 wxDataViewColumn
* wxDataViewCtrlBase::GetColumn( unsigned int pos
)
529 return (wxDataViewColumn
*) m_cols
[ pos
];
532 // ---------------------------------------------------------
534 // ---------------------------------------------------------
536 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent
,wxNotifyEvent
)
538 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
)
539 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
)
540 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
)
541 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
)
542 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
)
544 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED
)
545 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED
)
546 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED
)
547 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED
)
548 DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED
)