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