1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/dataview_osx.cpp
3 // Purpose:     wxDataViewCtrl native mac implementation
4 // Author:
5 // Copyright:   (c) 2009
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 #if wxUSE_DATAVIEWCTRL
13 
14 #include "wx/dataview.h"
15 
16 #ifndef wxHAS_GENERIC_DATAVIEWCTRL
17 
18 #include <limits>
19 
20 #ifndef WX_PRECOMP
21     #include "wx/timer.h"
22     #include "wx/settings.h"
23     #include "wx/dcclient.h"
24     #include "wx/icon.h"
25 #endif
26 
27 #include "wx/osx/core/dataview.h"
28 #include "wx/osx/private.h"
29 #include "wx/renderer.h"
30 
31 // ============================================================================
32 // Helper functions for dataviewe implementation on OSX
33 // ============================================================================
ConcatenateDataViewItemValues(wxDataViewCtrl const * dataViewCtrlPtr,wxDataViewItem const & dataViewItem)34 wxString ConcatenateDataViewItemValues(wxDataViewCtrl const* dataViewCtrlPtr, wxDataViewItem const& dataViewItem)
35 {
36   wxString dataString; // contains the TAB concatenated data
37 
38 
39   for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); i++)
40   {
41    // variable definition:
42     wxVariant dataValue;
43 
44     dataViewCtrlPtr->GetModel()->GetValue(dataValue,dataViewItem,dataViewCtrlPtr->GetColumn(i)->GetModelColumn());
45     if (i > 0)
46       dataString << wxT('\t');
47     dataString << dataValue.MakeString();
48   }
49   return dataString;
50 }
51 
52 // ============================================================================
53 // wxOSXDataViewModelNotifier
54 // ============================================================================
55 class wxOSXDataViewModelNotifier : public wxDataViewModelNotifier
56 {
57 public:
58  //
59  // constructors / destructor
60  //
61   wxOSXDataViewModelNotifier(wxDataViewCtrl* initDataViewCtrlPtr);
62 
63  //
64  // inherited methods from wxDataViewModelNotifier
65  //
66   virtual bool ItemAdded   (wxDataViewItem const &parent, wxDataViewItem const &item) wxOVERRIDE;
67   virtual bool ItemsAdded  (wxDataViewItem const& parent, wxDataViewItemArray const& items) wxOVERRIDE;
68   virtual bool ItemChanged (wxDataViewItem const& item) wxOVERRIDE;
69   virtual bool ItemsChanged(wxDataViewItemArray const& items) wxOVERRIDE;
70   virtual bool ItemDeleted (wxDataViewItem const& parent, wxDataViewItem const& item) wxOVERRIDE;
71   virtual bool ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& items) wxOVERRIDE;
72   virtual bool ValueChanged(wxDataViewItem const& item, unsigned int col) wxOVERRIDE;
73   virtual bool Cleared() wxOVERRIDE;
74   virtual void Resort() wxOVERRIDE;
75 
76  // adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data
77   void AdjustAutosizedColumns();
78 
79 protected:
80  // if the dataview control can have a variable row height this method sets the dataview's control row height of
81  // the passed item to the maximum value occupied by the item in all columns
82   void AdjustRowHeight(wxDataViewItem const& item);
83  // ... and the same method for a couple of items:
84   void AdjustRowHeights(wxDataViewItemArray const& items);
85 
86 private:
87   wxDataViewCtrl* m_DataViewCtrlPtr;
88 };
89 
90 //
91 // constructors / destructor
92 //
wxOSXDataViewModelNotifier(wxDataViewCtrl * initDataViewCtrlPtr)93 wxOSXDataViewModelNotifier::wxOSXDataViewModelNotifier(wxDataViewCtrl* initDataViewCtrlPtr)
94                            :m_DataViewCtrlPtr(initDataViewCtrlPtr)
95 {
96   if (initDataViewCtrlPtr == NULL)
97     wxFAIL_MSG("Pointer to dataview control must not be NULL");
98 }
99 
ItemAdded(wxDataViewItem const & parent,wxDataViewItem const & item)100 bool wxOSXDataViewModelNotifier::ItemAdded(wxDataViewItem const& parent, wxDataViewItem const& item)
101 {
102   bool noFailureFlag;
103 
104 
105   wxCHECK_MSG(item.IsOk(),false,"Added item is invalid.");
106   noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Add(parent,item);
107   AdjustRowHeight(item);
108   AdjustAutosizedColumns();
109   return noFailureFlag;
110 }
111 
ItemsAdded(wxDataViewItem const & parent,wxDataViewItemArray const & items)112 bool wxOSXDataViewModelNotifier::ItemsAdded(wxDataViewItem const& parent, wxDataViewItemArray const& items)
113 {
114   bool noFailureFlag;
115 
116 
117  // insert all valid items into control:
118   noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Add(parent,items);
119  // adjust row heights:
120   AdjustRowHeights(items);
121   AdjustAutosizedColumns();
122  // done:
123   return noFailureFlag;
124 }
125 
ItemChanged(wxDataViewItem const & item)126 bool wxOSXDataViewModelNotifier::ItemChanged(wxDataViewItem const& item)
127 {
128   wxCHECK_MSG(item.IsOk(),             false,"Changed item is invalid.");
129   wxCHECK_MSG(GetOwner() != NULL,false,"Owner not initialized.");
130   if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(item),item))
131   {
132    // send the equivalent wxWidgets event:
133     wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, m_DataViewCtrlPtr, item);
134     m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
135    // row height may have to be adjusted:
136     AdjustRowHeight(item);
137     AdjustAutosizedColumns();
138    // done
139     return true;
140   }
141   else
142     return false;
143 }
144 
ItemsChanged(wxDataViewItemArray const & items)145 bool wxOSXDataViewModelNotifier::ItemsChanged(wxDataViewItemArray const& items)
146 {
147   size_t const noOfItems = items.GetCount();
148 
149   for (size_t indexItem=0; indexItem<noOfItems; ++indexItem)
150     if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(items[indexItem]),items[indexItem]))
151     {
152      // send for all changed items a wxWidgets event:
153       wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,m_DataViewCtrlPtr,items[indexItem]);
154       m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
155     }
156     else
157       return false;
158  // if this location is reached all items have been updated:
159   AdjustRowHeights(items);
160   AdjustAutosizedColumns();
161  // done:
162   return true;
163 }
164 
ItemDeleted(wxDataViewItem const & parent,wxDataViewItem const & item)165 bool wxOSXDataViewModelNotifier::ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
166 {
167   bool noFailureFlag;
168 
169 
170   wxCHECK_MSG(item.IsOk(),false,"To be deleted item is invalid.");
171  // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
172  // not to be identical because the being edited item might be below the passed item in the hierarchy);
173  // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
174  // has been started and that variables can currently not be updated even when requested by the system:
175   m_DataViewCtrlPtr->SetDeleting(true);
176   noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
177  // enable automatic updating again:
178   m_DataViewCtrlPtr->SetDeleting(false);
179 
180   AdjustAutosizedColumns();
181  // done:
182   return noFailureFlag;
183 }
184 
ItemsDeleted(wxDataViewItem const & parent,wxDataViewItemArray const & WXUNUSED (items))185 bool wxOSXDataViewModelNotifier::ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& WXUNUSED(items))
186 {
187   bool noFailureFlag;
188 
189 
190  // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
191  // not to be identical because the being edited item might be below the passed item in the hierarchy);
192  // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
193  // has been started and that variables can currently not be updated even when requested by the system:
194   m_DataViewCtrlPtr->SetDeleting(true);
195  // delete all specified items:
196   noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
197  // enable automatic updating again:
198   m_DataViewCtrlPtr->SetDeleting(false);
199 
200   AdjustAutosizedColumns();
201  // done:
202   return noFailureFlag;
203 }
204 
ValueChanged(wxDataViewItem const & item,unsigned int col)205 bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsigned int col)
206 {
207   wxCHECK_MSG(item.IsOk(),             false,"Passed item is invalid.");
208   wxCHECK_MSG(GetOwner() != NULL,false,"Owner not initialized.");
209   if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(item),item))
210   {
211     wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, m_DataViewCtrlPtr, m_DataViewCtrlPtr->GetColumn(col), item);
212 
213    // send the equivalent wxWidgets event:
214     m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
215 
216     AdjustAutosizedColumns();
217    // done
218     return true;
219   }
220   else
221     return false;
222 }
223 
Cleared()224 bool wxOSXDataViewModelNotifier::Cleared()
225 {
226   return m_DataViewCtrlPtr->GetDataViewPeer()->Reload();
227 }
228 
Resort()229 void wxOSXDataViewModelNotifier::Resort()
230 {
231   m_DataViewCtrlPtr->GetDataViewPeer()->Resort();
232 }
233 
AdjustRowHeight(wxDataViewItem const & item)234 void wxOSXDataViewModelNotifier::AdjustRowHeight(wxDataViewItem const& item)
235 {
236   if ((m_DataViewCtrlPtr->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) != 0)
237   {
238       wxDataViewModel *model = GetOwner();
239 
240       int height = 20; // TODO find out standard height
241       unsigned int num = m_DataViewCtrlPtr->GetColumnCount();
242       unsigned int col;
243       for (col = 0; col < num; col++)
244       {
245           wxDataViewColumn* column(m_DataViewCtrlPtr->GetColumnPtr(col));
246 
247           if (!(column->IsHidden()))
248           {
249             wxDataViewCustomRenderer *renderer = dynamic_cast<wxDataViewCustomRenderer*>(column->GetRenderer());
250             if (renderer)
251             {
252                 wxVariant value;
253                 model->GetValue( value, item, column->GetModelColumn() );
254                 renderer->SetValue( value );
255                 height = wxMax( height, renderer->GetSize().y );
256             }
257           }
258       }
259       if (height > 20)
260         m_DataViewCtrlPtr->GetDataViewPeer()->SetRowHeight(item,height);
261   }
262 }
263 
AdjustRowHeights(wxDataViewItemArray const & items)264 void wxOSXDataViewModelNotifier::AdjustRowHeights(wxDataViewItemArray const& items)
265 {
266   if ((m_DataViewCtrlPtr->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) != 0)
267   {
268       size_t const noOfItems = items.GetCount();
269 
270       wxDataViewModel *model = GetOwner();
271 
272       for (size_t itemIndex=0; itemIndex<noOfItems; ++itemIndex)
273       {
274         int height = 20; // TODO find out standard height
275         unsigned int num = m_DataViewCtrlPtr->GetColumnCount();
276         unsigned int col;
277 
278         for (col = 0; col < num; col++)
279         {
280             wxDataViewColumn* column(m_DataViewCtrlPtr->GetColumnPtr(col));
281 
282             if (!(column->IsHidden()))
283             {
284               wxDataViewCustomRenderer *renderer = dynamic_cast<wxDataViewCustomRenderer*>(column->GetRenderer());
285               if (renderer)
286               {
287                   wxVariant value;
288                   model->GetValue( value, items[itemIndex], column->GetModelColumn() );
289                   renderer->SetValue( value );
290                   height = wxMax( height, renderer->GetSize().y );
291               }
292             }
293         }
294         if (height > 20)
295           m_DataViewCtrlPtr->GetDataViewPeer()->SetRowHeight(items[itemIndex],height);
296       }
297   }
298 }
299 
AdjustAutosizedColumns()300 void wxOSXDataViewModelNotifier::AdjustAutosizedColumns()
301 {
302   unsigned count = m_DataViewCtrlPtr->GetColumnCount();
303   for ( unsigned col = 0; col < count; col++ )
304   {
305     m_DataViewCtrlPtr->GetDataViewPeer()->FitColumnWidthToContent(col);
306   }
307 }
308 
309 // ---------------------------------------------------------
310 // wxDataViewCustomRenderer
311 // The constructor, the implementation macro and environment
312 // dependent methods can be found in the environment's
313 // source file.
314 // ---------------------------------------------------------
~wxDataViewCustomRenderer()315 wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
316 {
317   delete m_DCPtr;
318 }
319 
GetDC()320 wxDC* wxDataViewCustomRenderer::GetDC()
321 {
322   if ((m_DCPtr == NULL) && (GetOwner() != NULL) && (GetOwner()->GetOwner() != NULL))
323     m_DCPtr = new wxClientDC(GetOwner()->GetOwner());
324   return m_DCPtr;
325 }
326 
SetDC(wxDC * newDCPtr)327 void wxDataViewCustomRenderer::SetDC(wxDC* newDCPtr)
328 {
329   delete m_DCPtr;
330   m_DCPtr = newDCPtr;
331 }
332 
333 //-----------------------------------------------------------------------------
334 // wxDataViewCtrl
335 //-----------------------------------------------------------------------------
336 
~wxDataViewCtrl()337 wxDataViewCtrl::~wxDataViewCtrl()
338 {
339   // Notice that we don't call ClearColumns() from here as with Cocoa this
340   // method actually recreates the entire control which is unnecessary when
341   // we're about to dsetroy it and results in unexpected side effects (e.g.
342   // calls to comparison function as the entire contents of the control is
343   // re-added to it and so possibly re-sorted).
344   WX_CLEAR_ARRAY(m_ColumnPtrs);
345 
346   // Ensure that the already destructed controls is not notified about changes
347   // in the model any more.
348   if (m_ModelNotifier != NULL)
349     m_ModelNotifier->GetOwner()->RemoveNotifier(m_ModelNotifier);
350 }
351 
Init()352 void wxDataViewCtrl::Init()
353 {
354   m_CustomRendererPtr = NULL;
355   m_Deleting          = false;
356   m_cgContext         = NULL;
357   m_ModelNotifier     = NULL;
358 }
359 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)360 bool wxDataViewCtrl::Create(wxWindow *parent,
361                             wxWindowID id,
362                             const wxPoint& pos,
363                             const wxSize& size,
364                             long style,
365                             const wxValidator& validator,
366                             const wxString& name)
367 {
368   // Remove wxVSCROLL and wxHSCROLL from the style, since the dataview panel has scrollbars
369   // by default, and wxControl::Create trys to make some but crashes in the process
370   style &= ~(wxVSCROLL | wxHSCROLL);
371 
372   DontCreatePeer();
373   if (!(wxControl::Create(parent,id,pos,size,style,validator,name)))
374     return false;
375   SetPeer(::CreateDataView(this,parent,id,pos,size,style,GetExtraStyle()));
376 
377   MacPostControlCreate(pos,size);
378 
379   return true;
380 }
381 
AssociateModel(wxDataViewModel * model)382 bool wxDataViewCtrl::AssociateModel(wxDataViewModel* model)
383 {
384   wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer());
385 
386 
387   wxCHECK_MSG(dataViewWidgetPtr != NULL,false,"Pointer to native control must not be NULL.");
388 
389   // We could have been associated with another model previously, break the
390   // association in this case.
391   if ( m_ModelNotifier )
392   {
393       m_ModelNotifier->GetOwner()->RemoveNotifier(m_ModelNotifier);
394       m_ModelNotifier = NULL;
395   }
396 
397   if (wxDataViewCtrlBase::AssociateModel(model) && dataViewWidgetPtr->AssociateModel(model))
398   {
399     if (model != NULL)
400     {
401       m_ModelNotifier = new wxOSXDataViewModelNotifier(this);
402       model->AddNotifier(m_ModelNotifier);
403     }
404     return true;
405   }
406   else
407     return false;
408 }
409 
AppendColumn(wxDataViewColumn * columnPtr)410 bool wxDataViewCtrl::AppendColumn(wxDataViewColumn* columnPtr)
411 {
412    return wxDataViewCtrl::InsertColumn( GetColumnCount(), columnPtr );
413 }
414 
PrependColumn(wxDataViewColumn * columnPtr)415 bool wxDataViewCtrl::PrependColumn(wxDataViewColumn* columnPtr)
416 {
417    return wxDataViewCtrl::InsertColumn( 0, columnPtr );
418 }
419 
InsertColumn(unsigned int pos,wxDataViewColumn * columnPtr)420 bool wxDataViewCtrl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
421 {
422   wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer());
423 
424  // first, some error checking:
425   wxCHECK_MSG(dataViewWidgetPtr != NULL,                                         false,"Pointer to native control must not be NULL.");
426   wxCHECK_MSG(columnPtr != NULL,                                                 false,"Column pointer must not be NULL.");
427   wxCHECK_MSG(columnPtr->GetRenderer() != NULL,                                  false,"Column does not have a renderer.");
428 
429  // add column to wxWidget's internal structure:
430   if (wxDataViewCtrlBase::InsertColumn(pos,columnPtr))
431   {
432     m_ColumnPtrs.Add(columnPtr);
433    // if the insertion in the native control is successful the rest can also be initialized:
434     if (dataViewWidgetPtr->InsertColumn(pos,columnPtr))
435     {
436      // make sure that the data is up-to-date...
437      // if the newly appended column is the first column add the initial data to the control and mark the column as an expander column,
438      // otherwise ask the control to 'update' the data in the newly appended column:
439       if (GetColumnCount() == 1)
440         SetExpanderColumn(columnPtr);
441 
442       AdjustAutosizedColumns();
443 
444      // done:
445       return true;
446     }
447     else
448     {
449      // clean-up:
450       m_ColumnPtrs.Remove(columnPtr);
451       delete columnPtr;
452      // and send a message in debug mode:
453       wxFAIL_MSG("Column could not be added to native control.");
454      // failed:
455       return false;
456     }
457   }
458   else
459   {
460    // clean-up:
461     delete columnPtr;
462     wxFAIL_MSG("Could not add column to internal structures.");
463    // failed:
464     return false;
465   }
466 }
467 
ClearColumns()468 bool wxDataViewCtrl::ClearColumns()
469 {
470   if (GetDataViewPeer()->ClearColumns())
471   {
472     WX_CLEAR_ARRAY(m_ColumnPtrs);
473     return true;
474   }
475   else
476     return false;
477 }
478 
DeleteColumn(wxDataViewColumn * columnPtr)479 bool wxDataViewCtrl::DeleteColumn(wxDataViewColumn* columnPtr)
480 {
481   if (GetDataViewPeer()->DeleteColumn(columnPtr))
482   {
483     m_ColumnPtrs.Remove(columnPtr);
484     delete columnPtr;
485 
486     AdjustAutosizedColumns();
487     return true;
488   }
489   else
490     return false;
491 }
492 
GetColumn(unsigned int pos) const493 wxDataViewColumn* wxDataViewCtrl::GetColumn(unsigned int pos) const
494 {
495   return GetDataViewPeer()->GetColumn(pos);
496 }
497 
GetColumnCount() const498 unsigned int wxDataViewCtrl::GetColumnCount() const
499 {
500   return m_ColumnPtrs.GetCount();
501 }
502 
GetColumnPosition(wxDataViewColumn const * columnPtr) const503 int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
504 {
505   return GetDataViewPeer()->GetColumnPosition(columnPtr);
506 }
507 
Collapse(wxDataViewItem const & item)508 void wxDataViewCtrl::Collapse(wxDataViewItem const& item)
509 {
510   GetDataViewPeer()->Collapse(item);
511   AdjustAutosizedColumns();
512 }
513 
EnsureVisible(wxDataViewItem const & item,wxDataViewColumn const * columnPtr)514 void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
515 {
516   if (item.IsOk())
517   {
518     ExpandAncestors(item); // make sure that the item exists in the control
519     GetDataViewPeer()->EnsureVisible(item,columnPtr);
520   }
521 }
522 
DoExpand(wxDataViewItem const & item,bool expandChildren)523 void wxDataViewCtrl::DoExpand(wxDataViewItem const& item, bool expandChildren)
524 {
525   GetDataViewPeer()->DoExpand(item, expandChildren);
526   AdjustAutosizedColumns();
527 }
528 
IsExpanded(const wxDataViewItem & item) const529 bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
530 {
531   return (item.IsOk() && GetDataViewPeer()->IsExpanded(item));
532 }
533 
GetSortingColumn() const534 wxDataViewColumn* wxDataViewCtrl::GetSortingColumn() const
535 {
536   return GetDataViewPeer()->GetSortingColumn();
537 }
538 
GetCount() const539 unsigned int wxDataViewCtrl::GetCount() const
540 {
541   return GetDataViewPeer()->GetCount();
542 }
543 
DoGetCurrentItem() const544 wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
545 {
546     return GetDataViewPeer()->GetCurrentItem();
547 }
548 
DoSetCurrentItem(const wxDataViewItem & item)549 void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
550 {
551     GetDataViewPeer()->SetCurrentItem(item);
552 }
553 
GetCurrentColumn() const554 wxDataViewColumn *wxDataViewCtrl::GetCurrentColumn() const
555 {
556     return GetDataViewPeer()->GetCurrentColumn();
557 }
558 
GetItemRect(wxDataViewItem const & item,wxDataViewColumn const * columnPtr) const559 wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
560 {
561   if ( !item.IsOk() )
562       return wxRect();
563 
564   wxRect rect = GetDataViewPeer()->GetRectangle(item, columnPtr ? columnPtr : GetColumn(0));
565 
566   if ( !columnPtr )
567   {
568       const unsigned columnCount = GetColumnCount();
569       if ( columnCount != 1 )
570       {
571           // Extend the rectangle to the rightmost part of the last column.
572           const wxRect rectLastCol = GetDataViewPeer()->GetRectangle(item, GetColumn(columnCount - 1));
573           rect.SetRight(rectLastCol.GetRight());
574       }
575       //else: We already have the rectangle we need.
576   }
577 
578   return rect;
579 }
580 
GetSelectedItemsCount() const581 int wxDataViewCtrl::GetSelectedItemsCount() const
582 {
583   return GetDataViewPeer()->GetSelectedItemsCount();
584 }
585 
GetSelections(wxDataViewItemArray & sel) const586 int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const
587 {
588   return GetDataViewPeer()->GetSelections(sel);
589 }
590 
GetTopItem() const591 wxDataViewItem wxDataViewCtrl::GetTopItem() const
592 {
593     return GetDataViewPeer()->GetTopItem();
594 }
595 
GetCountPerPage() const596 int wxDataViewCtrl::GetCountPerPage() const
597 {
598     return GetDataViewPeer()->GetCountPerPage();
599 }
600 
HitTest(wxPoint const & point,wxDataViewItem & item,wxDataViewColumn * & columnPtr) const601 void wxDataViewCtrl::HitTest(wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const
602 {
603   return GetDataViewPeer()->HitTest(point,item,columnPtr);
604 }
605 
SetRowHeight(int rowHeight)606 bool wxDataViewCtrl::SetRowHeight(int rowHeight)
607 {
608   GetDataViewPeer()->SetRowHeight(rowHeight);
609   return true;
610 }
611 
IsSelected(wxDataViewItem const & item) const612 bool wxDataViewCtrl::IsSelected(wxDataViewItem const& item) const
613 {
614   return GetDataViewPeer()->IsSelected(item);
615 }
616 
Select(wxDataViewItem const & item)617 void wxDataViewCtrl::Select(wxDataViewItem const& item)
618 {
619   if (item.IsOk())
620   {
621     ExpandAncestors(item); // make sure that the item exists in the control
622     GetDataViewPeer()->Select(item);
623   }
624 }
625 
SelectAll()626 void wxDataViewCtrl::SelectAll()
627 {
628   GetDataViewPeer()->SelectAll();
629 }
630 
SetSelections(wxDataViewItemArray const & sel)631 void wxDataViewCtrl::SetSelections(wxDataViewItemArray const& sel)
632 {
633     wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer());
634 
635     dataViewWidgetPtr->UnselectAll();
636 
637     size_t const noOfSelections = sel.GetCount();
638 
639     size_t i;
640 
641     wxDataViewItem last_parent;
642 
643 
644    // make sure that all to be selected items are visible in the control:
645     for (i = 0; i < noOfSelections; i++)
646     {
647         wxDataViewItem item   = sel[i];
648         wxDataViewItem parent = GetModel()->GetParent( item );
649 
650         if (parent.IsOk() && (parent != last_parent))
651           ExpandAncestors(item);
652         last_parent = parent;
653     }
654 
655     // finally select the items:
656     dataViewWidgetPtr->Select(sel);
657 }
658 
Unselect(wxDataViewItem const & item)659 void wxDataViewCtrl::Unselect(wxDataViewItem const& item)
660 {
661   if (item.IsOk())
662     GetDataViewPeer()->Unselect(item);
663 }
664 
UnselectAll()665 void wxDataViewCtrl::UnselectAll()
666 {
667   GetDataViewPeer()->UnselectAll();
668 }
669 
670 //
671 // implementation
672 //
GetDataViewPeer() const673 wxDataViewWidgetImpl* wxDataViewCtrl::GetDataViewPeer() const
674 {
675   return dynamic_cast<wxDataViewWidgetImpl*>(GetPeer());
676 }
677 
AddChildren(wxDataViewItem const & parentItem)678 void wxDataViewCtrl::AddChildren(wxDataViewItem const& parentItem)
679 {
680   wxDataViewItemArray items;
681 
682   wxCHECK_RET(GetModel() != NULL,"Model pointer not initialized.");
683   GetModel()->GetChildren(parentItem,items);
684   (void) GetModel()->ItemsAdded(parentItem,items);
685 }
686 
EditItem(const wxDataViewItem & item,const wxDataViewColumn * column)687 void wxDataViewCtrl::EditItem(const wxDataViewItem& item, const wxDataViewColumn *column)
688 {
689     GetDataViewPeer()->StartEditor(item, GetColumnPosition(column));
690 }
691 
FinishCustomItemEditing()692 void wxDataViewCtrl::FinishCustomItemEditing()
693 {
694   if (GetCustomRendererItem().IsOk())
695   {
696     GetCustomRendererPtr()->FinishEditing();
697     SetCustomRendererItem(wxDataViewItem());
698     SetCustomRendererPtr (NULL);
699   }
700 }
701 
AdjustAutosizedColumns() const702 void wxDataViewCtrl::AdjustAutosizedColumns() const
703 {
704   if ( m_ModelNotifier )
705     m_ModelNotifier->AdjustAutosizedColumns();
706 }
707 
708 /*static*/
709 wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant WXUNUSED (variant))710 wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
711 {
712     wxVisualAttributes attr;
713 
714     attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
715     attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
716     static wxFont font = wxFont(wxOSX_SYSTEM_FONT_VIEWS);
717     attr.font = font;
718 
719     return attr;
720 }
721 
722 // inherited methods from wxDataViewCtrlBase
DoSetExpanderColumn()723 void wxDataViewCtrl::DoSetExpanderColumn()
724 {
725   if (GetExpanderColumn() != NULL)
726     GetDataViewPeer()->DoSetExpanderColumn(GetExpanderColumn());
727 }
728 
DoSetIndent()729 void wxDataViewCtrl::DoSetIndent()
730 {
731   GetDataViewPeer()->DoSetIndent(GetIndent());
732 }
733 
734 // event handling:
OnSize(wxSizeEvent & event)735 void wxDataViewCtrl::OnSize(wxSizeEvent& event)
736 {
737   unsigned int const noOfColumns = GetColumnCount();
738 
739 
740  // reset DC of all custom renderers because DC has changed:
741   for (unsigned int i=0; i<noOfColumns; ++i)
742   {
743     wxDataViewColumn* dataViewColumnPtr(GetColumn(i));
744 
745     if (dataViewColumnPtr != NULL)
746     {
747       wxDataViewCustomRenderer* dataViewCustomRendererPtr(dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer()));
748 
749       if (dataViewCustomRendererPtr != NULL)
750         dataViewCustomRendererPtr->SetDC(NULL);
751     }
752   }
753 
754  // update the layout of the native control after a size event:
755   GetDataViewPeer()->OnSize();
756 
757   event.Skip();
758 }
759 
DoGetBestSize() const760 wxSize wxDataViewCtrl::DoGetBestSize() const
761 {
762     wxSize best = wxControl::DoGetBestSize();
763     best.y = 80;
764 
765     return best;
766 }
767 
OnMouse(wxMouseEvent & event)768 void wxDataViewCtrl::OnMouse(wxMouseEvent& event)
769 {
770     event.Skip();
771 }
772 
773 wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase);
774 
775 wxBEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase)
776   EVT_SIZE(wxDataViewCtrl::OnSize)
777   EVT_MOTION(wxDataViewCtrl::OnMouse)
778 wxEND_EVENT_TABLE()
779 
780 #endif // !wxHAS_GENERIC_DATAVIEWCTRL
781 
782 #endif // wxUSE_DATAVIEWCTRL
783