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