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