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