Fix destruction of wxDataViewCtrl's editor control.
[wxWidgets.git] / src / common / datavcmn.cpp
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/dc.h"
24 #include "wx/settings.h"
25 #include "wx/log.h"
26 #include "wx/crt.h"
27 #endif
28
29 #include "wx/datectrl.h"
30 #include "wx/spinctrl.h"
31 #include "wx/choice.h"
32 #include "wx/imaglist.h"
33
34 const char wxDataViewCtrlNameStr[] = "dataviewCtrl";
35
36 namespace
37 {
38
39 // Custom handler pushed on top of the edit control used by wxDataViewCtrl to
40 // forward some events to the main control itself.
41 class wxDataViewEditorCtrlEvtHandler: public wxEvtHandler
42 {
43 public:
44 wxDataViewEditorCtrlEvtHandler(wxWindow *editor, wxDataViewRenderer *owner)
45 {
46 m_editorCtrl = editor;
47 m_owner = owner;
48
49 m_finished = false;
50 }
51
52 void AcceptChangesAndFinish();
53 void SetFocusOnIdle( bool focus = true ) { m_focusOnIdle = focus; }
54
55 protected:
56 void OnChar( wxKeyEvent &event );
57 void OnTextEnter( wxCommandEvent &event );
58 void OnKillFocus( wxFocusEvent &event );
59 void OnIdle( wxIdleEvent &event );
60
61 private:
62 wxDataViewRenderer *m_owner;
63 wxWindow *m_editorCtrl;
64 bool m_finished;
65 bool m_focusOnIdle;
66
67 private:
68 DECLARE_EVENT_TABLE()
69 };
70
71 } // anonymous namespace
72
73 // ---------------------------------------------------------
74 // wxDataViewItemAttr
75 // ---------------------------------------------------------
76
77 wxFont wxDataViewItemAttr::GetEffectiveFont(const wxFont& font) const
78 {
79 if ( !HasFont() )
80 return font;
81
82 wxFont f(font);
83 if ( GetBold() )
84 f.MakeBold();
85 if ( GetItalic() )
86 f.MakeItalic();
87 return f;
88 }
89
90
91 // ---------------------------------------------------------
92 // wxDataViewModelNotifier
93 // ---------------------------------------------------------
94
95 #include "wx/listimpl.cpp"
96 WX_DEFINE_LIST(wxDataViewModelNotifiers)
97
98 bool wxDataViewModelNotifier::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
99 {
100 size_t count = items.GetCount();
101 size_t i;
102 for (i = 0; i < count; i++)
103 if (!ItemAdded( parent, items[i] )) return false;
104
105 return true;
106 }
107
108 bool wxDataViewModelNotifier::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
109 {
110 size_t count = items.GetCount();
111 size_t i;
112 for (i = 0; i < count; i++)
113 if (!ItemDeleted( parent, items[i] )) return false;
114
115 return true;
116 }
117
118 bool wxDataViewModelNotifier::ItemsChanged( const wxDataViewItemArray &items )
119 {
120 size_t count = items.GetCount();
121 size_t i;
122 for (i = 0; i < count; i++)
123 if (!ItemChanged( items[i] )) return false;
124
125 return true;
126 }
127
128 // ---------------------------------------------------------
129 // wxDataViewModel
130 // ---------------------------------------------------------
131
132 wxDataViewModel::wxDataViewModel()
133 {
134 m_notifiers.DeleteContents( true );
135 }
136
137 bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
138 {
139 bool ret = true;
140
141 wxDataViewModelNotifiers::iterator iter;
142 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
143 {
144 wxDataViewModelNotifier* notifier = *iter;
145 if (!notifier->ItemAdded( parent, item ))
146 ret = false;
147 }
148
149 return ret;
150 }
151
152 bool wxDataViewModel::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
153 {
154 bool ret = true;
155
156 wxDataViewModelNotifiers::iterator iter;
157 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
158 {
159 wxDataViewModelNotifier* notifier = *iter;
160 if (!notifier->ItemDeleted( parent, item ))
161 ret = false;
162 }
163
164 return ret;
165 }
166
167 bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
168 {
169 bool ret = true;
170
171 wxDataViewModelNotifiers::iterator iter;
172 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
173 {
174 wxDataViewModelNotifier* notifier = *iter;
175 if (!notifier->ItemChanged( item ))
176 ret = false;
177 }
178
179 return ret;
180 }
181
182 bool wxDataViewModel::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
183 {
184 bool ret = true;
185
186 wxDataViewModelNotifiers::iterator iter;
187 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
188 {
189 wxDataViewModelNotifier* notifier = *iter;
190 if (!notifier->ItemsAdded( parent, items ))
191 ret = false;
192 }
193
194 return ret;
195 }
196
197 bool wxDataViewModel::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
198 {
199 bool ret = true;
200
201 wxDataViewModelNotifiers::iterator iter;
202 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
203 {
204 wxDataViewModelNotifier* notifier = *iter;
205 if (!notifier->ItemsDeleted( parent, items ))
206 ret = false;
207 }
208
209 return ret;
210 }
211
212 bool wxDataViewModel::ItemsChanged( const wxDataViewItemArray &items )
213 {
214 bool ret = true;
215
216 wxDataViewModelNotifiers::iterator iter;
217 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
218 {
219 wxDataViewModelNotifier* notifier = *iter;
220 if (!notifier->ItemsChanged( items ))
221 ret = false;
222 }
223
224 return ret;
225 }
226
227 bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
228 {
229 bool ret = true;
230
231 wxDataViewModelNotifiers::iterator iter;
232 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
233 {
234 wxDataViewModelNotifier* notifier = *iter;
235 if (!notifier->ValueChanged( item, col ))
236 ret = false;
237 }
238
239 return ret;
240 }
241
242 bool wxDataViewModel::Cleared()
243 {
244 bool ret = true;
245
246 wxDataViewModelNotifiers::iterator iter;
247 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
248 {
249 wxDataViewModelNotifier* notifier = *iter;
250 if (!notifier->Cleared())
251 ret = false;
252 }
253
254 return ret;
255 }
256
257 bool wxDataViewModel::BeforeReset()
258 {
259 bool ret = true;
260
261 wxDataViewModelNotifiers::iterator iter;
262 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
263 {
264 wxDataViewModelNotifier* notifier = *iter;
265 if (!notifier->BeforeReset())
266 ret = false;
267 }
268
269 return ret;
270 }
271
272 bool wxDataViewModel::AfterReset()
273 {
274 bool ret = true;
275
276 wxDataViewModelNotifiers::iterator iter;
277 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
278 {
279 wxDataViewModelNotifier* notifier = *iter;
280 if (!notifier->AfterReset())
281 ret = false;
282 }
283
284 return ret;
285 }
286
287 void wxDataViewModel::Resort()
288 {
289 wxDataViewModelNotifiers::iterator iter;
290 for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
291 {
292 wxDataViewModelNotifier* notifier = *iter;
293 notifier->Resort();
294 }
295 }
296
297 void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
298 {
299 m_notifiers.push_back( notifier );
300 notifier->SetOwner( this );
301 }
302
303 void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
304 {
305 m_notifiers.DeleteObject( notifier );
306 }
307
308 int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
309 unsigned int column, bool ascending ) const
310 {
311 // sort branches before leaves
312 bool item1_is_container = IsContainer(item1);
313 bool item2_is_container = IsContainer(item2);
314
315 if (item1_is_container && !item2_is_container)
316 return 1;
317 if (item2_is_container && !item1_is_container)
318 return -1;
319
320 wxVariant value1,value2;
321 GetValue( value1, item1, column );
322 GetValue( value2, item2, column );
323
324 if (!ascending)
325 {
326 wxVariant temp = value1;
327 value1 = value2;
328 value2 = temp;
329 }
330
331 if (value1.GetType() == wxT("string"))
332 {
333 wxString str1 = value1.GetString();
334 wxString str2 = value2.GetString();
335 int res = str1.Cmp( str2 );
336 if (res)
337 return res;
338 }
339 else if (value1.GetType() == wxT("long"))
340 {
341 long l1 = value1.GetLong();
342 long l2 = value2.GetLong();
343 long res = l1-l2;
344 if (res)
345 return res;
346 }
347 else if (value1.GetType() == wxT("double"))
348 {
349 double d1 = value1.GetDouble();
350 double d2 = value2.GetDouble();
351 if (d1 < d2)
352 return 1;
353 if (d1 > d2)
354 return -1;
355 }
356 else if (value1.GetType() == wxT("datetime"))
357 {
358 wxDateTime dt1 = value1.GetDateTime();
359 wxDateTime dt2 = value2.GetDateTime();
360 if (dt1.IsEarlierThan(dt2))
361 return 1;
362 if (dt2.IsEarlierThan(dt1))
363 return -1;
364 }
365
366 // items must be different
367 wxUIntPtr id1 = wxPtrToUInt(item1.GetID()),
368 id2 = wxPtrToUInt(item2.GetID());
369
370 return ascending ? id1 - id2 : id2 - id1;
371 }
372
373 // ---------------------------------------------------------
374 // wxDataViewIndexListModel
375 // ---------------------------------------------------------
376
377 static int my_sort( int *v1, int *v2 )
378 {
379 return *v2-*v1;
380 }
381
382
383 wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size )
384 {
385 // IDs are ordered until an item gets deleted or inserted
386 m_ordered = true;
387
388 // build initial index
389 unsigned int i;
390 for (i = 1; i < initial_size+1; i++)
391 m_hash.Add( wxDataViewItem(wxUIntToPtr(i)) );
392 m_nextFreeID = initial_size + 1;
393 }
394
395 void wxDataViewIndexListModel::Reset( unsigned int new_size )
396 {
397 /* wxDataViewModel:: */ BeforeReset();
398
399 m_hash.Clear();
400
401 // IDs are ordered until an item gets deleted or inserted
402 m_ordered = true;
403
404 // build initial index
405 unsigned int i;
406 for (i = 1; i < new_size+1; i++)
407 m_hash.Add( wxDataViewItem(wxUIntToPtr(i)) );
408
409 m_nextFreeID = new_size + 1;
410
411 /* wxDataViewModel:: */ AfterReset();
412 }
413
414 void wxDataViewIndexListModel::RowPrepended()
415 {
416 m_ordered = false;
417
418 unsigned int id = m_nextFreeID;
419 m_nextFreeID++;
420
421 wxDataViewItem item( wxUIntToPtr(id) );
422 m_hash.Insert( item, 0 );
423 ItemAdded( wxDataViewItem(0), item );
424
425 }
426
427 void wxDataViewIndexListModel::RowInserted( unsigned int before )
428 {
429 m_ordered = false;
430
431 unsigned int id = m_nextFreeID;
432 m_nextFreeID++;
433
434 wxDataViewItem item( wxUIntToPtr(id) );
435 m_hash.Insert( item, before );
436 ItemAdded( wxDataViewItem(0), item );
437 }
438
439 void wxDataViewIndexListModel::RowAppended()
440 {
441 unsigned int id = m_nextFreeID;
442 m_nextFreeID++;
443
444 wxDataViewItem item( wxUIntToPtr(id) );
445 m_hash.Add( item );
446 ItemAdded( wxDataViewItem(0), item );
447 }
448
449 void wxDataViewIndexListModel::RowDeleted( unsigned int row )
450 {
451 m_ordered = false;
452
453 wxDataViewItem item( m_hash[row] );
454 m_hash.RemoveAt( row );
455 /* wxDataViewModel:: */ ItemDeleted( wxDataViewItem(0), item );
456 }
457
458 void wxDataViewIndexListModel::RowsDeleted( const wxArrayInt &rows )
459 {
460 m_ordered = false;
461
462 wxDataViewItemArray array;
463 unsigned int i;
464 for (i = 0; i < rows.GetCount(); i++)
465 {
466 wxDataViewItem item( m_hash[rows[i]] );
467 array.Add( item );
468 }
469
470 wxArrayInt sorted = rows;
471 sorted.Sort( my_sort );
472 for (i = 0; i < sorted.GetCount(); i++)
473 m_hash.RemoveAt( sorted[i] );
474
475 /* wxDataViewModel:: */ ItemsDeleted( wxDataViewItem(0), array );
476 }
477
478 void wxDataViewIndexListModel::RowChanged( unsigned int row )
479 {
480 /* wxDataViewModel:: */ ItemChanged( GetItem(row) );
481 }
482
483 void wxDataViewIndexListModel::RowValueChanged( unsigned int row, unsigned int col )
484 {
485 /* wxDataViewModel:: */ ValueChanged( GetItem(row), col );
486 }
487
488 unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem &item ) const
489 {
490 if (m_ordered)
491 return wxPtrToUInt(item.GetID())-1;
492
493 // assert for not found
494 return (unsigned int) m_hash.Index( item );
495 }
496
497 wxDataViewItem wxDataViewIndexListModel::GetItem( unsigned int row ) const
498 {
499 wxASSERT( row < m_hash.GetCount() );
500 return wxDataViewItem( m_hash[row] );
501 }
502
503 unsigned int wxDataViewIndexListModel::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
504 {
505 if (item.IsOk())
506 return 0;
507
508 children = m_hash;
509
510 return m_hash.GetCount();
511 }
512
513 // ---------------------------------------------------------
514 // wxDataViewVirtualListModel
515 // ---------------------------------------------------------
516
517 #ifndef __WXMAC__
518
519 wxDataViewVirtualListModel::wxDataViewVirtualListModel( unsigned int initial_size )
520 {
521 m_size = initial_size;
522 }
523
524 void wxDataViewVirtualListModel::Reset( unsigned int new_size )
525 {
526 /* wxDataViewModel:: */ BeforeReset();
527
528 m_size = new_size;
529
530 /* wxDataViewModel:: */ AfterReset();
531 }
532
533 void wxDataViewVirtualListModel::RowPrepended()
534 {
535 m_size++;
536 wxDataViewItem item( wxUIntToPtr(1) );
537 ItemAdded( wxDataViewItem(0), item );
538 }
539
540 void wxDataViewVirtualListModel::RowInserted( unsigned int before )
541 {
542 m_size++;
543 wxDataViewItem item( wxUIntToPtr(before+1) );
544 ItemAdded( wxDataViewItem(0), item );
545 }
546
547 void wxDataViewVirtualListModel::RowAppended()
548 {
549 m_size++;
550 wxDataViewItem item( wxUIntToPtr(m_size) );
551 ItemAdded( wxDataViewItem(0), item );
552 }
553
554 void wxDataViewVirtualListModel::RowDeleted( unsigned int row )
555 {
556 m_size--;
557 wxDataViewItem item( wxUIntToPtr(row+1) );
558 /* wxDataViewModel:: */ ItemDeleted( wxDataViewItem(0), item );
559 }
560
561 void wxDataViewVirtualListModel::RowsDeleted( const wxArrayInt &rows )
562 {
563 m_size -= rows.GetCount();
564
565 wxArrayInt sorted = rows;
566 sorted.Sort( my_sort );
567
568 wxDataViewItemArray array;
569 unsigned int i;
570 for (i = 0; i < sorted.GetCount(); i++)
571 {
572 wxDataViewItem item( wxUIntToPtr(sorted[i]+1) );
573 array.Add( item );
574 }
575 /* wxDataViewModel:: */ ItemsDeleted( wxDataViewItem(0), array );
576 }
577
578 void wxDataViewVirtualListModel::RowChanged( unsigned int row )
579 {
580 /* wxDataViewModel:: */ ItemChanged( GetItem(row) );
581 }
582
583 void wxDataViewVirtualListModel::RowValueChanged( unsigned int row, unsigned int col )
584 {
585 /* wxDataViewModel:: */ ValueChanged( GetItem(row), col );
586 }
587
588 unsigned int wxDataViewVirtualListModel::GetRow( const wxDataViewItem &item ) const
589 {
590 return wxPtrToUInt( item.GetID() ) -1;
591 }
592
593 wxDataViewItem wxDataViewVirtualListModel::GetItem( unsigned int row ) const
594 {
595 return wxDataViewItem( wxUIntToPtr(row+1) );
596 }
597
598 bool wxDataViewVirtualListModel::HasDefaultCompare() const
599 {
600 return true;
601 }
602
603 int wxDataViewVirtualListModel::Compare(const wxDataViewItem& item1,
604 const wxDataViewItem& item2,
605 unsigned int WXUNUSED(column),
606 bool ascending) const
607 {
608 unsigned int pos1 = wxPtrToUInt(item1.GetID()); // -1 not needed here
609 unsigned int pos2 = wxPtrToUInt(item2.GetID()); // -1 not needed here
610
611 if (ascending)
612 return pos1 - pos2;
613 else
614 return pos2 - pos1;
615 }
616
617 unsigned int wxDataViewVirtualListModel::GetChildren( const wxDataViewItem &WXUNUSED(item), wxDataViewItemArray &WXUNUSED(children) ) const
618 {
619 return 0; // should we report an error ?
620 }
621
622 #endif // __WXMAC__
623
624 //-----------------------------------------------------------------------------
625 // wxDataViewIconText
626 //-----------------------------------------------------------------------------
627
628 IMPLEMENT_DYNAMIC_CLASS(wxDataViewIconText,wxObject)
629
630 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxDataViewIconText, WXDLLIMPEXP_ADV)
631
632 // ---------------------------------------------------------
633 // wxDataViewRendererBase
634 // ---------------------------------------------------------
635
636 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
637
638 wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
639 wxDataViewCellMode WXUNUSED(mode),
640 int WXUNUSED(align) )
641 {
642 m_variantType = varianttype;
643 m_owner = NULL;
644 }
645
646 wxDataViewRendererBase::~wxDataViewRendererBase()
647 {
648 if ( m_editorCtrl )
649 DestroyEditControl();
650 }
651
652 wxDataViewCtrl* wxDataViewRendererBase::GetView() const
653 {
654 return const_cast<wxDataViewRendererBase*>(this)->GetOwner()->GetOwner();
655 }
656
657 bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
658 {
659 wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
660
661 // Before doing anything we send an event asking if editing of this item is really wanted.
662 wxDataViewEvent start_event( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, dv_ctrl->GetId() );
663 start_event.SetDataViewColumn( GetOwner() );
664 start_event.SetModel( dv_ctrl->GetModel() );
665 start_event.SetItem( item );
666 start_event.SetEventObject( dv_ctrl );
667 dv_ctrl->GetEventHandler()->ProcessEvent( start_event );
668 if( !start_event.IsAllowed() )
669 return false;
670
671 m_item = item; // remember for later
672
673 unsigned int col = GetOwner()->GetModelColumn();
674 wxVariant value;
675 dv_ctrl->GetModel()->GetValue( value, item, col );
676
677 m_editorCtrl = CreateEditorCtrl( dv_ctrl->GetMainWindow(), labelRect, value );
678
679 // there might be no editor control for the given item
680 if(!m_editorCtrl)
681 return false;
682
683 wxDataViewEditorCtrlEvtHandler *handler =
684 new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
685
686 m_editorCtrl->PushEventHandler( handler );
687
688 #if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
689 handler->SetFocusOnIdle();
690 #else
691 m_editorCtrl->SetFocus();
692 #endif
693
694 // Now we should send Editing Started event
695 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv_ctrl->GetId() );
696 event.SetDataViewColumn( GetOwner() );
697 event.SetModel( dv_ctrl->GetModel() );
698 event.SetItem( item );
699 event.SetEventObject( dv_ctrl );
700 dv_ctrl->GetEventHandler()->ProcessEvent( event );
701
702 return true;
703 }
704
705 void wxDataViewRendererBase::DestroyEditControl()
706 {
707 // Remove our event handler first to prevent it from (recursively) calling
708 // us again as it would do via a call to FinishEditing() when the editor
709 // loses focus when we hide it below.
710 wxEvtHandler * const handler = m_editorCtrl->PopEventHandler();
711
712 // Hide the control immediately but don't delete it yet as there could be
713 // some pending messages for it.
714 m_editorCtrl->Hide();
715
716 wxPendingDelete.Append(handler);
717 wxPendingDelete.Append(m_editorCtrl);
718
719 // Ensure that DestroyEditControl() is not called again for this control.
720 m_editorCtrl.Release();
721 }
722
723 void wxDataViewRendererBase::CancelEditing()
724 {
725 if (!m_editorCtrl)
726 return;
727
728 DestroyEditControl();
729 }
730
731 bool wxDataViewRendererBase::FinishEditing()
732 {
733 if (!m_editorCtrl)
734 return true;
735
736 wxVariant value;
737 GetValueFromEditorCtrl( m_editorCtrl, value );
738
739 wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
740
741 DestroyEditControl();
742
743 dv_ctrl->GetMainWindow()->SetFocus();
744
745 bool isValid = Validate(value);
746 unsigned int col = GetOwner()->GetModelColumn();
747
748 // Now we should send Editing Done event
749 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv_ctrl->GetId() );
750 event.SetDataViewColumn( GetOwner() );
751 event.SetModel( dv_ctrl->GetModel() );
752 event.SetItem( m_item );
753 event.SetValue( value );
754 event.SetColumn( col );
755 event.SetEditCanceled( !isValid );
756 event.SetEventObject( dv_ctrl );
757 dv_ctrl->GetEventHandler()->ProcessEvent( event );
758
759 if ( isValid && event.IsAllowed() )
760 {
761 dv_ctrl->GetModel()->ChangeValue(value, m_item, col);
762 return true;
763 }
764
765 return false;
766 }
767
768 void wxDataViewRendererBase::PrepareForItem(const wxDataViewModel *model,
769 const wxDataViewItem& item,
770 unsigned column)
771 {
772 wxVariant value;
773 model->GetValue(value, item, column);
774 SetValue(value);
775
776 wxDataViewItemAttr attr;
777 model->GetAttr(item, column, attr);
778 SetAttr(attr);
779
780 SetEnabled(model->IsEnabled(item, column));
781 }
782
783
784 // ----------------------------------------------------------------------------
785 // wxDataViewCustomRendererBase
786 // ----------------------------------------------------------------------------
787
788 bool wxDataViewCustomRendererBase::ActivateCell(const wxRect& cell,
789 wxDataViewModel *model,
790 const wxDataViewItem & item,
791 unsigned int col,
792 const wxMouseEvent* mouseEvent)
793 {
794 // Compatibility code
795 if ( mouseEvent )
796 return LeftClick(mouseEvent->GetPosition(), cell, model, item, col);
797 else
798 return Activate(cell, model, item, col);
799 }
800
801 void wxDataViewCustomRendererBase::RenderBackground(wxDC* dc, const wxRect& rect)
802 {
803 if ( !m_attr.HasBackgroundColour() )
804 return;
805
806 const wxColour& colour = m_attr.GetBackgroundColour();
807 wxDCPenChanger changePen(*dc, colour);
808 wxDCBrushChanger changeBrush(*dc, colour);
809
810 dc->DrawRectangle(rect);
811 }
812
813 void
814 wxDataViewCustomRendererBase::WXCallRender(wxRect rectCell, wxDC *dc, int state)
815 {
816 wxCHECK_RET( dc, "no DC to draw on in custom renderer?" );
817
818 // adjust the rectangle ourselves to account for the alignment
819 wxRect rectItem = rectCell;
820 const int align = GetAlignment();
821 if ( align != wxDVR_DEFAULT_ALIGNMENT )
822 {
823 const wxSize size = GetSize();
824
825 // take alignment into account only if there is enough space, otherwise
826 // show as much contents as possible
827 //
828 // notice that many existing renderers (e.g. wxDataViewSpinRenderer)
829 // return hard-coded size which can be more than they need and if we
830 // trusted their GetSize() we'd draw the text out of cell bounds
831 // entirely
832
833 if ( size.x >= 0 && size.x < rectCell.width )
834 {
835 if ( align & wxALIGN_CENTER_HORIZONTAL )
836 rectItem.x += (rectCell.width - size.x)/2;
837 else if ( align & wxALIGN_RIGHT )
838 rectItem.x += rectCell.width - size.x;
839 // else: wxALIGN_LEFT is the default
840
841 rectItem.width = size.x;
842 }
843
844 if ( size.y >= 0 && size.y < rectCell.height )
845 {
846 if ( align & wxALIGN_CENTER_VERTICAL )
847 rectItem.y += (rectCell.height - size.y)/2;
848 else if ( align & wxALIGN_BOTTOM )
849 rectItem.y += rectCell.height - size.y;
850 // else: wxALIGN_TOP is the default
851
852 rectItem.height = size.y;
853 }
854 }
855
856
857 // set up the DC attributes
858
859 // override custom foreground with the standard one for the selected items
860 // because we currently don't allow changing the selection background and
861 // custom colours may be unreadable on it
862 wxColour col;
863 if ( state & wxDATAVIEW_CELL_SELECTED )
864 col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
865 else if ( m_attr.HasColour() )
866 col = m_attr.GetColour();
867 else // use default foreground
868 col = GetOwner()->GetOwner()->GetForegroundColour();
869
870 wxDCTextColourChanger changeFg(*dc, col);
871
872 wxDCFontChanger changeFont(*dc);
873 if ( m_attr.HasFont() )
874 changeFont.Set(m_attr.GetEffectiveFont(dc->GetFont()));
875
876 Render(rectItem, dc, state);
877 }
878
879 wxSize wxDataViewCustomRendererBase::GetTextExtent(const wxString& str) const
880 {
881 const wxDataViewCtrl *view = GetView();
882
883 if ( m_attr.HasFont() )
884 {
885 wxFont font(m_attr.GetEffectiveFont(view->GetFont()));
886 wxSize size;
887 view->GetTextExtent(str, &size.x, &size.y, NULL, NULL, &font);
888 return size;
889 }
890 else
891 {
892 return view->GetTextExtent(str);
893 }
894 }
895
896 void
897 wxDataViewCustomRendererBase::RenderText(const wxString& text,
898 int xoffset,
899 wxRect rect,
900 wxDC *dc,
901 int WXUNUSED(state))
902 {
903 wxRect rectText = rect;
904 rectText.x += xoffset;
905 rectText.width -= xoffset;
906
907 // check if we want to ellipsize the text if it doesn't fit
908 wxString ellipsizedText;
909 if ( GetEllipsizeMode() != wxELLIPSIZE_NONE )
910 {
911 ellipsizedText = wxControl::Ellipsize
912 (
913 text,
914 *dc,
915 GetEllipsizeMode(),
916 rectText.width,
917 wxELLIPSIZE_FLAGS_NONE
918 );
919 }
920
921 // get the alignment to use
922 int align = GetAlignment();
923 if ( align == wxDVR_DEFAULT_ALIGNMENT )
924 {
925 // if we don't have an explicit alignment ourselves, use that of the
926 // column in horizontal direction and default vertical alignment
927 align = GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
928 }
929
930 dc->DrawLabel(ellipsizedText.empty() ? text : ellipsizedText,
931 rectText, align);
932 }
933
934 //-----------------------------------------------------------------------------
935 // wxDataViewEditorCtrlEvtHandler
936 //-----------------------------------------------------------------------------
937
938 BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
939 EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
940 EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
941 EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
942 EVT_TEXT_ENTER (-1, wxDataViewEditorCtrlEvtHandler::OnTextEnter)
943 END_EVENT_TABLE()
944
945 void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
946 {
947 if (m_focusOnIdle)
948 {
949 m_focusOnIdle = false;
950 if (wxWindow::FindFocus() != m_editorCtrl)
951 m_editorCtrl->SetFocus();
952 }
953
954 event.Skip();
955 }
956
957 void wxDataViewEditorCtrlEvtHandler::OnTextEnter( wxCommandEvent &WXUNUSED(event) )
958 {
959 m_finished = true;
960 m_owner->FinishEditing();
961 }
962
963 void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
964 {
965 switch ( event.m_keyCode )
966 {
967 case WXK_RETURN:
968 m_finished = true;
969 m_owner->FinishEditing();
970 break;
971
972 case WXK_ESCAPE:
973 {
974 m_finished = true;
975 m_owner->CancelEditing();
976 break;
977 }
978 default:
979 event.Skip();
980 }
981 }
982
983 void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
984 {
985 if (!m_finished)
986 {
987 m_finished = true;
988 m_owner->FinishEditing();
989 }
990
991 event.Skip();
992 }
993
994 // ---------------------------------------------------------
995 // wxDataViewColumnBase
996 // ---------------------------------------------------------
997
998 void wxDataViewColumnBase::Init(wxDataViewRenderer *renderer,
999 unsigned int model_column)
1000 {
1001 m_renderer = renderer;
1002 m_model_column = model_column;
1003 m_owner = NULL;
1004 m_renderer->SetOwner( (wxDataViewColumn*) this );
1005 }
1006
1007 wxDataViewColumnBase::~wxDataViewColumnBase()
1008 {
1009 delete m_renderer;
1010 }
1011
1012 // ---------------------------------------------------------
1013 // wxDataViewCtrlBase
1014 // ---------------------------------------------------------
1015
1016 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
1017
1018 wxDataViewCtrlBase::wxDataViewCtrlBase()
1019 {
1020 m_model = NULL;
1021 m_expander_column = 0;
1022 m_indent = 8;
1023 }
1024
1025 wxDataViewCtrlBase::~wxDataViewCtrlBase()
1026 {
1027 if (m_model)
1028 {
1029 m_model->DecRef();
1030 m_model = NULL;
1031 }
1032 }
1033
1034 bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
1035 {
1036 if (m_model)
1037 {
1038 m_model->DecRef(); // discard old model, if any
1039 }
1040
1041 // add our own reference to the new model:
1042 m_model = model;
1043 if (m_model)
1044 {
1045 m_model->IncRef();
1046 }
1047
1048 return true;
1049 }
1050
1051 wxDataViewModel* wxDataViewCtrlBase::GetModel()
1052 {
1053 return m_model;
1054 }
1055
1056 const wxDataViewModel* wxDataViewCtrlBase::GetModel() const
1057 {
1058 return m_model;
1059 }
1060
1061 void wxDataViewCtrlBase::ExpandAncestors( const wxDataViewItem & item )
1062 {
1063 if (!m_model) return;
1064
1065 if (!item.IsOk()) return;
1066
1067 wxVector<wxDataViewItem> parentChain;
1068
1069 // at first we get all the parents of the selected item
1070 wxDataViewItem parent = m_model->GetParent(item);
1071 while (parent.IsOk())
1072 {
1073 parentChain.push_back(parent);
1074 parent = m_model->GetParent(parent);
1075 }
1076
1077 // then we expand the parents, starting at the root
1078 while (!parentChain.empty())
1079 {
1080 Expand(parentChain.back());
1081 parentChain.pop_back();
1082 }
1083 }
1084
1085 wxDataViewItem wxDataViewCtrlBase::GetCurrentItem() const
1086 {
1087 return HasFlag(wxDV_MULTIPLE) ? DoGetCurrentItem()
1088 : GetSelection();
1089 }
1090
1091 void wxDataViewCtrlBase::SetCurrentItem(const wxDataViewItem& item)
1092 {
1093 wxCHECK_RET( item.IsOk(), "Can't make current an invalid item." );
1094
1095 if ( HasFlag(wxDV_MULTIPLE) )
1096 DoSetCurrentItem(item);
1097 else
1098 Select(item);
1099 }
1100
1101 wxDataViewItem wxDataViewCtrlBase::GetSelection() const
1102 {
1103 if ( GetSelectedItemsCount() != 1 )
1104 return wxDataViewItem();
1105
1106 wxDataViewItemArray selections;
1107 GetSelections(selections);
1108 return selections[0];
1109 }
1110
1111 wxDataViewColumn *
1112 wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
1113 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1114 {
1115 wxDataViewColumn *ret = new wxDataViewColumn( label,
1116 new wxDataViewTextRenderer( wxT("string"), mode ),
1117 model_column, width, align, flags );
1118 AppendColumn( ret );
1119 return ret;
1120 }
1121
1122 wxDataViewColumn *
1123 wxDataViewCtrlBase::AppendIconTextColumn( const wxString &label, unsigned int model_column,
1124 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1125 {
1126 wxDataViewColumn *ret = new wxDataViewColumn( label,
1127 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1128 model_column, width, align, flags );
1129 AppendColumn( ret );
1130 return ret;
1131 }
1132
1133 wxDataViewColumn *
1134 wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
1135 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1136 {
1137 wxDataViewColumn *ret = new wxDataViewColumn( label,
1138 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1139 model_column, width, align, flags );
1140 AppendColumn( ret );
1141 return ret;
1142 }
1143
1144 wxDataViewColumn *
1145 wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
1146 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1147 {
1148 wxDataViewColumn *ret = new wxDataViewColumn( label,
1149 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1150 model_column, width, align, flags );
1151 AppendColumn( ret );
1152 return ret;
1153 }
1154
1155 wxDataViewColumn *
1156 wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
1157 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1158 {
1159 wxDataViewColumn *ret = new wxDataViewColumn( label,
1160 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1161 model_column, width, align, flags );
1162 AppendColumn( ret );
1163 return ret;
1164 }
1165
1166 wxDataViewColumn *
1167 wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
1168 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1169 {
1170 wxDataViewColumn *ret = new wxDataViewColumn( label,
1171 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1172 model_column, width, align, flags );
1173 AppendColumn( ret );
1174 return ret;
1175 }
1176
1177 wxDataViewColumn *
1178 wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
1179 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1180 {
1181 wxDataViewColumn *ret = new wxDataViewColumn( label,
1182 new wxDataViewTextRenderer( wxT("string"), mode ),
1183 model_column, width, align, flags );
1184 AppendColumn( ret );
1185 return ret;
1186 }
1187
1188 wxDataViewColumn *
1189 wxDataViewCtrlBase::AppendIconTextColumn( const wxBitmap &label, unsigned int model_column,
1190 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1191 {
1192 wxDataViewColumn *ret = new wxDataViewColumn( label,
1193 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1194 model_column, width, align, flags );
1195 AppendColumn( ret );
1196 return ret;
1197 }
1198
1199 wxDataViewColumn *
1200 wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
1201 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1202 {
1203 wxDataViewColumn *ret = new wxDataViewColumn( label,
1204 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1205 model_column, width, align, flags );
1206 AppendColumn( ret );
1207 return ret;
1208 }
1209
1210 wxDataViewColumn *
1211 wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
1212 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1213 {
1214 wxDataViewColumn *ret = new wxDataViewColumn( label,
1215 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1216 model_column, width, align, flags );
1217 AppendColumn( ret );
1218 return ret;
1219 }
1220
1221 wxDataViewColumn *
1222 wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
1223 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1224 {
1225 wxDataViewColumn *ret = new wxDataViewColumn( label,
1226 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1227 model_column, width, align, flags );
1228 AppendColumn( ret );
1229 return ret;
1230 }
1231
1232 wxDataViewColumn *
1233 wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
1234 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1235 {
1236 wxDataViewColumn *ret = new wxDataViewColumn( label,
1237 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1238 model_column, width, align, flags );
1239 AppendColumn( ret );
1240 return ret;
1241 }
1242
1243 wxDataViewColumn *
1244 wxDataViewCtrlBase::PrependTextColumn( const wxString &label, unsigned int model_column,
1245 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1246 {
1247 wxDataViewColumn *ret = new wxDataViewColumn( label,
1248 new wxDataViewTextRenderer( wxT("string"), mode ),
1249 model_column, width, align, flags );
1250 PrependColumn( ret );
1251 return ret;
1252 }
1253
1254 wxDataViewColumn *
1255 wxDataViewCtrlBase::PrependIconTextColumn( const wxString &label, unsigned int model_column,
1256 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1257 {
1258 wxDataViewColumn *ret = new wxDataViewColumn( label,
1259 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1260 model_column, width, align, flags );
1261 PrependColumn( ret );
1262 return ret;
1263 }
1264
1265 wxDataViewColumn *
1266 wxDataViewCtrlBase::PrependToggleColumn( const wxString &label, unsigned int model_column,
1267 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1268 {
1269
1270 wxDataViewColumn *ret = new wxDataViewColumn( label,
1271 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1272 model_column, width, align, flags );
1273 PrependColumn( ret );
1274 return ret;
1275 }
1276
1277 wxDataViewColumn *
1278 wxDataViewCtrlBase::PrependProgressColumn( const wxString &label, unsigned int model_column,
1279 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1280 {
1281 wxDataViewColumn *ret = new wxDataViewColumn( label,
1282 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1283 model_column, width, align, flags );
1284 PrependColumn( ret );
1285 return ret;
1286 }
1287
1288 wxDataViewColumn *
1289 wxDataViewCtrlBase::PrependDateColumn( const wxString &label, unsigned int model_column,
1290 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1291 {
1292 wxDataViewColumn *ret = new wxDataViewColumn( label,
1293 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1294 model_column, width, align, flags );
1295 PrependColumn( ret );
1296 return ret;
1297 }
1298
1299 wxDataViewColumn *
1300 wxDataViewCtrlBase::PrependBitmapColumn( const wxString &label, unsigned int model_column,
1301 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1302 {
1303 wxDataViewColumn *ret = new wxDataViewColumn( label,
1304 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1305 model_column, width, align, flags );
1306 PrependColumn( ret );
1307 return ret;
1308 }
1309
1310 wxDataViewColumn *
1311 wxDataViewCtrlBase::PrependTextColumn( const wxBitmap &label, unsigned int model_column,
1312 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1313 {
1314 wxDataViewColumn *ret = new wxDataViewColumn( label,
1315 new wxDataViewTextRenderer( wxT("string"), mode ),
1316 model_column, width, align, flags );
1317 PrependColumn( ret );
1318 return ret;
1319 }
1320
1321 wxDataViewColumn *
1322 wxDataViewCtrlBase::PrependIconTextColumn( const wxBitmap &label, unsigned int model_column,
1323 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1324 {
1325 wxDataViewColumn *ret = new wxDataViewColumn( label,
1326 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1327 model_column, width, align, flags );
1328 PrependColumn( ret );
1329 return ret;
1330 }
1331
1332 wxDataViewColumn *
1333 wxDataViewCtrlBase::PrependToggleColumn( const wxBitmap &label, unsigned int model_column,
1334 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1335 {
1336 wxDataViewColumn *ret = new wxDataViewColumn( label,
1337 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1338 model_column, width, align, flags );
1339 PrependColumn( ret );
1340 return ret;
1341 }
1342
1343 wxDataViewColumn *
1344 wxDataViewCtrlBase::PrependProgressColumn( const wxBitmap &label, unsigned int model_column,
1345 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1346 {
1347 wxDataViewColumn *ret = new wxDataViewColumn( label,
1348 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1349 model_column, width, align, flags );
1350 PrependColumn( ret );
1351 return ret;
1352 }
1353
1354 wxDataViewColumn *
1355 wxDataViewCtrlBase::PrependDateColumn( const wxBitmap &label, unsigned int model_column,
1356 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1357 {
1358 wxDataViewColumn *ret = new wxDataViewColumn( label,
1359 new wxDataViewDateRenderer( wxT("datetime"), mode ),
1360 model_column, width, align, flags );
1361 PrependColumn( ret );
1362 return ret;
1363 }
1364
1365 wxDataViewColumn *
1366 wxDataViewCtrlBase::PrependBitmapColumn( const wxBitmap &label, unsigned int model_column,
1367 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1368 {
1369 wxDataViewColumn *ret = new wxDataViewColumn( label,
1370 new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
1371 model_column, width, align, flags );
1372 PrependColumn( ret );
1373 return ret;
1374 }
1375
1376 bool
1377 wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
1378 {
1379 col->SetOwner( (wxDataViewCtrl*) this );
1380 return true;
1381 }
1382
1383 bool
1384 wxDataViewCtrlBase::PrependColumn( wxDataViewColumn *col )
1385 {
1386 col->SetOwner( (wxDataViewCtrl*) this );
1387 return true;
1388 }
1389
1390 bool
1391 wxDataViewCtrlBase::InsertColumn( unsigned int WXUNUSED(pos), wxDataViewColumn *col )
1392 {
1393 col->SetOwner( (wxDataViewCtrl*) this );
1394 return true;
1395 }
1396
1397 void wxDataViewCtrlBase::StartEditor(const wxDataViewItem& item, unsigned int column)
1398 {
1399 EditItem(item, GetColumn(column));
1400 }
1401
1402 // ---------------------------------------------------------
1403 // wxDataViewEvent
1404 // ---------------------------------------------------------
1405
1406 IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
1407
1408 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEvent );
1409
1410 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEvent );
1411 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, wxDataViewEvent );
1412 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, wxDataViewEvent );
1413 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, wxDataViewEvent );
1414 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, wxDataViewEvent );
1415 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, wxDataViewEvent );
1416 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, wxDataViewEvent );
1417 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEvent );
1418 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEvent );
1419
1420 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEvent );
1421
1422 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, wxDataViewEvent );
1423 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, wxDataViewEvent );
1424 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, wxDataViewEvent );
1425 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED, wxDataViewEvent );
1426
1427 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_CACHE_HINT, wxDataViewEvent );
1428
1429 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, wxDataViewEvent );
1430 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, wxDataViewEvent );
1431 wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, wxDataViewEvent );
1432
1433
1434
1435 // -------------------------------------
1436 // wxDataViewSpinRenderer
1437 // -------------------------------------
1438
1439 wxDataViewSpinRenderer::wxDataViewSpinRenderer( int min, int max, wxDataViewCellMode mode, int alignment ) :
1440 wxDataViewCustomRenderer(wxT("long"), mode, alignment )
1441 {
1442 m_min = min;
1443 m_max = max;
1444 }
1445
1446 wxWindow* wxDataViewSpinRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
1447 {
1448 long l = value;
1449 wxSize size = labelRect.GetSize();
1450 #ifdef __WXMAC__
1451 size = wxSize( wxMax(70,labelRect.width ), -1 );
1452 #endif
1453 wxString str;
1454 str.Printf( wxT("%d"), (int) l );
1455 wxSpinCtrl *sc = new wxSpinCtrl( parent, wxID_ANY, str,
1456 labelRect.GetTopLeft(), size, wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER, m_min, m_max, l );
1457 #ifdef __WXMAC__
1458 size = sc->GetSize();
1459 wxPoint pt = sc->GetPosition();
1460 sc->SetSize( pt.x - 4, pt.y - 4, size.x, size.y );
1461 #endif
1462
1463 return sc;
1464 }
1465
1466 bool wxDataViewSpinRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
1467 {
1468 wxSpinCtrl *sc = (wxSpinCtrl*) editor;
1469 long l = sc->GetValue();
1470 value = l;
1471 return true;
1472 }
1473
1474 bool wxDataViewSpinRenderer::Render( wxRect rect, wxDC *dc, int state )
1475 {
1476 wxString str;
1477 str.Printf(wxT("%d"), (int) m_data );
1478 RenderText( str, 0, rect, dc, state );
1479 return true;
1480 }
1481
1482 wxSize wxDataViewSpinRenderer::GetSize() const
1483 {
1484 wxSize sz = GetTextExtent(wxString::Format("%d", (int)m_data));
1485
1486 // Allow some space for the spin buttons, which is approximately the size
1487 // of a scrollbar (and getting pixel-exact value would be complicated).
1488 // Also add some whitespace between the text and the button:
1489 sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1490 sz.x += GetTextExtent("M").x;
1491
1492 return sz;
1493 }
1494
1495 bool wxDataViewSpinRenderer::SetValue( const wxVariant &value )
1496 {
1497 m_data = value.GetLong();
1498 return true;
1499 }
1500
1501 bool wxDataViewSpinRenderer::GetValue( wxVariant &value ) const
1502 {
1503 value = m_data;
1504 return true;
1505 }
1506
1507 // -------------------------------------
1508 // wxDataViewChoiceRenderer
1509 // -------------------------------------
1510
1511 #if defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXOSX_CARBON__)
1512
1513 wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString& choices, wxDataViewCellMode mode, int alignment ) :
1514 wxDataViewCustomRenderer(wxT("string"), mode, alignment )
1515 {
1516 m_choices = choices;
1517 }
1518
1519 wxWindow* wxDataViewChoiceRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
1520 {
1521 wxChoice* c = new wxChoice
1522 (
1523 parent,
1524 wxID_ANY,
1525 labelRect.GetTopLeft(),
1526 wxSize(labelRect.GetWidth(), -1),
1527 m_choices
1528 );
1529 c->Move(labelRect.GetRight() - c->GetRect().width, wxDefaultCoord);
1530 c->SetStringSelection( value.GetString() );
1531 return c;
1532 }
1533
1534 bool wxDataViewChoiceRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
1535 {
1536 wxChoice *c = (wxChoice*) editor;
1537 wxString s = c->GetStringSelection();
1538 value = s;
1539 return true;
1540 }
1541
1542 bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state )
1543 {
1544 RenderText( m_data, 0, rect, dc, state );
1545 return true;
1546 }
1547
1548 wxSize wxDataViewChoiceRenderer::GetSize() const
1549 {
1550 wxSize sz;
1551
1552 for ( wxArrayString::const_iterator i = m_choices.begin(); i != m_choices.end(); ++i )
1553 sz.IncTo(GetTextExtent(*i));
1554
1555 // Allow some space for the right-side button, which is approximately the
1556 // size of a scrollbar (and getting pixel-exact value would be complicated).
1557 // Also add some whitespace between the text and the button:
1558 sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1559 sz.x += GetTextExtent("M").x;
1560
1561 return sz;
1562 }
1563
1564 bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
1565 {
1566 m_data = value.GetString();
1567 return true;
1568 }
1569
1570 bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
1571 {
1572 value = m_data;
1573 return true;
1574 }
1575
1576 // ----------------------------------------------------------------------------
1577 // wxDataViewChoiceByIndexRenderer
1578 // ----------------------------------------------------------------------------
1579
1580 wxDataViewChoiceByIndexRenderer::wxDataViewChoiceByIndexRenderer( const wxArrayString &choices,
1581 wxDataViewCellMode mode, int alignment ) :
1582 wxDataViewChoiceRenderer( choices, mode, alignment )
1583 {
1584 }
1585
1586 wxWindow* wxDataViewChoiceByIndexRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
1587 {
1588 wxVariant string_value = GetChoice( value.GetLong() );
1589
1590 return wxDataViewChoiceRenderer::CreateEditorCtrl( parent, labelRect, string_value );
1591 }
1592
1593 bool wxDataViewChoiceByIndexRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
1594 {
1595 wxVariant string_value;
1596 if (!wxDataViewChoiceRenderer::GetValueFromEditorCtrl( editor, string_value ))
1597 return false;
1598
1599 value = (long) GetChoices().Index( string_value.GetString() );
1600 return true;
1601 }
1602
1603 bool wxDataViewChoiceByIndexRenderer::SetValue( const wxVariant &value )
1604 {
1605 wxVariant string_value = GetChoice( value.GetLong() );
1606 return wxDataViewChoiceRenderer::SetValue( string_value );
1607 }
1608
1609 bool wxDataViewChoiceByIndexRenderer::GetValue( wxVariant &value ) const
1610 {
1611 wxVariant string_value;
1612 if (!wxDataViewChoiceRenderer::GetValue( string_value ))
1613 return false;
1614
1615 value = (long) GetChoices().Index( string_value.GetString() );
1616 return true;
1617 }
1618
1619 #endif
1620
1621 // ---------------------------------------------------------
1622 // wxDataViewDateRenderer
1623 // ---------------------------------------------------------
1624
1625 #if (defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXGTK__)) && wxUSE_DATEPICKCTRL
1626
1627 wxDataViewDateRenderer::wxDataViewDateRenderer(const wxString& varianttype,
1628 wxDataViewCellMode mode, int align)
1629 : wxDataViewCustomRenderer(varianttype, mode, align)
1630 {
1631 }
1632
1633 wxWindow *
1634 wxDataViewDateRenderer::CreateEditorCtrl(wxWindow *parent, wxRect labelRect, const wxVariant& value)
1635 {
1636 return new wxDatePickerCtrl
1637 (
1638 parent,
1639 wxID_ANY,
1640 value.GetDateTime(),
1641 labelRect.GetTopLeft(),
1642 labelRect.GetSize()
1643 );
1644 }
1645
1646 bool wxDataViewDateRenderer::GetValueFromEditorCtrl(wxWindow *editor, wxVariant& value)
1647 {
1648 wxDatePickerCtrl *ctrl = static_cast<wxDatePickerCtrl*>(editor);
1649 value = ctrl->GetValue();
1650 return true;
1651 }
1652
1653 bool wxDataViewDateRenderer::SetValue(const wxVariant& value)
1654 {
1655 m_date = value.GetDateTime();
1656 return true;
1657 }
1658
1659 bool wxDataViewDateRenderer::GetValue(wxVariant& value) const
1660 {
1661 value = m_date;
1662 return true;
1663 }
1664
1665 bool wxDataViewDateRenderer::Render(wxRect cell, wxDC* dc, int state)
1666 {
1667 wxString tmp = m_date.FormatDate();
1668 RenderText( tmp, 0, cell, dc, state );
1669 return true;
1670 }
1671
1672 wxSize wxDataViewDateRenderer::GetSize() const
1673 {
1674 return GetTextExtent(m_date.FormatDate());
1675 }
1676
1677 #endif // (defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXGTK__)) && wxUSE_DATEPICKCTRL
1678
1679 //-----------------------------------------------------------------------------
1680 // wxDataViewListStore
1681 //-----------------------------------------------------------------------------
1682
1683 wxDataViewListStore::wxDataViewListStore()
1684 {
1685 }
1686
1687 wxDataViewListStore::~wxDataViewListStore()
1688 {
1689 wxVector<wxDataViewListStoreLine*>::iterator it;
1690 for (it = m_data.begin(); it != m_data.end(); ++it)
1691 {
1692 wxDataViewListStoreLine* line = *it;
1693 delete line;
1694 }
1695 }
1696
1697 void wxDataViewListStore::PrependColumn( const wxString &varianttype )
1698 {
1699 m_cols.Insert( varianttype, 0 );
1700 }
1701
1702 void wxDataViewListStore::InsertColumn( unsigned int pos, const wxString &varianttype )
1703 {
1704 m_cols.Insert( varianttype, pos );
1705 }
1706
1707 void wxDataViewListStore::AppendColumn( const wxString &varianttype )
1708 {
1709 m_cols.Add( varianttype );
1710 }
1711
1712 unsigned int wxDataViewListStore::GetColumnCount() const
1713 {
1714 return m_cols.GetCount();
1715 }
1716
1717 wxString wxDataViewListStore::GetColumnType( unsigned int pos ) const
1718 {
1719 return m_cols[pos];
1720 }
1721
1722 void wxDataViewListStore::AppendItem( const wxVector<wxVariant> &values, wxClientData *data )
1723 {
1724 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1725 line->m_values = values;
1726 m_data.push_back( line );
1727
1728 RowAppended();
1729 }
1730
1731 void wxDataViewListStore::PrependItem( const wxVector<wxVariant> &values, wxClientData *data )
1732 {
1733 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1734 line->m_values = values;
1735 m_data.insert( m_data.begin(), line );
1736
1737 RowPrepended();
1738 }
1739
1740 void wxDataViewListStore::InsertItem( unsigned int row, const wxVector<wxVariant> &values,
1741 wxClientData *data )
1742 {
1743 wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
1744 line->m_values = values;
1745 m_data.insert( m_data.begin()+row, line );
1746
1747 RowInserted( row );
1748 }
1749
1750 void wxDataViewListStore::DeleteItem( unsigned int row )
1751 {
1752 wxVector<wxDataViewListStoreLine*>::iterator it = m_data.begin() + row;
1753 delete *it;
1754 m_data.erase( it );
1755
1756 RowDeleted( row );
1757 }
1758
1759 void wxDataViewListStore::DeleteAllItems()
1760 {
1761 wxVector<wxDataViewListStoreLine*>::iterator it;
1762 for (it = m_data.begin(); it != m_data.end(); ++it)
1763 {
1764 wxDataViewListStoreLine* line = *it;
1765 delete line;
1766 }
1767
1768 m_data.clear();
1769
1770 Reset( 0 );
1771 }
1772
1773 void wxDataViewListStore::GetValueByRow( wxVariant &value, unsigned int row, unsigned int col ) const
1774 {
1775 wxDataViewListStoreLine *line = m_data[row];
1776 value = line->m_values[col];
1777 }
1778
1779 bool wxDataViewListStore::SetValueByRow( const wxVariant &value, unsigned int row, unsigned int col )
1780 {
1781 wxDataViewListStoreLine *line = m_data[row];
1782 line->m_values[col] = value;
1783
1784 return true;
1785 }
1786
1787 //-----------------------------------------------------------------------------
1788 // wxDataViewListCtrl
1789 //-----------------------------------------------------------------------------
1790
1791 IMPLEMENT_DYNAMIC_CLASS(wxDataViewListCtrl,wxDataViewCtrl)
1792
1793 BEGIN_EVENT_TABLE(wxDataViewListCtrl,wxDataViewCtrl)
1794 EVT_SIZE( wxDataViewListCtrl::OnSize )
1795 END_EVENT_TABLE()
1796
1797 wxDataViewListCtrl::wxDataViewListCtrl()
1798 {
1799 }
1800
1801 wxDataViewListCtrl::wxDataViewListCtrl( wxWindow *parent, wxWindowID id,
1802 const wxPoint& pos, const wxSize& size, long style,
1803 const wxValidator& validator )
1804 {
1805 Create( parent, id, pos, size, style, validator );
1806 }
1807
1808 wxDataViewListCtrl::~wxDataViewListCtrl()
1809 {
1810 }
1811
1812
1813 bool wxDataViewListCtrl::Create( wxWindow *parent, wxWindowID id,
1814 const wxPoint& pos, const wxSize& size, long style,
1815 const wxValidator& validator )
1816 {
1817 if ( !wxDataViewCtrl::Create( parent, id, pos, size, style, validator ) )
1818 return false;
1819
1820 wxDataViewListStore *store = new wxDataViewListStore;
1821 AssociateModel( store );
1822 store->DecRef();
1823
1824 return true;
1825 }
1826
1827 bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *column, const wxString &varianttype )
1828 {
1829 GetStore()->AppendColumn( varianttype );
1830 return wxDataViewCtrl::AppendColumn( column );
1831 }
1832
1833 bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *column, const wxString &varianttype )
1834 {
1835 GetStore()->PrependColumn( varianttype );
1836 return wxDataViewCtrl::PrependColumn( column );
1837 }
1838
1839 bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *column, const wxString &varianttype )
1840 {
1841 GetStore()->InsertColumn( pos, varianttype );
1842 return wxDataViewCtrl::InsertColumn( pos, column );
1843 }
1844
1845 bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *col )
1846 {
1847 return PrependColumn( col, "string" );
1848 }
1849
1850 bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
1851 {
1852 return InsertColumn( pos, col, "string" );
1853 }
1854
1855 bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *col )
1856 {
1857 return AppendColumn( col, "string" );
1858 }
1859
1860 wxDataViewColumn *wxDataViewListCtrl::AppendTextColumn( const wxString &label,
1861 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1862 {
1863 GetStore()->AppendColumn( wxT("string") );
1864
1865 wxDataViewColumn *ret = new wxDataViewColumn( label,
1866 new wxDataViewTextRenderer( wxT("string"), mode ),
1867 GetStore()->GetColumnCount()-1, width, align, flags );
1868
1869 wxDataViewCtrl::AppendColumn( ret );
1870
1871 return ret;
1872 }
1873
1874 wxDataViewColumn *wxDataViewListCtrl::AppendToggleColumn( const wxString &label,
1875 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1876 {
1877 GetStore()->AppendColumn( wxT("bool") );
1878
1879 wxDataViewColumn *ret = new wxDataViewColumn( label,
1880 new wxDataViewToggleRenderer( wxT("bool"), mode ),
1881 GetStore()->GetColumnCount()-1, width, align, flags );
1882
1883 wxDataViewCtrl::AppendColumn( ret );
1884
1885 return ret;
1886 }
1887
1888 wxDataViewColumn *wxDataViewListCtrl::AppendProgressColumn( const wxString &label,
1889 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1890 {
1891 GetStore()->AppendColumn( wxT("long") );
1892
1893 wxDataViewColumn *ret = new wxDataViewColumn( label,
1894 new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
1895 GetStore()->GetColumnCount()-1, width, align, flags );
1896
1897 wxDataViewCtrl::AppendColumn( ret );
1898
1899 return ret;
1900 }
1901
1902 wxDataViewColumn *wxDataViewListCtrl::AppendIconTextColumn( const wxString &label,
1903 wxDataViewCellMode mode, int width, wxAlignment align, int flags )
1904 {
1905 GetStore()->AppendColumn( wxT("wxDataViewIconText") );
1906
1907 wxDataViewColumn *ret = new wxDataViewColumn( label,
1908 new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
1909 GetStore()->GetColumnCount()-1, width, align, flags );
1910
1911 wxDataViewCtrl::AppendColumn( ret );
1912
1913 return ret;
1914 }
1915
1916 void wxDataViewListCtrl::OnSize( wxSizeEvent &event )
1917 {
1918 event.Skip( true );
1919 }
1920
1921 //-----------------------------------------------------------------------------
1922 // wxDataViewTreeStore
1923 //-----------------------------------------------------------------------------
1924
1925 wxDataViewTreeStoreNode::wxDataViewTreeStoreNode(
1926 wxDataViewTreeStoreNode *parent,
1927 const wxString &text, const wxIcon &icon, wxClientData *data )
1928 {
1929 m_parent = parent;
1930 m_text = text;
1931 m_icon = icon;
1932 m_data = data;
1933 }
1934
1935 wxDataViewTreeStoreNode::~wxDataViewTreeStoreNode()
1936 {
1937 if (m_data)
1938 delete m_data;
1939 }
1940
1941 #include "wx/listimpl.cpp"
1942 WX_DEFINE_LIST(wxDataViewTreeStoreNodeList)
1943
1944 wxDataViewTreeStoreContainerNode::wxDataViewTreeStoreContainerNode(
1945 wxDataViewTreeStoreNode *parent, const wxString &text,
1946 const wxIcon &icon, const wxIcon &expanded, wxClientData *data ) :
1947 wxDataViewTreeStoreNode( parent, text, icon, data )
1948 {
1949 m_iconExpanded = expanded;
1950 m_isExpanded = false;
1951 m_children.DeleteContents(true);
1952 }
1953
1954 wxDataViewTreeStoreContainerNode::~wxDataViewTreeStoreContainerNode()
1955 {
1956 }
1957
1958 //-----------------------------------------------------------------------------
1959
1960 wxDataViewTreeStore::wxDataViewTreeStore()
1961 {
1962 m_root = new wxDataViewTreeStoreContainerNode( NULL, wxEmptyString );
1963 }
1964
1965 wxDataViewTreeStore::~wxDataViewTreeStore()
1966 {
1967 delete m_root;
1968 }
1969
1970 wxDataViewItem wxDataViewTreeStore::AppendItem( const wxDataViewItem& parent,
1971 const wxString &text, const wxIcon &icon, wxClientData *data )
1972 {
1973 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1974 if (!parent_node) return wxDataViewItem(0);
1975
1976 wxDataViewTreeStoreNode *node =
1977 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
1978 parent_node->GetChildren().Append( node );
1979
1980 return node->GetItem();
1981 }
1982
1983 wxDataViewItem wxDataViewTreeStore::PrependItem( const wxDataViewItem& parent,
1984 const wxString &text, const wxIcon &icon, wxClientData *data )
1985 {
1986 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
1987 if (!parent_node) return wxDataViewItem(0);
1988
1989 wxDataViewTreeStoreNode *node =
1990 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
1991 parent_node->GetChildren().Insert( node );
1992
1993 return node->GetItem();
1994 }
1995
1996 wxDataViewItem
1997 wxDataViewTreeStore::InsertItem(const wxDataViewItem& parent,
1998 const wxDataViewItem& previous,
1999 const wxString& text,
2000 const wxIcon& icon,
2001 wxClientData *data)
2002 {
2003 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
2004 if (!parent_node) return wxDataViewItem(0);
2005
2006 wxDataViewTreeStoreNode *previous_node = FindNode( previous );
2007 int pos = parent_node->GetChildren().IndexOf( previous_node );
2008 if (pos == wxNOT_FOUND) return wxDataViewItem(0);
2009
2010 wxDataViewTreeStoreNode *node =
2011 new wxDataViewTreeStoreNode( parent_node, text, icon, data );
2012 parent_node->GetChildren().Insert( (size_t) pos, node );
2013
2014 return node->GetItem();
2015 }
2016
2017 wxDataViewItem wxDataViewTreeStore::PrependContainer( const wxDataViewItem& parent,
2018 const wxString &text, const wxIcon &icon, const wxIcon &expanded,
2019 wxClientData *data )
2020 {
2021 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
2022 if (!parent_node) return wxDataViewItem(0);
2023
2024 wxDataViewTreeStoreContainerNode *node =
2025 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
2026 parent_node->GetChildren().Insert( node );
2027
2028 return node->GetItem();
2029 }
2030
2031 wxDataViewItem
2032 wxDataViewTreeStore::AppendContainer(const wxDataViewItem& parent,
2033 const wxString &text,
2034 const wxIcon& icon,
2035 const wxIcon& expanded,
2036 wxClientData * data)
2037 {
2038 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
2039 if (!parent_node) return wxDataViewItem(0);
2040
2041 wxDataViewTreeStoreContainerNode *node =
2042 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
2043 parent_node->GetChildren().Append( node );
2044
2045 return node->GetItem();
2046 }
2047
2048 wxDataViewItem
2049 wxDataViewTreeStore::InsertContainer(const wxDataViewItem& parent,
2050 const wxDataViewItem& previous,
2051 const wxString& text,
2052 const wxIcon& icon,
2053 const wxIcon& expanded,
2054 wxClientData * data)
2055 {
2056 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
2057 if (!parent_node) return wxDataViewItem(0);
2058
2059 wxDataViewTreeStoreNode *previous_node = FindNode( previous );
2060 int pos = parent_node->GetChildren().IndexOf( previous_node );
2061 if (pos == wxNOT_FOUND) return wxDataViewItem(0);
2062
2063 wxDataViewTreeStoreContainerNode *node =
2064 new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
2065 parent_node->GetChildren().Insert( (size_t) pos, node );
2066
2067 return node->GetItem();
2068 }
2069
2070 bool wxDataViewTreeStore::IsContainer( const wxDataViewItem& item ) const
2071 {
2072 wxDataViewTreeStoreNode *node = FindNode( item );
2073 if (!node) return false;
2074
2075 return node->IsContainer();
2076 }
2077
2078 wxDataViewItem wxDataViewTreeStore::GetNthChild( const wxDataViewItem& parent, unsigned int pos ) const
2079 {
2080 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
2081 if (!parent_node) return wxDataViewItem(0);
2082
2083 wxDataViewTreeStoreNodeList::compatibility_iterator node = parent_node->GetChildren().Item( pos );
2084 if (node)
2085 return wxDataViewItem(node->GetData());
2086
2087 return wxDataViewItem(0);
2088 }
2089
2090 int wxDataViewTreeStore::GetChildCount( const wxDataViewItem& parent ) const
2091 {
2092 wxDataViewTreeStoreNode *node = FindNode( parent );
2093 if (!node) return -1;
2094
2095 if (!node->IsContainer())
2096 return 0;
2097
2098 wxDataViewTreeStoreContainerNode *container_node = (wxDataViewTreeStoreContainerNode*) node;
2099 return (int) container_node->GetChildren().GetCount();
2100 }
2101
2102 void wxDataViewTreeStore::SetItemText( const wxDataViewItem& item, const wxString &text )
2103 {
2104 wxDataViewTreeStoreNode *node = FindNode( item );
2105 if (!node) return;
2106
2107 node->SetText( text );
2108 }
2109
2110 wxString wxDataViewTreeStore::GetItemText( const wxDataViewItem& item ) const
2111 {
2112 wxDataViewTreeStoreNode *node = FindNode( item );
2113 if (!node) return wxEmptyString;
2114
2115 return node->GetText();
2116 }
2117
2118 void wxDataViewTreeStore::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
2119 {
2120 wxDataViewTreeStoreNode *node = FindNode( item );
2121 if (!node) return;
2122
2123 node->SetIcon( icon );
2124 }
2125
2126 const wxIcon &wxDataViewTreeStore::GetItemIcon( const wxDataViewItem& item ) const
2127 {
2128 wxDataViewTreeStoreNode *node = FindNode( item );
2129 if (!node) return wxNullIcon;
2130
2131 return node->GetIcon();
2132 }
2133
2134 void wxDataViewTreeStore::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
2135 {
2136 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
2137 if (!node) return;
2138
2139 node->SetExpandedIcon( icon );
2140 }
2141
2142 const wxIcon &wxDataViewTreeStore::GetItemExpandedIcon( const wxDataViewItem& item ) const
2143 {
2144 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
2145 if (!node) return wxNullIcon;
2146
2147 return node->GetExpandedIcon();
2148 }
2149
2150 void wxDataViewTreeStore::SetItemData( const wxDataViewItem& item, wxClientData *data )
2151 {
2152 wxDataViewTreeStoreNode *node = FindNode( item );
2153 if (!node) return;
2154
2155 node->SetData( data );
2156 }
2157
2158 wxClientData *wxDataViewTreeStore::GetItemData( const wxDataViewItem& item ) const
2159 {
2160 wxDataViewTreeStoreNode *node = FindNode( item );
2161 if (!node) return NULL;
2162
2163 return node->GetData();
2164 }
2165
2166 void wxDataViewTreeStore::DeleteItem( const wxDataViewItem& item )
2167 {
2168 if (!item.IsOk()) return;
2169
2170 wxDataViewItem parent_item = GetParent( item );
2171
2172 wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent_item );
2173 if (!parent_node) return;
2174
2175 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
2176 if (!node) return;
2177
2178 parent_node->GetChildren().DeleteObject( node );
2179 }
2180
2181 void wxDataViewTreeStore::DeleteChildren( const wxDataViewItem& item )
2182 {
2183 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
2184 if (!node) return;
2185
2186 node->GetChildren().clear();
2187 }
2188
2189 void wxDataViewTreeStore::DeleteAllItems()
2190 {
2191 DeleteChildren(wxDataViewItem(m_root));
2192 }
2193
2194 void
2195 wxDataViewTreeStore::GetValue(wxVariant &variant,
2196 const wxDataViewItem &item,
2197 unsigned int WXUNUSED(col)) const
2198 {
2199 // if (col != 0) return;
2200
2201 wxDataViewTreeStoreNode *node = FindNode( item );
2202 if (!node) return;
2203
2204 wxIcon icon( node->GetIcon());
2205 if (node->IsContainer())
2206 {
2207 wxDataViewTreeStoreContainerNode *container = (wxDataViewTreeStoreContainerNode*) node;
2208 if (container->IsExpanded() && container->GetExpandedIcon().IsOk())
2209 icon = container->GetExpandedIcon();
2210 }
2211
2212 wxDataViewIconText data( node->GetText(), icon );
2213
2214 variant << data;
2215 }
2216
2217 bool
2218 wxDataViewTreeStore::SetValue(const wxVariant& variant,
2219 const wxDataViewItem& item,
2220 unsigned int WXUNUSED(col))
2221 {
2222 // if (col != 0) return false;
2223
2224 wxDataViewTreeStoreNode *node = FindNode( item );
2225 if (!node) return false;
2226
2227 wxDataViewIconText data;
2228
2229 data << variant;
2230
2231 node->SetText( data.GetText() );
2232 node->SetIcon( data.GetIcon() );
2233
2234 return true;
2235 }
2236
2237 wxDataViewItem wxDataViewTreeStore::GetParent( const wxDataViewItem &item ) const
2238 {
2239 wxDataViewTreeStoreNode *node = FindNode( item );
2240 if (!node) return wxDataViewItem(0);
2241
2242 wxDataViewTreeStoreNode *parent = node->GetParent();
2243 if (!parent) return wxDataViewItem(0);
2244
2245 if (parent == m_root)
2246 return wxDataViewItem(0);
2247
2248 return parent->GetItem();
2249 }
2250
2251 unsigned int wxDataViewTreeStore::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
2252 {
2253 wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
2254 if (!node) return 0;
2255
2256 wxDataViewTreeStoreNodeList::iterator iter;
2257 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
2258 {
2259 wxDataViewTreeStoreNode* child = *iter;
2260 children.Add( child->GetItem() );
2261 }
2262
2263 return node->GetChildren().GetCount();
2264 }
2265
2266 int wxDataViewTreeStore::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
2267 unsigned int WXUNUSED(column), bool WXUNUSED(ascending) ) const
2268 {
2269 wxDataViewTreeStoreNode *node1 = FindNode( item1 );
2270 wxDataViewTreeStoreNode *node2 = FindNode( item2 );
2271
2272 if (!node1 || !node2)
2273 return 0;
2274
2275 wxDataViewTreeStoreContainerNode* parent1 =
2276 (wxDataViewTreeStoreContainerNode*) node1->GetParent();
2277 wxDataViewTreeStoreContainerNode* parent2 =
2278 (wxDataViewTreeStoreContainerNode*) node2->GetParent();
2279
2280 if (parent1 != parent2)
2281 {
2282 wxLogError( wxT("Comparing items with different parent.") );
2283 return 0;
2284 }
2285
2286 if (node1->IsContainer() && !node2->IsContainer())
2287 return -1;
2288
2289 if (node2->IsContainer() && !node1->IsContainer())
2290 return 1;
2291
2292 return parent1->GetChildren().IndexOf( node1 ) - parent2->GetChildren().IndexOf( node2 );
2293 }
2294
2295 wxDataViewTreeStoreNode *wxDataViewTreeStore::FindNode( const wxDataViewItem &item ) const
2296 {
2297 if (!item.IsOk())
2298 return m_root;
2299
2300 return (wxDataViewTreeStoreNode*) item.GetID();
2301 }
2302
2303 wxDataViewTreeStoreContainerNode *wxDataViewTreeStore::FindContainerNode( const wxDataViewItem &item ) const
2304 {
2305 if (!item.IsOk())
2306 return (wxDataViewTreeStoreContainerNode*) m_root;
2307
2308 wxDataViewTreeStoreNode* node = (wxDataViewTreeStoreNode*) item.GetID();
2309
2310 if (!node->IsContainer())
2311 return NULL;
2312
2313 return (wxDataViewTreeStoreContainerNode*) node;
2314 }
2315
2316 //-----------------------------------------------------------------------------
2317 // wxDataViewTreeCtrl
2318 //-----------------------------------------------------------------------------
2319
2320 IMPLEMENT_DYNAMIC_CLASS(wxDataViewTreeCtrl,wxDataViewCtrl)
2321
2322 BEGIN_EVENT_TABLE(wxDataViewTreeCtrl,wxDataViewCtrl)
2323 EVT_DATAVIEW_ITEM_EXPANDED(-1, wxDataViewTreeCtrl::OnExpanded)
2324 EVT_DATAVIEW_ITEM_COLLAPSED(-1, wxDataViewTreeCtrl::OnCollapsed)
2325 EVT_SIZE( wxDataViewTreeCtrl::OnSize )
2326 END_EVENT_TABLE()
2327
2328 bool wxDataViewTreeCtrl::Create( wxWindow *parent, wxWindowID id,
2329 const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator )
2330 {
2331 if ( !wxDataViewCtrl::Create( parent, id, pos, size, style, validator ) )
2332 return false;
2333
2334 // create the standard model and a column in the tree
2335 wxDataViewTreeStore *store = new wxDataViewTreeStore;
2336 AssociateModel( store );
2337 store->DecRef();
2338
2339 AppendIconTextColumn
2340 (
2341 wxString(), // no label (header is not shown anyhow)
2342 0, // the only model column
2343 wxDATAVIEW_CELL_EDITABLE,
2344 -1, // default width
2345 wxALIGN_NOT, // and alignment
2346 0 // not resizable
2347 );
2348
2349 return true;
2350 }
2351
2352 wxDataViewItem wxDataViewTreeCtrl::AppendItem( const wxDataViewItem& parent,
2353 const wxString &text, int iconIndex, wxClientData *data )
2354 {
2355 wxDataViewItem res = GetStore()->
2356 AppendItem( parent, text, GetImage(iconIndex), data );
2357
2358 GetStore()->ItemAdded( parent, res );
2359
2360 return res;
2361 }
2362
2363 wxDataViewItem wxDataViewTreeCtrl::PrependItem( const wxDataViewItem& parent,
2364 const wxString &text, int iconIndex, wxClientData *data )
2365 {
2366 wxDataViewItem res = GetStore()->
2367 PrependItem( parent, text, GetImage(iconIndex), data );
2368
2369 GetStore()->ItemAdded( parent, res );
2370
2371 return res;
2372 }
2373
2374 wxDataViewItem wxDataViewTreeCtrl::InsertItem( const wxDataViewItem& parent, const wxDataViewItem& previous,
2375 const wxString &text, int iconIndex, wxClientData *data )
2376 {
2377 wxDataViewItem res = GetStore()->
2378 InsertItem( parent, previous, text, GetImage(iconIndex), data );
2379
2380 GetStore()->ItemAdded( parent, res );
2381
2382 return res;
2383 }
2384
2385 wxDataViewItem wxDataViewTreeCtrl::PrependContainer( const wxDataViewItem& parent,
2386 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2387 {
2388 wxDataViewItem res = GetStore()->
2389 PrependContainer( parent, text,
2390 GetImage(iconIndex), GetImage(expandedIndex), data );
2391
2392 GetStore()->ItemAdded( parent, res );
2393
2394 return res;
2395 }
2396
2397 wxDataViewItem wxDataViewTreeCtrl::AppendContainer( const wxDataViewItem& parent,
2398 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2399 {
2400 wxDataViewItem res = GetStore()->
2401 AppendContainer( parent, text,
2402 GetImage(iconIndex), GetImage(expandedIndex), data );
2403
2404 GetStore()->ItemAdded( parent, res );
2405
2406 return res;
2407 }
2408
2409 wxDataViewItem wxDataViewTreeCtrl::InsertContainer( const wxDataViewItem& parent, const wxDataViewItem& previous,
2410 const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
2411 {
2412 wxDataViewItem res = GetStore()->
2413 InsertContainer( parent, previous, text,
2414 GetImage(iconIndex), GetImage(expandedIndex), data );
2415
2416 GetStore()->ItemAdded( parent, res );
2417
2418 return res;
2419 }
2420
2421 void wxDataViewTreeCtrl::SetItemText( const wxDataViewItem& item, const wxString &text )
2422 {
2423 GetStore()->SetItemText(item,text);
2424
2425 // notify control
2426 GetStore()->ValueChanged( item, 0 );
2427 }
2428
2429 void wxDataViewTreeCtrl::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
2430 {
2431 GetStore()->SetItemIcon(item,icon);
2432
2433 // notify control
2434 GetStore()->ValueChanged( item, 0 );
2435 }
2436
2437 void wxDataViewTreeCtrl::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
2438 {
2439 GetStore()->SetItemExpandedIcon(item,icon);
2440
2441 // notify control
2442 GetStore()->ValueChanged( item, 0 );
2443 }
2444
2445 void wxDataViewTreeCtrl::DeleteItem( const wxDataViewItem& item )
2446 {
2447 wxDataViewItem parent_item = GetStore()->GetParent( item );
2448
2449 GetStore()->DeleteItem(item);
2450
2451 // notify control
2452 GetStore()->ItemDeleted( parent_item, item );
2453 }
2454
2455 void wxDataViewTreeCtrl::DeleteChildren( const wxDataViewItem& item )
2456 {
2457 wxDataViewTreeStoreContainerNode *node = GetStore()->FindContainerNode( item );
2458 if (!node) return;
2459
2460 wxDataViewItemArray array;
2461 wxDataViewTreeStoreNodeList::iterator iter;
2462 for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
2463 {
2464 wxDataViewTreeStoreNode* child = *iter;
2465 array.Add( child->GetItem() );
2466 }
2467
2468 GetStore()->DeleteChildren( item );
2469
2470 // notify control
2471 GetStore()->ItemsDeleted( item, array );
2472 }
2473
2474 void wxDataViewTreeCtrl::DeleteAllItems()
2475 {
2476 GetStore()->DeleteAllItems();
2477
2478 GetStore()->Cleared();
2479 }
2480
2481 void wxDataViewTreeCtrl::OnExpanded( wxDataViewEvent &event )
2482 {
2483 if (HasImageList()) return;
2484
2485 wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
2486 if (!container) return;
2487
2488 container->SetExpanded( true );
2489
2490 GetStore()->ItemChanged( event.GetItem() );
2491 }
2492
2493 void wxDataViewTreeCtrl::OnCollapsed( wxDataViewEvent &event )
2494 {
2495 if (HasImageList()) return;
2496
2497 wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
2498 if (!container) return;
2499
2500 container->SetExpanded( false );
2501
2502 GetStore()->ItemChanged( event.GetItem() );
2503 }
2504
2505 void wxDataViewTreeCtrl::OnSize( wxSizeEvent &event )
2506 {
2507 #if defined(wxUSE_GENERICDATAVIEWCTRL)
2508 // automatically resize our only column to take the entire control width
2509 if ( GetColumnCount() )
2510 {
2511 wxSize size = GetClientSize();
2512 GetColumn(0)->SetWidth(size.x);
2513 }
2514 #endif
2515 event.Skip( true );
2516 }
2517
2518 #endif // wxUSE_DATAVIEWCTRL
2519