]> git.saurik.com Git - wxWidgets.git/blame - src/osx/dataview_osx.cpp
Support using GetTextExtent() with empty string to get descent in wxOSX.
[wxWidgets.git] / src / osx / dataview_osx.cpp
CommitLineData
e86edab0
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/dataview_osx.cpp
3// Purpose: wxDataViewCtrl native mac implementation
4// Author:
b5b208a1 5// Id: $Id$
e86edab0
RR
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
e86edab0
RR
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
f0e867e9
VZ
23#if wxOSX_USE_CARBON
24#include "wx/osx/carbon/dataview.h"
25#endif
e86edab0
RR
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// ============================================================================
34wxString 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;
608129e5 43
e86edab0
RR
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// ============================================================================
55class wxOSXDataViewModelNotifier : public wxDataViewModelNotifier
56{
57public:
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
76protected:
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);
b06ed2f8
VS
82 // adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data
83 void AdjustAutosizedColumns();
e86edab0
RR
84
85private:
86 wxDataViewCtrl* m_DataViewCtrlPtr;
87};
88
89//
90// constructors / destructor
91//
92wxOSXDataViewModelNotifier::wxOSXDataViewModelNotifier(wxDataViewCtrl* initDataViewCtrlPtr)
93 :m_DataViewCtrlPtr(initDataViewCtrlPtr)
94{
95 if (initDataViewCtrlPtr == NULL)
8d96f54d 96 wxFAIL_MSG("Pointer to dataview control must not be NULL");
e86edab0
RR
97}
98
99bool wxOSXDataViewModelNotifier::ItemAdded(wxDataViewItem const& parent, wxDataViewItem const& item)
100{
101 bool noFailureFlag;
102
103
8d96f54d 104 wxCHECK_MSG(item.IsOk(),false,"Added item is invalid.");
de40d736
VZ
105 noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Add(parent,item);
106 AdjustRowHeight(item);
e86edab0
RR
107 return noFailureFlag;
108}
109
110bool wxOSXDataViewModelNotifier::ItemsAdded(wxDataViewItem const& parent, wxDataViewItemArray const& items)
111{
112 bool noFailureFlag;
113
114
115 // insert all valid items into control:
de40d736 116 noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Add(parent,items);
e86edab0 117 // adjust row heights:
de40d736 118 AdjustRowHeights(items);
e86edab0
RR
119 // done:
120 return noFailureFlag;
121}
122
123bool wxOSXDataViewModelNotifier::ItemChanged(wxDataViewItem const& item)
124{
8d96f54d
VS
125 wxCHECK_MSG(item.IsOk(), false,"Changed item is invalid.");
126 wxCHECK_MSG(GetOwner() != NULL,false,"Owner not initialized.");
de40d736 127 if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(item),item))
e86edab0
RR
128 {
129 // sent the equivalent wxWidget event:
ce7fe42e 130 wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,m_DataViewCtrlPtr->GetId());
e86edab0 131
de40d736 132 dataViewEvent.SetEventObject(m_DataViewCtrlPtr);
e86edab0
RR
133 dataViewEvent.SetItem(item);
134 // sent the equivalent wxWidget event:
de40d736 135 m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
e86edab0 136 // row height may have to be adjusted:
de40d736 137 AdjustRowHeight(item);
b06ed2f8 138 AdjustAutosizedColumns();
e86edab0
RR
139 // done
140 return true;
141 }
142 else
143 return false;
144}
145
146bool wxOSXDataViewModelNotifier::ItemsChanged(wxDataViewItemArray const& items)
147{
148 size_t const noOfItems = items.GetCount();
149
ce7fe42e 150 wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,m_DataViewCtrlPtr->GetId());
e86edab0
RR
151
152
de40d736 153 dataViewEvent.SetEventObject(m_DataViewCtrlPtr);
e86edab0 154 for (size_t indexItem=0; indexItem<noOfItems; ++indexItem)
de40d736 155 if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(items[indexItem]),items[indexItem]))
e86edab0
RR
156 {
157 // send for all changed items a wxWidget event:
158 dataViewEvent.SetItem(items[indexItem]);
de40d736 159 m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
e86edab0
RR
160 }
161 else
162 return false;
163 // if this location is reached all items have been updated:
de40d736 164 AdjustRowHeights(items);
b06ed2f8 165 AdjustAutosizedColumns();
e86edab0
RR
166 // done:
167 return true;
168}
169
170bool wxOSXDataViewModelNotifier::ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
171{
172 bool noFailureFlag;
173
174
8d96f54d 175 wxCHECK_MSG(item.IsOk(),false,"To be deleted item is invalid.");
e86edab0
RR
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:
de40d736
VZ
180 m_DataViewCtrlPtr->SetDeleting(true);
181 noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,item);
e86edab0 182 // enable automatic updating again:
de40d736 183 m_DataViewCtrlPtr->SetDeleting(false);
b06ed2f8
VS
184
185 AdjustAutosizedColumns();
e86edab0
RR
186 // done:
187 return noFailureFlag;
188}
189
190bool 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:
de40d736 199 m_DataViewCtrlPtr->SetDeleting(true);
e86edab0 200 // delete all specified items:
de40d736 201 noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,items);
e86edab0 202 // enable automatic updating again:
de40d736 203 m_DataViewCtrlPtr->SetDeleting(false);
b06ed2f8
VS
204
205 AdjustAutosizedColumns();
e86edab0
RR
206 // done:
207 return noFailureFlag;
208}
209
210bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsigned int col)
211{
8d96f54d
VS
212 wxCHECK_MSG(item.IsOk(), false,"Passed item is invalid.");
213 wxCHECK_MSG(GetOwner() != NULL,false,"Owner not initialized.");
de40d736 214 if (m_DataViewCtrlPtr->GetDataViewPeer()->Update(GetOwner()->GetParent(item),item))
e86edab0 215 {
ce7fe42e 216 wxDataViewEvent dataViewEvent(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,m_DataViewCtrlPtr->GetId());
e86edab0 217
de40d736 218 dataViewEvent.SetEventObject(m_DataViewCtrlPtr);
e86edab0
RR
219 dataViewEvent.SetColumn(col);
220 dataViewEvent.SetItem(item);
221 // send the equivalent wxWidget event:
de40d736 222 m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
b06ed2f8
VS
223
224 AdjustAutosizedColumns();
e86edab0
RR
225 // done
226 return true;
227 }
228 else
229 return false;
230}
231
232bool wxOSXDataViewModelNotifier::Cleared()
233{
de40d736 234 return m_DataViewCtrlPtr->GetDataViewPeer()->Reload();
e86edab0
RR
235}
236
237void wxOSXDataViewModelNotifier::Resort()
238{
de40d736 239 m_DataViewCtrlPtr->GetDataViewPeer()->Resort();
e86edab0
RR
240}
241
242void wxOSXDataViewModelNotifier::AdjustRowHeight(wxDataViewItem const& item)
243{
de40d736 244 if ((m_DataViewCtrlPtr->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) != 0)
e86edab0 245 {
de40d736 246 wxDataViewModel *model = GetOwner();
e86edab0
RR
247
248 int height = 20; // TODO find out standard height
de40d736 249 unsigned int num = m_DataViewCtrlPtr->GetColumnCount();
e86edab0
RR
250 unsigned int col;
251 for (col = 0; col < num; col++)
252 {
de40d736 253 wxDataViewColumn* column(m_DataViewCtrlPtr->GetColumnPtr(col));
608129e5 254
e86edab0
RR
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)
de40d736 268 m_DataViewCtrlPtr->GetDataViewPeer()->SetRowHeight(item,height);
e86edab0
RR
269 }
270}
271
272void wxOSXDataViewModelNotifier::AdjustRowHeights(wxDataViewItemArray const& items)
273{
de40d736 274 if ((m_DataViewCtrlPtr->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) != 0)
e86edab0
RR
275 {
276 size_t const noOfItems = items.GetCount();
277
de40d736 278 wxDataViewModel *model = GetOwner();
e86edab0
RR
279
280 for (size_t itemIndex=0; itemIndex<noOfItems; ++itemIndex)
281 {
282 int height = 20; // TODO find out standard height
de40d736 283 unsigned int num = m_DataViewCtrlPtr->GetColumnCount();
e86edab0
RR
284 unsigned int col;
285
286 for (col = 0; col < num; col++)
287 {
de40d736 288 wxDataViewColumn* column(m_DataViewCtrlPtr->GetColumnPtr(col));
608129e5 289
e86edab0
RR
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)
de40d736 303 m_DataViewCtrlPtr->GetDataViewPeer()->SetRowHeight(items[itemIndex],height);
e86edab0
RR
304 }
305 }
306}
307
b06ed2f8
VS
308void 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
e86edab0
RR
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// ---------------------------------------------------------
de40d736 326wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
e86edab0 327{
de40d736 328 delete m_DCPtr;
e86edab0
RR
329}
330
e86edab0
RR
331wxDC* wxDataViewCustomRenderer::GetDC()
332{
de40d736
VZ
333 if ((m_DCPtr == NULL) && (GetOwner() != NULL) && (GetOwner()->GetOwner() != NULL))
334 m_DCPtr = new wxClientDC(GetOwner()->GetOwner());
335 return m_DCPtr;
e86edab0
RR
336}
337
338void wxDataViewCustomRenderer::SetDC(wxDC* newDCPtr)
339{
340 delete m_DCPtr;
341 m_DCPtr = newDCPtr;
342}
343
e86edab0
RR
344//-----------------------------------------------------------------------------
345// wxDataViewCtrl
346//-----------------------------------------------------------------------------
347
348wxDataViewCtrl::~wxDataViewCtrl()
349{
de40d736 350 ClearColumns();
a2c3fc7c
VZ
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);
e86edab0
RR
356}
357
358void wxDataViewCtrl::Init()
359{
360 m_CustomRendererPtr = NULL;
361 m_Deleting = false;
e86edab0 362 m_cgContext = NULL;
a2c3fc7c 363 m_ModelNotifier = NULL;
e86edab0
RR
364}
365
62e9285a
VZ
366bool 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)
e86edab0 373{
d15694e8 374 DontCreatePeer();
62e9285a 375 if (!(wxControl::Create(parent,id,pos,size,style,validator,name)))
e86edab0 376 return false;
22756322 377 SetPeer(::CreateDataView(this,parent,id,pos,size,style,GetExtraStyle()));
e86edab0 378
de40d736 379 MacPostControlCreate(pos,size);
e86edab0
RR
380
381 return true;
382}
383
384bool wxDataViewCtrl::AssociateModel(wxDataViewModel* model)
385{
de40d736 386 wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer());
e86edab0
RR
387
388
8d96f54d 389 wxCHECK_MSG(dataViewWidgetPtr != NULL,false,"Pointer to native control must not be NULL.");
a2c3fc7c
VZ
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
e86edab0
RR
396 if (wxDataViewCtrlBase::AssociateModel(model) && dataViewWidgetPtr->AssociateModel(model))
397 {
398 if (model != NULL)
a2c3fc7c
VZ
399 {
400 m_ModelNotifier = new wxOSXDataViewModelNotifier(this);
401 model->AddNotifier(m_ModelNotifier);
402 }
e86edab0
RR
403 return true;
404 }
405 else
406 return false;
407}
408
409bool wxDataViewCtrl::AppendColumn(wxDataViewColumn* columnPtr)
410{
411 return wxDataViewCtrl::InsertColumn( GetColumnCount(), columnPtr );
412}
413
414bool wxDataViewCtrl::PrependColumn(wxDataViewColumn* columnPtr)
415{
416 return wxDataViewCtrl::InsertColumn( 0, columnPtr );
417}
418
419bool wxDataViewCtrl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
420{
de40d736 421 wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer());
e86edab0
RR
422
423 // first, some error checking:
8d96f54d
VS
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.");
450b4305 428 wxCHECK_MSG(columnPtr->GetModelColumn() < GetModel()->GetColumnCount(),false,"Column's model column has no equivalent in the associated model.");
e86edab0
RR
429
430 // add column to wxWidget's internal structure:
de40d736 431 if (wxDataViewCtrlBase::InsertColumn(pos,columnPtr))
e86edab0 432 {
de40d736 433 m_ColumnPtrs.Add(columnPtr);
e86edab0
RR
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:
de40d736
VZ
440 if (GetColumnCount() == 1)
441 SetExpanderColumn(columnPtr);
e86edab0
RR
442 // done:
443 return true;
444 }
445 else
446 {
447 // clean-up:
de40d736 448 m_ColumnPtrs.Remove(columnPtr);
e86edab0
RR
449 delete columnPtr;
450 // and send a message in debug mode:
8d96f54d 451 wxFAIL_MSG("Column could not be added to native control.");
e86edab0
RR
452 // failed:
453 return false;
454 }
455 }
456 else
457 {
458 // clean-up:
459 delete columnPtr;
8d96f54d 460 wxFAIL_MSG("Could not add column to internal structures.");
e86edab0
RR
461 // failed:
462 return false;
463 }
464}
465
466bool wxDataViewCtrl::ClearColumns()
467{
de40d736 468 if (GetDataViewPeer()->ClearColumns())
e86edab0 469 {
de40d736 470 WX_CLEAR_ARRAY(m_ColumnPtrs);
e86edab0
RR
471 return true;
472 }
473 else
474 return false;
475}
476
477bool wxDataViewCtrl::DeleteColumn(wxDataViewColumn* columnPtr)
478{
de40d736 479 if (GetDataViewPeer()->DeleteColumn(columnPtr))
e86edab0 480 {
de40d736 481 m_ColumnPtrs.Remove(columnPtr);
e86edab0
RR
482 delete columnPtr;
483 return true;
484 }
485 else
486 return false;
487}
488
489wxDataViewColumn* wxDataViewCtrl::GetColumn(unsigned int pos) const
490{
de40d736 491 return GetDataViewPeer()->GetColumn(pos);
e86edab0
RR
492}
493
494unsigned int wxDataViewCtrl::GetColumnCount() const
495{
de40d736 496 return m_ColumnPtrs.GetCount();
e86edab0
RR
497}
498
499int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
500{
de40d736 501 return GetDataViewPeer()->GetColumnPosition(columnPtr);
e86edab0
RR
502}
503
504void wxDataViewCtrl::Collapse(wxDataViewItem const& item)
505{
de40d736 506 GetDataViewPeer()->Collapse(item);
e86edab0
RR
507}
508
509void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
510{
511 if (item.IsOk())
512 {
de40d736
VZ
513 ExpandAncestors(item); // make sure that the item exists in the control
514 GetDataViewPeer()->EnsureVisible(item,columnPtr);
e86edab0
RR
515 }
516}
517
518void wxDataViewCtrl::Expand(wxDataViewItem const& item)
519{
de40d736 520 return GetDataViewPeer()->Expand(item);
e86edab0
RR
521}
522
523bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
524{
de40d736 525 return (item.IsOk() && GetDataViewPeer()->IsExpanded(item));
e86edab0
RR
526}
527
528wxDataViewColumn* wxDataViewCtrl::GetSortingColumn() const
529{
de40d736 530 return GetDataViewPeer()->GetSortingColumn();
e86edab0
RR
531}
532
533unsigned int wxDataViewCtrl::GetCount() const
534{
de40d736 535 return GetDataViewPeer()->GetCount();
e86edab0
RR
536}
537
80ce465c
VZ
538wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
539{
540 return GetDataViewPeer()->GetCurrentItem();
541}
542
543void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
544{
545 GetDataViewPeer()->SetCurrentItem(item);
546}
547
ee1377e1
VS
548wxDataViewColumn *wxDataViewCtrl::GetCurrentColumn() const
549{
550 return GetDataViewPeer()->GetCurrentColumn();
551}
552
e86edab0
RR
553wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
554{
555 if (item.IsOk() && (columnPtr != NULL))
de40d736 556 return GetDataViewPeer()->GetRectangle(item,columnPtr);
e86edab0
RR
557 else
558 return wxRect();
559}
560
fa93d732 561int wxDataViewCtrl::GetSelectedItemsCount() const
e86edab0 562{
fa93d732 563 return GetDataViewPeer()->GetSelectedItemsCount();
e86edab0
RR
564}
565
566int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const
567{
de40d736 568 return GetDataViewPeer()->GetSelections(sel);
e86edab0
RR
569}
570
571void wxDataViewCtrl::HitTest(wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const
572{
de40d736 573 return GetDataViewPeer()->HitTest(point,item,columnPtr);
e86edab0
RR
574}
575
576bool wxDataViewCtrl::IsSelected(wxDataViewItem const& item) const
577{
de40d736 578 return GetDataViewPeer()->IsSelected(item);
e86edab0
RR
579}
580
581void wxDataViewCtrl::Select(wxDataViewItem const& item)
582{
583 if (item.IsOk())
584 {
de40d736
VZ
585 ExpandAncestors(item); // make sure that the item exists in the control
586 GetDataViewPeer()->Select(item);
e86edab0
RR
587 }
588}
589
de40d736 590void wxDataViewCtrl::SelectAll()
e86edab0 591{
de40d736 592 GetDataViewPeer()->SelectAll();
e86edab0
RR
593}
594
595void 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];
de40d736 608 wxDataViewItem parent = GetModel()->GetParent( item );
e86edab0
RR
609
610 if (parent.IsOk() && (parent != last_parent))
de40d736 611 ExpandAncestors(item);
e86edab0
RR
612 last_parent = parent;
613 }
614
615 // finally select the items:
de40d736 616 wxDataViewWidgetImpl* dataViewWidgetPtr(GetDataViewPeer()); // variable definition for abbreviational purposes
e86edab0
RR
617
618 for (i=0; i<noOfSelections; ++i)
619 dataViewWidgetPtr->Select(sel[i]);
620}
621
622void wxDataViewCtrl::Unselect(wxDataViewItem const& item)
623{
624 if (item.IsOk())
de40d736 625 GetDataViewPeer()->Unselect(item);
e86edab0
RR
626}
627
de40d736 628void wxDataViewCtrl::UnselectAll()
e86edab0 629{
de40d736 630 GetDataViewPeer()->UnselectAll();
e86edab0
RR
631}
632
633//
634// implementation
635//
de40d736 636wxDataViewWidgetImpl* wxDataViewCtrl::GetDataViewPeer() const
e86edab0 637{
de40d736 638 return dynamic_cast<wxDataViewWidgetImpl*>(GetPeer());
e86edab0
RR
639}
640
641void wxDataViewCtrl::AddChildren(wxDataViewItem const& parentItem)
642{
643 int noOfChildren;
644
645 wxDataViewItemArray items;
646
647
8d96f54d 648 wxCHECK_RET(GetModel() != NULL,"Model pointer not initialized.");
de40d736
VZ
649 noOfChildren = GetModel()->GetChildren(parentItem,items);
650 (void) GetModel()->ItemsAdded(parentItem,items);
e86edab0
RR
651}
652
907f09f4 653void wxDataViewCtrl::EditItem(const wxDataViewItem& item, const wxDataViewColumn *column)
eeea3b03 654{
907f09f4 655 GetDataViewPeer()->StartEditor(item, GetColumnPosition(column));
eeea3b03
RD
656}
657
de40d736 658void wxDataViewCtrl::FinishCustomItemEditing()
e86edab0 659{
de40d736 660 if (GetCustomRendererItem().IsOk())
e86edab0 661 {
de40d736
VZ
662 GetCustomRendererPtr()->FinishEditing();
663 SetCustomRendererItem(wxDataViewItem());
664 SetCustomRendererPtr (NULL);
e86edab0
RR
665 }
666}
667
668/*static*/
8f2a8de6
VZ
669wxVisualAttributes
670wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
e86edab0
RR
671{
672 wxVisualAttributes attr;
673
674 attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
675 attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
7eb8aeb8
SC
676 static wxFont font = wxFont(wxOSX_SYSTEM_FONT_VIEWS);
677 attr.font = font;
e86edab0
RR
678
679 return attr;
680}
681
682// inherited methods from wxDataViewCtrlBase
683void wxDataViewCtrl::DoSetExpanderColumn()
684{
de40d736
VZ
685 if (GetExpanderColumn() != NULL)
686 GetDataViewPeer()->DoSetExpanderColumn(GetExpanderColumn());
e86edab0
RR
687}
688
689void wxDataViewCtrl::DoSetIndent()
690{
de40d736 691 GetDataViewPeer()->DoSetIndent(GetIndent());
e86edab0
RR
692}
693
694// event handling:
695void wxDataViewCtrl::OnSize(wxSizeEvent& event)
696{
de40d736 697 unsigned int const noOfColumns = GetColumnCount();
e86edab0
RR
698
699
700 // reset DC of all custom renderers because DC has changed:
701 for (unsigned int i=0; i<noOfColumns; ++i)
702 {
de40d736 703 wxDataViewColumn* dataViewColumnPtr(GetColumn(i));
e86edab0
RR
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:
de40d736 715 GetDataViewPeer()->OnSize();
e86edab0
RR
716
717 event.Skip();
718}
719
35d85392
RR
720wxSize wxDataViewCtrl::DoGetBestSize() const
721{
722 wxSize best = wxControl::DoGetBestSize();
723 best.y = 80;
608129e5 724
35d85392
RR
725 return best;
726}
727
728void wxDataViewCtrl::OnMouse(wxMouseEvent& event)
729{
730 event.Skip();
608129e5 731
f0e867e9 732#if wxOSX_USE_CARBON
35d85392
RR
733 if (GetModel() == NULL)
734 return;
735
1f920487 736 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(GetPeer()));
35d85392
RR
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);
608129e5
VZ
747
748
35d85392
RR
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;
608129e5 758
35d85392 759 Rect itemrect;
608129e5 760 ::GetDataBrowserItemPartBounds( MacDataViewListCtrlPtr->GetControlRef(),
1f920487 761 reinterpret_cast<DataBrowserItemID>(firstChild.GetID()), column->GetNativeData()->GetPropertyID(),
35d85392 762 kDataBrowserPropertyEnclosingPart, &itemrect );
608129e5 763
35d85392
RR
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 }
608129e5 773
35d85392 774 }
35d85392
RR
775 SetCursor( *wxSTANDARD_CURSOR );
776#endif
777}
778
e86edab0
RR
779IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase)
780
781BEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase)
782 EVT_SIZE(wxDataViewCtrl::OnSize)
35d85392 783 EVT_MOTION(wxDataViewCtrl::OnMouse)
e86edab0
RR
784END_EVENT_TABLE()
785
786#endif // (wxUSE_DATAVIEWCTRL != 0) && (!defined(wxUSE_GENERICDATAVIEWCTRL) || (wxUSE_GENERICDATAVIEWCTRL == 0))
787