]>
Commit | Line | Data |
---|---|---|
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 | // ============================================================================ | |
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; | |
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 | // ============================================================================ | |
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); | |
b06ed2f8 VS |
82 | // adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data |
83 | void AdjustAutosizedColumns(); | |
e86edab0 RR |
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) | |
8d96f54d | 96 | wxFAIL_MSG("Pointer to dataview control must not be NULL"); |
e86edab0 RR |
97 | } |
98 | ||
99 | bool 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 | ||
110 | bool 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 | ||
123 | bool 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 | ||
146 | bool 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 | ||
170 | bool 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 | ||
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: | |
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 | ||
210 | bool 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 | ||
232 | bool wxOSXDataViewModelNotifier::Cleared() | |
233 | { | |
de40d736 | 234 | return m_DataViewCtrlPtr->GetDataViewPeer()->Reload(); |
e86edab0 RR |
235 | } |
236 | ||
237 | void wxOSXDataViewModelNotifier::Resort() | |
238 | { | |
de40d736 | 239 | m_DataViewCtrlPtr->GetDataViewPeer()->Resort(); |
e86edab0 RR |
240 | } |
241 | ||
242 | void 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 | ||
272 | void 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 |
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 | ||
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 | 326 | wxDataViewCustomRenderer::~wxDataViewCustomRenderer() |
e86edab0 | 327 | { |
de40d736 | 328 | delete m_DCPtr; |
e86edab0 RR |
329 | } |
330 | ||
e86edab0 RR |
331 | wxDC* 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 | ||
338 | void wxDataViewCustomRenderer::SetDC(wxDC* newDCPtr) | |
339 | { | |
340 | delete m_DCPtr; | |
341 | m_DCPtr = newDCPtr; | |
342 | } | |
343 | ||
e86edab0 RR |
344 | //----------------------------------------------------------------------------- |
345 | // wxDataViewCtrl | |
346 | //----------------------------------------------------------------------------- | |
347 | ||
348 | wxDataViewCtrl::~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 | ||
358 | void 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 |
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) | |
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 | ||
384 | bool 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 | ||
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 | { | |
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 | ||
466 | bool 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 | ||
477 | bool 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 | ||
489 | wxDataViewColumn* wxDataViewCtrl::GetColumn(unsigned int pos) const | |
490 | { | |
de40d736 | 491 | return GetDataViewPeer()->GetColumn(pos); |
e86edab0 RR |
492 | } |
493 | ||
494 | unsigned int wxDataViewCtrl::GetColumnCount() const | |
495 | { | |
de40d736 | 496 | return m_ColumnPtrs.GetCount(); |
e86edab0 RR |
497 | } |
498 | ||
499 | int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const | |
500 | { | |
de40d736 | 501 | return GetDataViewPeer()->GetColumnPosition(columnPtr); |
e86edab0 RR |
502 | } |
503 | ||
504 | void wxDataViewCtrl::Collapse(wxDataViewItem const& item) | |
505 | { | |
de40d736 | 506 | GetDataViewPeer()->Collapse(item); |
e86edab0 RR |
507 | } |
508 | ||
509 | void 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 | ||
518 | void wxDataViewCtrl::Expand(wxDataViewItem const& item) | |
519 | { | |
de40d736 | 520 | return GetDataViewPeer()->Expand(item); |
e86edab0 RR |
521 | } |
522 | ||
523 | bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const | |
524 | { | |
de40d736 | 525 | return (item.IsOk() && GetDataViewPeer()->IsExpanded(item)); |
e86edab0 RR |
526 | } |
527 | ||
528 | wxDataViewColumn* wxDataViewCtrl::GetSortingColumn() const | |
529 | { | |
de40d736 | 530 | return GetDataViewPeer()->GetSortingColumn(); |
e86edab0 RR |
531 | } |
532 | ||
533 | unsigned int wxDataViewCtrl::GetCount() const | |
534 | { | |
de40d736 | 535 | return GetDataViewPeer()->GetCount(); |
e86edab0 RR |
536 | } |
537 | ||
80ce465c VZ |
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 | ||
ee1377e1 VS |
548 | wxDataViewColumn *wxDataViewCtrl::GetCurrentColumn() const |
549 | { | |
550 | return GetDataViewPeer()->GetCurrentColumn(); | |
551 | } | |
552 | ||
e86edab0 RR |
553 | wxRect 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 | 561 | int wxDataViewCtrl::GetSelectedItemsCount() const |
e86edab0 | 562 | { |
fa93d732 | 563 | return GetDataViewPeer()->GetSelectedItemsCount(); |
e86edab0 RR |
564 | } |
565 | ||
566 | int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const | |
567 | { | |
de40d736 | 568 | return GetDataViewPeer()->GetSelections(sel); |
e86edab0 RR |
569 | } |
570 | ||
571 | void wxDataViewCtrl::HitTest(wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const | |
572 | { | |
de40d736 | 573 | return GetDataViewPeer()->HitTest(point,item,columnPtr); |
e86edab0 RR |
574 | } |
575 | ||
576 | bool wxDataViewCtrl::IsSelected(wxDataViewItem const& item) const | |
577 | { | |
de40d736 | 578 | return GetDataViewPeer()->IsSelected(item); |
e86edab0 RR |
579 | } |
580 | ||
581 | void 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 | 590 | void wxDataViewCtrl::SelectAll() |
e86edab0 | 591 | { |
de40d736 | 592 | GetDataViewPeer()->SelectAll(); |
e86edab0 RR |
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]; | |
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 | ||
622 | void wxDataViewCtrl::Unselect(wxDataViewItem const& item) | |
623 | { | |
624 | if (item.IsOk()) | |
de40d736 | 625 | GetDataViewPeer()->Unselect(item); |
e86edab0 RR |
626 | } |
627 | ||
de40d736 | 628 | void wxDataViewCtrl::UnselectAll() |
e86edab0 | 629 | { |
de40d736 | 630 | GetDataViewPeer()->UnselectAll(); |
e86edab0 RR |
631 | } |
632 | ||
633 | // | |
634 | // implementation | |
635 | // | |
de40d736 | 636 | wxDataViewWidgetImpl* wxDataViewCtrl::GetDataViewPeer() const |
e86edab0 | 637 | { |
de40d736 | 638 | return dynamic_cast<wxDataViewWidgetImpl*>(GetPeer()); |
e86edab0 RR |
639 | } |
640 | ||
641 | void 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 | 653 | void wxDataViewCtrl::EditItem(const wxDataViewItem& item, const wxDataViewColumn *column) |
eeea3b03 | 654 | { |
907f09f4 | 655 | GetDataViewPeer()->StartEditor(item, GetColumnPosition(column)); |
eeea3b03 RD |
656 | } |
657 | ||
de40d736 | 658 | void 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 |
669 | wxVisualAttributes |
670 | wxDataViewCtrl::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 | |
683 | void wxDataViewCtrl::DoSetExpanderColumn() | |
684 | { | |
de40d736 VZ |
685 | if (GetExpanderColumn() != NULL) |
686 | GetDataViewPeer()->DoSetExpanderColumn(GetExpanderColumn()); | |
e86edab0 RR |
687 | } |
688 | ||
689 | void wxDataViewCtrl::DoSetIndent() | |
690 | { | |
de40d736 | 691 | GetDataViewPeer()->DoSetIndent(GetIndent()); |
e86edab0 RR |
692 | } |
693 | ||
694 | // event handling: | |
695 | void 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 |
720 | wxSize wxDataViewCtrl::DoGetBestSize() const |
721 | { | |
722 | wxSize best = wxControl::DoGetBestSize(); | |
723 | best.y = 80; | |
608129e5 | 724 | |
35d85392 RR |
725 | return best; |
726 | } | |
727 | ||
728 | void 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 |
779 | IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase) |
780 | ||
781 | BEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase) | |
782 | EVT_SIZE(wxDataViewCtrl::OnSize) | |
35d85392 | 783 | EVT_MOTION(wxDataViewCtrl::OnMouse) |
e86edab0 RR |
784 | END_EVENT_TABLE() |
785 | ||
786 | #endif // (wxUSE_DATAVIEWCTRL != 0) && (!defined(wxUSE_GENERICDATAVIEWCTRL) || (wxUSE_GENERICDATAVIEWCTRL == 0)) | |
787 |