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