]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/datavcmn.cpp
Rework the wxCusor ctor taking wx stock number to provide as many cursors as
[wxWidgets.git] / src / common / datavcmn.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/datavcmn.cpp
3// Purpose: wxDataViewCtrl base classes and common parts
4// Author: Robert Roebling
5// Created: 2006/02/20
6// RCS-ID: $Id$
7// Copyright: (c) 2006, Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#if wxUSE_DATAVIEWCTRL
19
20#include "wx/dataview.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/log.h"
24#endif
25
26const wxChar wxDataViewCtrlNameStr[] = wxT("dataviewCtrl");
27
28
29bool operator == (const wxDataViewItem &left, const wxDataViewItem &right)
30{
31 return (left.GetID() == right.GetID() );
32}
33
34
35// ---------------------------------------------------------
36// wxDataViewModel
37// ---------------------------------------------------------
38
39wxDataViewModel::wxDataViewModel()
40{
41 m_notifiers.DeleteContents( true );
42 m_sortingColumn = 0;
43 m_ascending = true;
44}
45
46bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
47{
48 bool ret = true;
49
50 wxList::compatibility_iterator node = m_notifiers.GetFirst();
51 while (node)
52 {
53 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
54 if (!notifier->ItemAdded( parent, item ))
55 ret = false;
56 node = node->GetNext();
57 }
58
59 return ret;
60}
61
62bool wxDataViewModel::ItemDeleted( const wxDataViewItem &item )
63{
64 bool ret = true;
65
66 wxList::compatibility_iterator node = m_notifiers.GetFirst();
67 while (node)
68 {
69 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
70 if (!notifier->ItemDeleted( item ))
71 ret = false;
72 node = node->GetNext();
73 }
74
75 return ret;
76}
77
78bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
79{
80 bool ret = true;
81
82 wxList::compatibility_iterator node = m_notifiers.GetFirst();
83 while (node)
84 {
85 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
86 if (!notifier->ItemChanged( item ))
87 ret = false;
88 node = node->GetNext();
89 }
90
91 return ret;
92}
93
94bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
95{
96 bool ret = true;
97
98 wxList::compatibility_iterator node = m_notifiers.GetFirst();
99 while (node)
100 {
101 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
102 if (!notifier->ValueChanged( item, col ))
103 ret = false;
104 node = node->GetNext();
105 }
106
107 return ret;
108}
109
110bool wxDataViewModel::Cleared()
111{
112 bool ret = true;
113
114 wxList::compatibility_iterator node = m_notifiers.GetFirst();
115 while (node)
116 {
117 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
118 if (!notifier->Cleared())
119 ret = false;
120 node = node->GetNext();
121 }
122
123 return ret;
124}
125
126void wxDataViewModel::Resort()
127{
128 wxList::compatibility_iterator node = m_notifiers.GetFirst();
129 while (node)
130 {
131 wxDataViewModelNotifier* notifier = (wxDataViewModelNotifier*) node->GetData();
132 notifier->Resort();
133 node = node->GetNext();
134 }
135}
136
137void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
138{
139 m_notifiers.Append( notifier );
140 notifier->SetOwner( this );
141}
142
143void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
144{
145 m_notifiers.DeleteObject( notifier );
146}
147
148int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2 )
149{
150 // sort branches before leaves
151 bool item1_has_children = HasChildren(item1);
152 bool item2_has_children = HasChildren(item2);
153
154 if (item1_has_children && !item2_has_children)
155 return 1;
156 if (item2_has_children && !item1_has_children)
157 return -1;
158
159 wxVariant value1,value2;
160 GetValue( value1, item1, m_sortingColumn );
161 GetValue( value2, item2, m_sortingColumn );
162
163 if (!m_ascending)
164 {
165 wxVariant temp = value1;
166 value1 = value2;
167 value2 = temp;
168 }
169
170 if (value1.GetType() == wxT("string"))
171 {
172 wxString str1 = value1.GetString();
173 wxString str2 = value2.GetString();
174 int res = str1.Cmp( str2 );
175 if (res) return res;
176 } else
177 if (value1.GetType() == wxT("long"))
178 {
179 long l1 = value1.GetLong();
180 long l2 = value2.GetLong();
181 long res = l1-l2;
182 if (res) return res;
183 } else
184 if (value1.GetType() == wxT("double"))
185 {
186 double d1 = value1.GetDouble();
187 double d2 = value2.GetDouble();
188 if (d1 < d2) return 1;
189 if (d1 > d2) return -1;
190 } else
191 if (value1.GetType() == wxT("datetime"))
192 {
193 wxDateTime dt1 = value1.GetDateTime();
194 wxDateTime dt2 = value2.GetDateTime();
195 if (dt1.IsEarlierThan(dt2)) return 1;
196 if (dt2.IsEarlierThan(dt1)) return -11;
197 }
198
199 // items must be different
200 unsigned long litem1 = (unsigned long) item1.GetID();
201 unsigned long litem2 = (unsigned long) item2.GetID();
202
203 if (!m_ascending)
204 return litem2-litem1;
205 return litem1-litem2;
206}
207
208// ---------------------------------------------------------
209// wxDataViewRendererBase
210// ---------------------------------------------------------
211
212IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
213
214wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
215 wxDataViewCellMode WXUNUSED(mode),
216 int WXUNUSED(align) )
217{
218 m_variantType = varianttype;
219 m_editorCtrl = NULL;
220}
221
222const wxDataViewCtrl* wxDataViewRendererBase::GetView() const
223{
224 return wx_const_cast(wxDataViewRendererBase*, this)->GetOwner()->GetOwner();
225}
226
227bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
228{
229 m_item = item; // remember for later
230
231 unsigned int col = GetOwner()->GetModelColumn();
232 wxVariant value;
233 GetOwner()->GetOwner()->GetModel()->GetValue( value, item, col );
234
235 m_editorCtrl = CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect, value );
236
237 wxDataViewEditorCtrlEvtHandler *handler =
238 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
239
240 m_editorCtrl->PushEventHandler( handler );
241
242#if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
243 handler->SetFocusOnIdle();
244#else
245 m_editorCtrl->SetFocus();
246#endif
247
248 return true;
249}
250
251void wxDataViewRendererBase::CancelEditing()
252{
253 wxPendingDelete.Append( m_editorCtrl );
254
255 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
256
257 // m_editorCtrl->PopEventHandler( true );
258}
259
260bool wxDataViewRendererBase::FinishEditing()
261{
262 wxVariant value;
263 GetValueFromEditorCtrl( m_editorCtrl, value );
264
265 wxPendingDelete.Append( m_editorCtrl );
266
267 GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
268
269 if (!Validate(value))
270 return false;
271
272 unsigned int col = GetOwner()->GetModelColumn();
273 GetOwner()->GetOwner()->GetModel()->SetValue( value, m_item, col );
274 GetOwner()->GetOwner()->GetModel()->ValueChanged( m_item, col );
275
276 // m_editorCtrl->PopEventHandler( true );
277
278 return true;
279}
280
281//-----------------------------------------------------------------------------
282// wxDataViewEditorCtrlEvtHandler
283//-----------------------------------------------------------------------------
284
285BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
286 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
287 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
288 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
289END_EVENT_TABLE()
290
291wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
292 wxControl *editorCtrl,
293 wxDataViewRenderer *owner )
294{
295 m_owner = owner;
296 m_editorCtrl = editorCtrl;
297
298 m_finished = false;
299}
300
301void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
302{
303 if (m_focusOnIdle)
304 {
305 m_focusOnIdle = false;
306 if (wxWindow::FindFocus() != m_editorCtrl)
307 m_editorCtrl->SetFocus();
308 }
309
310 event.Skip();
311}
312
313void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
314{
315 switch ( event.m_keyCode )
316 {
317 case WXK_RETURN:
318 m_finished = true;
319 m_owner->FinishEditing();
320 break;
321
322 case WXK_ESCAPE:
323 m_finished = true;
324 m_owner->CancelEditing();
325 break;
326
327 default:
328 event.Skip();
329 }
330}
331
332void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
333{
334 if (!m_finished)
335 {
336 m_finished = true;
337 m_owner->FinishEditing();
338 }
339
340 event.Skip();
341}
342
343// ---------------------------------------------------------
344// wxDataViewColumnBase
345// ---------------------------------------------------------
346
347IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumnBase, wxObject)
348
349wxDataViewColumnBase::wxDataViewColumnBase(const wxString& WXUNUSED(title),
350 wxDataViewRenderer *renderer,
351 unsigned int model_column,
352 int WXUNUSED(width),
353 wxAlignment WXUNUSED(align),
354 int WXUNUSED(flags))
355{
356 m_renderer = renderer;
357 m_model_column = model_column;
358 m_owner = NULL;
359 m_renderer->SetOwner( (wxDataViewColumn*) this );
360
361 // NOTE: the wxDataViewColumn's ctor must store the width, align, flags
362 // parameters inside the native control!
363}
364
365wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap& bitmap,
366 wxDataViewRenderer *renderer,
367 unsigned int model_column,
368 int WXUNUSED(width),
369 wxAlignment WXUNUSED(align),
370 int WXUNUSED(flags) )
371{
372 m_renderer = renderer;
373 m_model_column = model_column;
374 m_bitmap = bitmap;
375 m_owner = NULL;
376 m_renderer->SetOwner( (wxDataViewColumn*) this );
377}
378
379wxDataViewColumnBase::~wxDataViewColumnBase()
380{
381 if (m_renderer)
382 delete m_renderer;
383}
384
385int wxDataViewColumnBase::GetFlags() const
386{
387 int ret = 0;
388
389 if (IsSortable())
390 ret |= wxDATAVIEW_COL_SORTABLE;
391 if (IsResizeable())
392 ret |= wxDATAVIEW_COL_RESIZABLE;
393 if (IsHidden())
394 ret |= wxDATAVIEW_COL_HIDDEN;
395
396 return ret;
397}
398
399void wxDataViewColumnBase::SetFlags(int flags)
400{
401 SetSortable((flags & wxDATAVIEW_COL_SORTABLE) != 0);
402 SetResizeable((flags & wxDATAVIEW_COL_RESIZABLE) != 0);
403 SetHidden((flags & wxDATAVIEW_COL_HIDDEN) != 0);
404}
405
406// ---------------------------------------------------------
407// wxDataViewEventModelNotifier
408// ---------------------------------------------------------
409
410class WXDLLIMPEXP_ADV wxDataViewEventModelNotifier: public wxDataViewModelNotifier
411{
412public:
413 wxDataViewEventModelNotifier( wxDataViewCtrl *ctrl ) { m_ctrl = ctrl; }
414
415 bool SendEvent( wxEventType event_type, const wxDataViewItem &item, unsigned int col = 0 )
416 {
417 wxDataViewEvent event( event_type, m_ctrl->GetId() );
418 event.SetEventObject( m_ctrl );
419 event.SetModel( m_ctrl->GetModel() );
420 event.SetItem( item );
421 event.SetColumn( col );
422 m_ctrl->GetEventHandler()->ProcessEvent( event );
423 return true;
424 }
425
426 virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
427 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED, item ); }
428 virtual bool ItemDeleted( const wxDataViewItem &item )
429 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED, item ); }
430 virtual bool ItemChanged( const wxDataViewItem &item )
431 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED, item ); }
432 virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col )
433 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED, item, col ); }
434 virtual bool Cleared()
435 { return SendEvent( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED, wxDataViewItem(0) ); }
436
437private:
438 wxDataViewCtrl *m_ctrl;
439};
440
441
442// ---------------------------------------------------------
443// wxDataViewCtrlBase
444// ---------------------------------------------------------
445
446IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
447
448wxDataViewCtrlBase::wxDataViewCtrlBase()
449{
450 m_model = NULL;
451 m_cols.DeleteContents( true );
452 m_eventNotifier = NULL;
453 m_expander_column = 0;
454 m_indent = 8;
455}
456
457wxDataViewCtrlBase::~wxDataViewCtrlBase()
458{
459 // IMPORTANT: before calling DecRef() on our model (since it may
460 // result in a free() call), erase all columns (since
461 // they hold a pointer to our model)
462 m_cols.Clear();
463
464 if (m_model)
465 {
466 if (m_eventNotifier)
467 m_model->RemoveNotifier( m_eventNotifier );
468 m_eventNotifier = NULL;
469
470 m_model->DecRef();
471 m_model = NULL;
472 }
473}
474
475bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
476{
477 if (m_model)
478 {
479 if (m_eventNotifier)
480 m_model->RemoveNotifier( m_eventNotifier );
481 m_eventNotifier = NULL;
482
483 m_model->DecRef(); // discard old model, if any
484 }
485
486 // add our own reference to the new model:
487 m_model = model;
488 if (m_model)
489 {
490 m_model->IncRef();
491 m_eventNotifier = new wxDataViewEventModelNotifier( (wxDataViewCtrl*) this );
492 m_model->AddNotifier( m_eventNotifier );
493 }
494
495 return true;
496}
497
498wxDataViewModel* wxDataViewCtrlBase::GetModel()
499{
500 return m_model;
501}
502
503bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
504 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
505{
506 return AppendColumn( new wxDataViewColumn( label,
507 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
508 model_column, width, align, flags ) );
509}
510
511bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
512 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
513{
514 return AppendColumn( new wxDataViewColumn( label,
515 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
516 model_column, width, align, flags ) );
517}
518
519bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
520 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
521{
522 return AppendColumn( new wxDataViewColumn( label,
523 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
524 model_column, width, align, flags ) );
525}
526
527bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
528 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
529{
530 return AppendColumn( new wxDataViewColumn( label,
531 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
532 model_column, width, align, flags ) );
533}
534
535bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
536 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
537{
538 return AppendColumn( new wxDataViewColumn( label,
539 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
540 model_column, width, align, flags ) );
541}
542
543bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
544 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
545{
546 return AppendColumn( new wxDataViewColumn( label,
547 new wxDataViewTextRenderer( wxT("string"), mode, (int)align ),
548 model_column, width, align, flags ) );
549}
550
551bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
552 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
553{
554 return AppendColumn( new wxDataViewColumn( label,
555 new wxDataViewToggleRenderer( wxT("bool"), mode, (int)align ),
556 model_column, width, align, flags ) );
557}
558
559bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
560 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
561{
562 return AppendColumn( new wxDataViewColumn( label,
563 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode, (int)align ),
564 model_column, width, align, flags ) );
565}
566
567bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
568 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
569{
570 return AppendColumn( new wxDataViewColumn( label,
571 new wxDataViewDateRenderer( wxT("datetime"), mode, (int)align ),
572 model_column, width, align, flags ) );
573}
574
575bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
576 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
577{
578 return AppendColumn( new wxDataViewColumn( label,
579 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode, (int)align ),
580 model_column, width, align, flags ) );
581}
582
583bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
584{
585 m_cols.Append( (wxObject*) col );
586 col->SetOwner( (wxDataViewCtrl*) this );
587 return true;
588}
589
590unsigned int wxDataViewCtrlBase::GetColumnCount() const
591{
592 return m_cols.GetCount();
593}
594
595bool wxDataViewCtrlBase::DeleteColumn( unsigned int WXUNUSED(pos) )
596{
597 return false;
598}
599
600bool wxDataViewCtrlBase::ClearColumns()
601{
602 return false;
603}
604
605wxDataViewColumn* wxDataViewCtrlBase::GetColumn( unsigned int pos )
606{
607 return (wxDataViewColumn*) m_cols[ pos ];
608}
609
610// ---------------------------------------------------------
611// wxDataViewEvent
612// ---------------------------------------------------------
613
614IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
615
616DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED)
617DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED)
618DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK)
619DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK)
620DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED)
621
622DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED)
623DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED)
624DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED)
625DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED)
626DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED)
627
628#endif