Merge in from trunk r68626 - r68683
[wxWidgets.git] / src / osx / carbon / dataview.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/dataview.cpp
3 // Purpose: wxDataViewCtrl native carbon implementation
4 // Author:
5 // Id: $Id: dataview.cpp 58317 2009-01-23
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 == 1) && !defined(wxUSE_GENERICDATAVIEWCTRL)
14
15 #ifndef WX_PRECOMP
16 #include "wx/app.h"
17 #include "wx/toplevel.h"
18 #include "wx/font.h"
19 #include "wx/settings.h"
20 #include "wx/utils.h"
21 #endif
22
23 #include "wx/osx/carbon/dataview.h"
24 #include "wx/osx/private.h"
25 #include "wx/osx/uma.h"
26 #include "wx/renderer.h"
27
28 #include <limits>
29
30 // ============================================================================
31 // Variables used locally in dataview.cpp
32 // ============================================================================
33 static DataBrowserGetContextualMenuUPP gDataBrowserTableViewGetContextualMenuUPP = NULL;
34 static DataBrowserItemCompareUPP gDataBrowserTableViewItemCompareUPP = NULL;
35 static DataBrowserItemDataUPP gDataBrowserTableViewItemDataUPP = NULL;
36 static DataBrowserItemNotificationUPP gDataBrowserTableViewItemNotificationUPP = NULL;
37
38 static DataBrowserAcceptDragUPP gDataBrowserTableViewAcceptDragUPP = NULL;
39 static DataBrowserAddDragItemUPP gDataBrowserTableViewAddDragItemUPP = NULL;
40 static DataBrowserReceiveDragUPP gDataBrowserTableViewReceiveDragUPP = NULL;
41
42 static DataBrowserDrawItemUPP gDataBrowserTableViewDrawItemUPP = NULL;
43 static DataBrowserEditItemUPP gDataBrowserTableViewEditItemUPP = NULL;
44 static DataBrowserHitTestUPP gDataBrowserTableViewHitTestUPP = NULL;
45 static DataBrowserTrackingUPP gDataBrowserTableViewTrackingUPP = NULL;
46
47 // ============================================================================
48 // Functions used locally in dataview.cpp
49 // ============================================================================
50 static DataBrowserItemID* CreateDataBrowserItemIDArray(size_t& noOfEntries, wxDataViewItemArray const& items) // returns a newly allocated pointer to valid data browser item IDs
51 {
52 size_t const noOfItems = items.GetCount();
53
54 DataBrowserItemID* itemIDs(new DataBrowserItemID[noOfItems]);
55
56
57 // convert all valid data view items to data browser items
58 noOfEntries = 0;
59 for (size_t i=0; i<noOfItems; ++i)
60 if (items[i].IsOk())
61 {
62 itemIDs[noOfEntries] = reinterpret_cast<DataBrowserItemID>(items[i].GetID());
63 ++noOfEntries;
64 }
65 // done:
66 return itemIDs;
67 }
68
69 static const EventTypeSpec eventList[] =
70 {
71 { kEventClassControl, kEventControlHit },
72 { kEventClassControl, kEventControlDraw }
73 };
74
75 static pascal OSStatus DataBrowserCtrlEventHandler(EventHandlerCallRef handler, EventRef EventReference, void* Data)
76 {
77 wxDataViewCtrl* DataViewCtrlPtr((wxDataViewCtrl*) Data); // the 'Data' variable always contains a pointer to the data view control that installed the handler
78
79 wxMacCarbonEvent CarbonEvent(EventReference) ;
80
81
82 switch (GetEventKind(EventReference))
83 {
84 case kEventControlDraw:
85 {
86 OSStatus status;
87
88 DataViewCtrlPtr->MacSetDrawingContext(CarbonEvent.GetParameter<CGContextRef>(kEventParamCGContextRef,typeCGContextRef));
89 status = ::CallNextEventHandler(handler,EventReference);
90 DataViewCtrlPtr->MacSetDrawingContext(NULL);
91 return status;
92 }
93 case kEventControlHit :
94 if (CarbonEvent.GetParameter<ControlPartCode>(kEventParamControlPart,typeControlPartCode) == kControlButtonPart) // we only care about the header
95 {
96 ControlRef controlReference;
97 DataBrowserPropertyID columnPropertyID;
98 DataBrowserSortOrder order;
99 unsigned long columnIndex;
100 wxDataViewColumn* column;
101 OSStatus status;
102 wxDataViewEvent DataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK,DataViewCtrlPtr->GetId());
103
104 CarbonEvent.GetParameter(kEventParamDirectObject,&controlReference);
105 // determine the column that triggered the event (this is the column that is responsible for sorting the data view):
106 status = ::GetDataBrowserSortProperty(controlReference,&columnPropertyID);
107 wxCHECK(status == noErr,status);
108 status = ::GetDataBrowserTableViewColumnPosition(controlReference,columnPropertyID,&columnIndex);
109 if (status == errDataBrowserPropertyNotFound) // user clicked into part of the header that does not have a property
110 return ::CallNextEventHandler(handler,EventReference);
111 wxCHECK(status == noErr,status);
112 column = DataViewCtrlPtr->GetColumn(columnIndex);
113 // set the column sort order:
114 status = ::GetDataBrowserSortOrder(controlReference,&order);
115 wxCHECK(status == noErr,status);
116 column->SetSortOrderVariable(order == kDataBrowserOrderIncreasing);
117 // initialize wxWidget event handler:
118 DataViewEvent.SetEventObject(DataViewCtrlPtr);
119 DataViewEvent.SetColumn(columnIndex);
120 DataViewEvent.SetDataViewColumn(column);
121 // finally sent the equivalent wxWidget event:
122 DataViewCtrlPtr->HandleWindowEvent(DataViewEvent);
123 return ::CallNextEventHandler(handler,EventReference);
124 }
125 else
126 return eventNotHandledErr;
127 }
128 return eventNotHandledErr;
129 }
130
131 static bool InitializeColumnDescription(DataBrowserListViewColumnDesc& columnDescription, wxDataViewColumn const* columnPtr, wxCFStringRef const& title)
132 {
133 // set properties for the column:
134 columnDescription.propertyDesc.propertyID = columnPtr->GetNativeData()->GetPropertyID();
135 columnDescription.propertyDesc.propertyType = columnPtr->GetRenderer()->GetNativeData()->GetPropertyType();
136 columnDescription.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn; // make the column selectable
137 if (columnPtr->IsReorderable())
138 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewMovableColumn;
139 if (columnPtr->IsResizeable())
140 {
141 columnDescription.headerBtnDesc.minimumWidth = 0;
142 columnDescription.headerBtnDesc.maximumWidth = 30000; // 32767 is the theoretical maximum though but 30000 looks nicer
143 }
144 else
145 {
146 columnDescription.headerBtnDesc.minimumWidth = columnPtr->GetWidth();
147 columnDescription.headerBtnDesc.maximumWidth = columnPtr->GetWidth();
148 }
149 if (columnPtr->IsSortable())
150 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewSortableColumn;
151 if ((columnPtr->GetRenderer()->GetMode() == wxDATAVIEW_CELL_EDITABLE) ||
152 (columnPtr->GetRenderer()->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE))
153 columnDescription.propertyDesc.propertyFlags |= kDataBrowserPropertyIsEditable;
154 if ((columnDescription.propertyDesc.propertyType == kDataBrowserCustomType) ||
155 (columnDescription.propertyDesc.propertyType == kDataBrowserDateTimeType) ||
156 (columnDescription.propertyDesc.propertyType == kDataBrowserIconAndTextType) ||
157 (columnDescription.propertyDesc.propertyType == kDataBrowserTextType))
158 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn; // enables generally the possibility to have user input for the mentioned types
159 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
160 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewNoGapForIconInHeaderButton;
161 #endif
162 // set header's properties:
163 columnDescription.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
164 columnDescription.headerBtnDesc.titleOffset = 0;
165 columnDescription.headerBtnDesc.titleString = ::CFStringCreateCopy(kCFAllocatorDefault,title);
166 columnDescription.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing; // choose one of the orders as "undefined" is not supported anyway (s. ControlDefs.h in the HIToolbox framework)
167 columnDescription.headerBtnDesc.btnFontStyle.flags = kControlUseFontMask | kControlUseJustMask;
168 switch (columnPtr->GetAlignment())
169 {
170 case wxALIGN_CENTER:
171 case wxALIGN_CENTER_HORIZONTAL:
172 columnDescription.headerBtnDesc.btnFontStyle.just = teCenter;
173 break;
174 case wxALIGN_LEFT:
175 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushLeft;
176 break;
177 case wxALIGN_RIGHT:
178 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushRight;
179 break;
180 default:
181 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushDefault;
182 }
183 columnDescription.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
184 columnDescription.headerBtnDesc.btnFontStyle.style = normal;
185 if (columnPtr->GetBitmap().IsOk())
186 {
187 columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
188 columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = columnPtr->GetBitmap().GetIconRef();
189 }
190 else
191 {
192 // not text only as we otherwise could not add a bitmap later
193 // columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
194 columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
195 columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = NULL;
196 }
197
198 // done:
199 return true;
200 }
201
202 // ============================================================================
203 // Type definitions of locally used function pointers
204 // ============================================================================
205 DEFINE_ONE_SHOT_HANDLER_GETTER(DataBrowserCtrlEventHandler)
206
207 // ============================================================================
208 // Helper functions for dataview implementation on OSX
209 // ============================================================================
210 wxWidgetImplType* CreateDataView(wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(parent), wxWindowID WXUNUSED(id), wxPoint const& pos, wxSize const& size,
211 long style, long WXUNUSED(extraStyle))
212 {
213 return new wxMacDataViewDataBrowserListViewControl(wxpeer,pos,size,style);
214 }
215
216 // ============================================================================
217 // wxMacDataBrowserTableViewControl
218 // ============================================================================
219 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserCompareProc(ControlRef browser, DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
220 {
221 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
222
223
224 if (ControlPtr != NULL)
225 return ControlPtr->DataBrowserCompareProc(itemOneID,itemTwoID,sortProperty);
226 else
227 return FALSE;
228 }
229
230 pascal void wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc(ControlRef browser, MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* selection)
231 {
232 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
233
234
235 if (ControlPtr != NULL)
236 ControlPtr->DataBrowserGetContextualMenuProc(menu,helpType,helpItemString,selection);
237 }
238
239 pascal OSStatus wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
240 {
241 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
242
243
244 if (ControlPtr != NULL)
245 return ControlPtr->DataBrowserGetSetItemDataProc(itemID,propertyID,itemData,getValue);
246 else
247 return errDataBrowserPropertyNotSupported;
248 }
249
250 pascal void wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
251 {
252 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
253
254
255 if (ControlPtr != NULL)
256 ControlPtr->DataBrowserItemNotificationProc(itemID,message,itemData);
257 }
258
259 pascal void wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemState state, Rect const* rectangle, SInt16 bitDepth, Boolean colorDevice)
260 {
261 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
262
263
264 if (ControlPtr != NULL)
265 ControlPtr->DataBrowserDrawItemProc(itemID,propertyID,state,rectangle,bitDepth,colorDevice);
266 }
267
268 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserEditItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
269 {
270 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
271
272
273 return ((ControlPtr != NULL) && ControlPtr->DataBrowserEditItemProc(itemID,propertyID,theString,maxEditTextRect,shrinkToFit));
274 }
275
276 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserHitTestProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Rect const* mouseRect)
277 {
278 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
279
280
281 return ((ControlPtr != NULL) && ControlPtr->DataBrowserHitTestProc(itemID,propertyID,theRect,mouseRect));
282 }
283
284 pascal DataBrowserTrackingResult wxMacDataBrowserTableViewControl::DataBrowserTrackingProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point startPt, EventModifiers modifiers)
285 {
286 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
287
288
289 if (ControlPtr != NULL)
290 return ControlPtr->DataBrowserTrackingProc(itemID,propertyID,theRect,startPt,modifiers);
291 else
292 return kDataBrowserNothingHit;
293 }
294
295 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserAcceptDragProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID)
296 {
297 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
298
299
300 return ((controlPtr != NULL) && controlPtr->DataBrowserAcceptDragProc(dragRef,itemID));
301 }
302
303 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserAddDragItemProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
304 {
305 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
306
307
308 return ((controlPtr != NULL) && controlPtr->DataBrowserAddDragItemProc(dragRef,itemID,itemRef));
309 }
310
311 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserReceiveDragProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID)
312 {
313 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
314
315
316 return ((controlPtr != NULL) && controlPtr->DataBrowserReceiveDragProc(dragRef,itemID));
317 }
318
319 wxMacDataBrowserTableViewControl::wxMacDataBrowserTableViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
320 :wxMacControl(peer)
321 {
322 Rect bounds = wxMacGetBoundsForControl(peer,pos,size);
323 OSStatus err = ::CreateDataBrowserControl(MAC_WXHWND(peer->MacGetTopLevelWindowRef()),&bounds,kDataBrowserListView,&(m_controlRef));
324
325
326 SetReferenceInNativeControl();
327 verify_noerr(err);
328
329 ::InstallControlEventHandler(m_controlRef, GetDataBrowserCtrlEventHandlerUPP(), GetEventTypeCount(eventList), eventList, peer, (EventHandlerRef *)&m_macDataViewCtrlEventHandler);
330
331 // setup standard callbacks:
332 if (gDataBrowserTableViewGetContextualMenuUPP == NULL) gDataBrowserTableViewGetContextualMenuUPP = NewDataBrowserGetContextualMenuUPP(wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc);
333 if (gDataBrowserTableViewItemCompareUPP == NULL) gDataBrowserTableViewItemCompareUPP = NewDataBrowserItemCompareUPP (wxMacDataBrowserTableViewControl::DataBrowserCompareProc);
334 if (gDataBrowserTableViewItemDataUPP == NULL) gDataBrowserTableViewItemDataUPP = NewDataBrowserItemDataUPP (wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc);
335 if (gDataBrowserTableViewItemNotificationUPP == NULL)
336 {
337 gDataBrowserTableViewItemNotificationUPP =
338 #if TARGET_API_MAC_OSX
339 (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
340 #else
341 NewDataBrowserItemNotificationUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
342 #endif
343 }
344 // setup drag and drop callbacks:
345 if (gDataBrowserTableViewAcceptDragUPP == NULL) gDataBrowserTableViewAcceptDragUPP = NewDataBrowserAcceptDragUPP (wxMacDataBrowserTableViewControl::DataBrowserAcceptDragProc);
346 if (gDataBrowserTableViewAddDragItemUPP == NULL) gDataBrowserTableViewAddDragItemUPP = NewDataBrowserAddDragItemUPP(wxMacDataBrowserTableViewControl::DataBrowserAddDragItemProc);
347 if (gDataBrowserTableViewReceiveDragUPP == NULL) gDataBrowserTableViewReceiveDragUPP = NewDataBrowserReceiveDragUPP(wxMacDataBrowserTableViewControl::DataBrowserReceiveDragProc);
348
349 DataBrowserCallbacks callbacks; // variable definition
350
351 InitializeDataBrowserCallbacks(&callbacks,kDataBrowserLatestCallbacks);
352 callbacks.u.v1.getContextualMenuCallback = gDataBrowserTableViewGetContextualMenuUPP;
353 callbacks.u.v1.itemDataCallback = gDataBrowserTableViewItemDataUPP;
354 callbacks.u.v1.itemCompareCallback = gDataBrowserTableViewItemCompareUPP;
355 callbacks.u.v1.itemNotificationCallback = gDataBrowserTableViewItemNotificationUPP;
356 callbacks.u.v1.acceptDragCallback = gDataBrowserTableViewAcceptDragUPP;
357 callbacks.u.v1.addDragItemCallback = gDataBrowserTableViewAddDragItemUPP;
358 callbacks.u.v1.receiveDragCallback = gDataBrowserTableViewReceiveDragUPP;
359 SetCallbacks(&callbacks);
360
361 // setup callbacks for customized items:
362 if (gDataBrowserTableViewDrawItemUPP == NULL) gDataBrowserTableViewDrawItemUPP = NewDataBrowserDrawItemUPP(wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc);
363 if (gDataBrowserTableViewEditItemUPP == NULL) gDataBrowserTableViewEditItemUPP = NewDataBrowserEditItemUPP(wxMacDataBrowserTableViewControl::DataBrowserEditItemProc);
364 if (gDataBrowserTableViewHitTestUPP == NULL) gDataBrowserTableViewHitTestUPP = NewDataBrowserHitTestUPP (wxMacDataBrowserTableViewControl::DataBrowserHitTestProc);
365 if (gDataBrowserTableViewTrackingUPP == NULL) gDataBrowserTableViewTrackingUPP = NewDataBrowserTrackingUPP(wxMacDataBrowserTableViewControl::DataBrowserTrackingProc);
366
367 DataBrowserCustomCallbacks customCallbacks; // variable definition
368
369 InitializeDataBrowserCustomCallbacks(&customCallbacks,kDataBrowserLatestCallbacks);
370 customCallbacks.u.v1.drawItemCallback = gDataBrowserTableViewDrawItemUPP;
371 customCallbacks.u.v1.editTextCallback = gDataBrowserTableViewEditItemUPP;
372 customCallbacks.u.v1.hitTestCallback = gDataBrowserTableViewHitTestUPP;
373 customCallbacks.u.v1.trackingCallback = gDataBrowserTableViewTrackingUPP;
374 SetCustomCallbacks(&customCallbacks);
375
376 // style setting:
377 EnableCellSizeModification( ((style & wxDV_VARIABLE_LINE_HEIGHT) != 0), true );
378
379 DataBrowserSelectionFlags flags; // variable definition
380
381 if (GetSelectionFlags(&flags) == noErr) // get default settings
382 {
383 if ((style & wxDV_MULTIPLE) != 0)
384 flags &= ~kDataBrowserSelectOnlyOne;
385 else
386 flags |= kDataBrowserSelectOnlyOne;
387 (void) SetSelectionFlags(flags);
388 }
389
390 OptionBits attributes; // variable definition
391
392 if (GetAttributes(&attributes) == noErr) // get default settings
393 {
394 if ((style & wxDV_VERT_RULES) != 0)
395 attributes |= kDataBrowserAttributeListViewDrawColumnDividers;
396 else
397 attributes &= ~kDataBrowserAttributeListViewDrawColumnDividers;
398 if ((style & wxDV_ROW_LINES) != 0)
399 attributes |= kDataBrowserAttributeListViewAlternatingRowColors;
400 else
401 attributes &= ~kDataBrowserAttributeListViewAlternatingRowColors;
402 (void) SetAttributes(attributes);
403 }
404
405 if ((style & wxDV_NO_HEADER) != 0)
406 SetHeaderButtonHeight(0);
407 }
408
409 wxMacDataBrowserTableViewControl::~wxMacDataBrowserTableViewControl()
410 {
411 ::RemoveEventHandler((EventHandlerRef) m_macDataViewCtrlEventHandler);
412 }
413
414 //
415 // callback handling
416 //
417 OSStatus wxMacDataBrowserTableViewControl::SetCallbacks(DataBrowserCallbacks const* callbacks)
418 {
419 return ::SetDataBrowserCallbacks(m_controlRef,callbacks);
420 }
421
422 OSStatus wxMacDataBrowserTableViewControl::SetCustomCallbacks(DataBrowserCustomCallbacks const* customCallbacks)
423 {
424 return ::SetDataBrowserCustomCallbacks(m_controlRef,customCallbacks);
425 }
426
427 //
428 // DnD handling
429 //
430 OSStatus wxMacDataBrowserTableViewControl::EnableAutomaticDragTracking(bool enable)
431 {
432 return ::SetAutomaticControlDragTrackingEnabledForWindow(::GetControlOwner(m_controlRef),enable);
433 }
434
435 //
436 // header handling
437 //
438 OSStatus wxMacDataBrowserTableViewControl::GetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc) const
439 {
440 desc->version = kDataBrowserListViewLatestHeaderDesc; // if this statement is missing the next call will fail (NOT DOCUMENTED!!)
441 return ::GetDataBrowserListViewHeaderDesc(m_controlRef,propertyID,desc);
442 }
443
444 OSStatus wxMacDataBrowserTableViewControl::SetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc)
445 {
446 return ::SetDataBrowserListViewHeaderDesc(m_controlRef,propertyID,desc);
447 }
448
449 //
450 // layout handling
451 //
452 OSStatus wxMacDataBrowserTableViewControl::AutoSizeColumns()
453 {
454 return AutoSizeDataBrowserListViewColumns(m_controlRef);
455 }
456
457 OSStatus wxMacDataBrowserTableViewControl::EnableCellSizeModification(bool enableHeight, bool enableWidth)
458 {
459 return ::SetDataBrowserTableViewGeometry(GetControlRef(),enableWidth,enableHeight);
460 }
461
462 OSStatus wxMacDataBrowserTableViewControl::GetAttributes(OptionBits* attributes)
463 {
464 return ::DataBrowserGetAttributes(GetControlRef(),attributes);
465 }
466
467 OSStatus wxMacDataBrowserTableViewControl::GetColumnWidth(DataBrowserPropertyID propertyID, UInt16* width) const
468 {
469 return ::GetDataBrowserTableViewNamedColumnWidth(m_controlRef,propertyID,width);
470 }
471
472 OSStatus wxMacDataBrowserTableViewControl::GetDefaultColumnWidth( UInt16 *width ) const
473 {
474 return GetDataBrowserTableViewColumnWidth(m_controlRef, width );
475 }
476
477 OSStatus wxMacDataBrowserTableViewControl::GetDefaultRowHeight(UInt16* height) const
478 {
479 return ::GetDataBrowserTableViewRowHeight(m_controlRef,height);
480 }
481
482 OSStatus wxMacDataBrowserTableViewControl::GetHeaderButtonHeight(UInt16 *height)
483 {
484 return ::GetDataBrowserListViewHeaderBtnHeight(m_controlRef,height);
485 }
486
487 OSStatus wxMacDataBrowserTableViewControl::GetPartBounds(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserPropertyPart part, Rect* bounds)
488 {
489 return ::GetDataBrowserItemPartBounds(m_controlRef,item,propertyID,part,bounds);
490 }
491
492 OSStatus wxMacDataBrowserTableViewControl::GetRowHeight(DataBrowserItemID item, UInt16* height) const
493 {
494 return ::GetDataBrowserTableViewItemRowHeight(m_controlRef,item,height);
495 }
496
497 OSStatus wxMacDataBrowserTableViewControl::GetScrollPosition( UInt32 *top , UInt32 *left ) const
498 {
499 return GetDataBrowserScrollPosition(m_controlRef, top , left );
500 }
501
502 OSStatus wxMacDataBrowserTableViewControl::SetAttributes(OptionBits attributes)
503 {
504 return ::DataBrowserChangeAttributes(GetControlRef(),attributes,~attributes);
505 }
506
507 OSStatus wxMacDataBrowserTableViewControl::SetColumnWidth(DataBrowserPropertyID propertyID, UInt16 width)
508 {
509 return ::SetDataBrowserTableViewNamedColumnWidth(m_controlRef,propertyID,width);
510 }
511
512 OSStatus wxMacDataBrowserTableViewControl::SetDefaultColumnWidth(UInt16 width)
513 {
514 return ::SetDataBrowserTableViewColumnWidth(m_controlRef,width);
515 }
516
517 OSStatus wxMacDataBrowserTableViewControl::SetDefaultRowHeight(UInt16 height)
518 {
519 return ::SetDataBrowserTableViewRowHeight(m_controlRef,height);
520 }
521
522 OSStatus wxMacDataBrowserTableViewControl::SetHasScrollBars(bool horiz, bool vert)
523 {
524 return ::SetDataBrowserHasScrollBars(m_controlRef,horiz,vert);
525 }
526
527 OSStatus wxMacDataBrowserTableViewControl::SetHeaderButtonHeight(UInt16 height)
528 {
529 return ::SetDataBrowserListViewHeaderBtnHeight(m_controlRef,height);
530 }
531
532 OSStatus wxMacDataBrowserTableViewControl::SetHiliteStyle(DataBrowserTableViewHiliteStyle hiliteStyle)
533 {
534 return ::SetDataBrowserTableViewHiliteStyle(m_controlRef,hiliteStyle);
535 }
536
537 OSStatus wxMacDataBrowserTableViewControl::SetIndent(float Indent)
538 {
539 return ::DataBrowserSetMetric(m_controlRef,kDataBrowserMetricDisclosureColumnPerDepthGap,true,Indent);
540 }
541
542 OSStatus wxMacDataBrowserTableViewControl::SetItemRowHeight(DataBrowserItemID item, UInt16 height)
543 {
544 return ::SetDataBrowserTableViewItemRowHeight(m_controlRef,item,height);
545 }
546
547 OSStatus wxMacDataBrowserTableViewControl::SetScrollPosition(UInt32 top, UInt32 left)
548 {
549 return ::SetDataBrowserScrollPosition(m_controlRef,top,left);
550 }
551
552 //
553 // column handling
554 //
555 OSStatus wxMacDataBrowserTableViewControl::GetColumnCount(UInt32* numColumns) const
556 {
557 return ::GetDataBrowserTableViewColumnCount(m_controlRef,numColumns);
558 }
559
560 OSStatus wxMacDataBrowserTableViewControl::GetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex* index) const
561 {
562 return ::GetDataBrowserTableViewColumnPosition(m_controlRef,propertyID,index);
563 }
564
565 OSStatus wxMacDataBrowserTableViewControl::GetFreePropertyID(DataBrowserPropertyID* propertyID) const
566 {
567 for (*propertyID=kMinPropertyID; *propertyID<std::numeric_limits<DataBrowserPropertyID>::max(); ++(*propertyID))
568 if (IsUsedPropertyID(*propertyID) == errDataBrowserPropertyNotFound)
569 return noErr;
570 return errDataBrowserPropertyNotSupported;
571 }
572
573 OSStatus wxMacDataBrowserTableViewControl::GetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags *flags) const
574 {
575 return ::GetDataBrowserPropertyFlags(m_controlRef,propertyID,flags);
576 }
577
578 OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserItemDataRef itemData, DataBrowserPropertyID* propertyID) const
579 {
580 return ::GetDataBrowserItemDataProperty(itemData,propertyID);
581 }
582
583 OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserTableViewColumnIndex index, DataBrowserTableViewColumnID* propertyID) const
584 {
585 return ::GetDataBrowserTableViewColumnProperty(m_controlRef,index,propertyID);
586 }
587
588 OSStatus wxMacDataBrowserTableViewControl::IsUsedPropertyID(DataBrowserPropertyID propertyID) const
589 {
590 // as the Mac interface does not provide a function that checks if the property id is in use or not a function is chosen that should not
591 // lead to a large overhead for the call but returns an error code if the property id does not exist, here we use the function that returns
592 // the column position for the property id:
593 DataBrowserTableViewColumnIndex index;
594
595 return ::GetDataBrowserTableViewColumnPosition(m_controlRef,propertyID,&index);
596 }
597
598 OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByProperty(DataBrowserTableViewColumnID propertyID)
599 {
600 return ::RemoveDataBrowserTableViewColumn(m_controlRef,propertyID);
601 }
602
603 OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByIndex(DataBrowserTableViewColumnIndex index)
604 {
605 DataBrowserTableViewColumnID propertyID;
606
607
608 GetPropertyID(index,&propertyID);
609 return ::RemoveDataBrowserTableViewColumn(m_controlRef,propertyID);
610 }
611
612 OSStatus wxMacDataBrowserTableViewControl::SetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex index)
613 {
614 return ::SetDataBrowserTableViewColumnPosition(m_controlRef,propertyID,index);
615 }
616
617 OSStatus wxMacDataBrowserTableViewControl::SetDisclosureColumn(DataBrowserPropertyID propertyID, Boolean expandableRows)
618 {
619 return ::SetDataBrowserListViewDisclosureColumn(m_controlRef,propertyID,expandableRows);
620 }
621
622 OSStatus wxMacDataBrowserTableViewControl::SetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags flags)
623 {
624 return ::SetDataBrowserPropertyFlags(m_controlRef,propertyID,flags);
625 }
626
627 //
628 // item handling
629 //
630 OSStatus wxMacDataBrowserTableViewControl::AddItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
631 {
632 return ::AddDataBrowserItems(m_controlRef,container,numItems,items,preSortProperty);
633 }
634
635 OSStatus wxMacDataBrowserTableViewControl::GetFreeItemID(DataBrowserItemID* id) const
636 {
637 ItemCount noOfItems;
638
639 OSStatus status;
640
641
642 status = GetItemCount(&noOfItems);
643 wxCHECK_MSG(status == noErr,status,_("Could not retrieve number of items"));
644 if (noOfItems == 0)
645 {
646 *id = 1;
647 return noErr;
648 }
649 else
650 {
651 // as there might be a lot of items in the data browser and mostly the data is added item by item the largest used ID number is roughly in the order of magnitude
652 // as the number of items; therefore, start from the number of items to look for a new ID:
653 for (*id=noOfItems; *id<std::numeric_limits<DataBrowserItemID>::max(); ++(*id))
654 if (IsUsedItemID(*id) == errDataBrowserItemNotFound)
655 return noErr;
656 // as the first approach was not successful, try from the beginning:
657 for (*id=0; *id<noOfItems; ++(*id))
658 if (IsUsedItemID(*id) == errDataBrowserItemNotFound)
659 return noErr;
660 // sorry, data browser is full:
661 return errDataBrowserItemNotAdded;
662 }
663 }
664
665 OSStatus wxMacDataBrowserTableViewControl::GetItemCount(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, ItemCount* numItems) const
666 {
667 return GetDataBrowserItemCount(m_controlRef,container,recurse,state,numItems);
668 }
669
670 OSStatus wxMacDataBrowserTableViewControl::GetItemID( DataBrowserTableViewRowIndex row, DataBrowserItemID * item ) const
671 {
672 return GetDataBrowserTableViewItemID(m_controlRef,row,item);
673 }
674
675 OSStatus wxMacDataBrowserTableViewControl::GetItems(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, Handle items) const
676 {
677 return GetDataBrowserItems(m_controlRef,container,recurse,state,items);
678 }
679
680 OSStatus wxMacDataBrowserTableViewControl::GetItemRow(DataBrowserItemID item, DataBrowserTableViewRowIndex* row) const
681 {
682 return GetDataBrowserTableViewItemRow(m_controlRef,item,row);
683 }
684
685 OSStatus wxMacDataBrowserTableViewControl::GetItemState(DataBrowserItemID item, DataBrowserItemState* state) const
686 {
687 return ::GetDataBrowserItemState(m_controlRef,item,state);
688 }
689
690 OSStatus wxMacDataBrowserTableViewControl::IsUsedItemID(DataBrowserItemID itemID) const
691 {
692 // as the Mac interface does not provide a function that checks if the property id is in use or not a function is chosen that should not
693 // lead to a large overhead for the call but returns an error code if the property id does not exist, here we use the function that returns
694 // the column position for the property id:
695 DataBrowserTableViewColumnIndex index;
696
697 return ::GetDataBrowserTableViewItemRow(m_controlRef,itemID,&index);
698 }
699
700 OSStatus wxMacDataBrowserTableViewControl::RemoveItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
701 {
702 return ::RemoveDataBrowserItems(m_controlRef,container,numItems,items,preSortProperty);
703 }
704
705 OSStatus wxMacDataBrowserTableViewControl::RevealItem(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserRevealOptions options) const
706 {
707 return ::RevealDataBrowserItem(m_controlRef,item,propertyID,options);
708 }
709
710 OSStatus wxMacDataBrowserTableViewControl::UpdateItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty,
711 DataBrowserPropertyID propertyID) const
712 {
713 return UpdateDataBrowserItems(m_controlRef,container,numItems,items,preSortProperty,propertyID);
714 }
715
716 //
717 // item selection
718 //
719 size_t wxMacDataBrowserTableViewControl::GetSelectedItemIDs(wxArrayDataBrowserItemID& itemIDs) const
720 {
721 DataBrowserItemID* itemIDPtr;
722 Handle handle(::NewHandle(0));
723
724 size_t noOfItems;
725
726
727 wxCHECK_MSG(GetItems(kDataBrowserNoItem,true,kDataBrowserItemIsSelected,handle) == noErr,0,_("Could not get selected items."));
728 noOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
729 itemIDs.Empty();
730 itemIDs.Alloc(noOfItems);
731 HLock(handle);
732 itemIDPtr = (DataBrowserItemID*) (*handle);
733 for (size_t i=0; i<noOfItems; ++i)
734 {
735 itemIDs.Add(*itemIDPtr);
736 ++itemIDPtr;
737 }
738 HUnlock(handle);
739 DisposeHandle(handle);
740 return noOfItems;
741 }
742
743 OSStatus wxMacDataBrowserTableViewControl::GetSelectionAnchor(DataBrowserItemID* first, DataBrowserItemID* last) const
744 {
745 return ::GetDataBrowserSelectionAnchor(m_controlRef,first,last);
746 }
747
748 OSStatus wxMacDataBrowserTableViewControl::GetSelectionFlags(DataBrowserSelectionFlags* flags) const
749 {
750 return ::GetDataBrowserSelectionFlags(m_controlRef,flags);
751 }
752
753 bool wxMacDataBrowserTableViewControl::IsItemSelected(DataBrowserItemID item) const
754 {
755 return ::IsDataBrowserItemSelected(m_controlRef,item);
756 }
757
758 OSStatus wxMacDataBrowserTableViewControl::SetSelectionFlags(DataBrowserSelectionFlags flags)
759 {
760 return ::SetDataBrowserSelectionFlags(m_controlRef,flags);
761 }
762
763 OSStatus wxMacDataBrowserTableViewControl::SetSelectedItems(UInt32 numItems, DataBrowserItemID const* items, DataBrowserSetOption operation)
764 {
765 return ::SetDataBrowserSelectedItems(m_controlRef, numItems, items, operation );
766 }
767
768 OSStatus wxMacDataBrowserTableViewControl::GetSortOrder(DataBrowserSortOrder* order) const
769 {
770 return ::GetDataBrowserSortOrder(m_controlRef,order);
771 }
772
773 OSStatus wxMacDataBrowserTableViewControl::GetSortProperty(DataBrowserPropertyID* propertyID) const
774 {
775 return ::GetDataBrowserSortProperty(m_controlRef,propertyID);
776 }
777
778 OSStatus wxMacDataBrowserTableViewControl::Resort(DataBrowserItemID container, Boolean sortChildren)
779 {
780 return ::SortDataBrowserContainer(m_controlRef,container,sortChildren);
781 }
782
783 OSStatus wxMacDataBrowserTableViewControl::SetSortOrder(DataBrowserSortOrder order)
784 {
785 return ::SetDataBrowserSortOrder(m_controlRef,order);
786 }
787
788 OSStatus wxMacDataBrowserTableViewControl::SetSortProperty(DataBrowserPropertyID propertyID)
789 {
790 return ::SetDataBrowserSortProperty(m_controlRef,propertyID);
791 }
792
793 //
794 // container handling
795 //
796 OSStatus wxMacDataBrowserTableViewControl::CloseContainer(DataBrowserItemID containerID)
797 {
798 return ::CloseDataBrowserContainer(m_controlRef,containerID);
799 }
800
801 OSStatus wxMacDataBrowserTableViewControl::OpenContainer(DataBrowserItemID containerID)
802 {
803 return ::OpenDataBrowserContainer(m_controlRef,containerID);
804 }
805
806 IMPLEMENT_ABSTRACT_CLASS(wxMacDataBrowserTableViewControl,wxMacControl)
807
808 // ============================================================================
809 // wxMacDataBrowserListViewControl
810 // ============================================================================
811 #pragma mark -
812 //
813 // column handling
814 //
815 OSStatus wxMacDataBrowserListViewControl::AddColumn(DataBrowserListViewColumnDesc *columnDesc, DataBrowserTableViewColumnIndex position)
816 {
817 return AddDataBrowserListViewColumn(m_controlRef,columnDesc,position);
818 }
819
820 // ============================================================================
821 // wxMacDataViewDataBrowserListViewControl
822 // ============================================================================
823 #pragma mark -
824 //
825 // constructors / destructor
826 //
827 wxMacDataViewDataBrowserListViewControl::wxMacDataViewDataBrowserListViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
828 :wxMacDataBrowserListViewControl(peer,pos,size,style)
829 {
830 if ((style & wxBORDER_NONE) != 0)
831 SetData(kControlNoPart,kControlDataBrowserIncludesFrameAndFocusTag,(Boolean) false);
832 (void) EnableAutomaticDragTracking();
833 (void) SetHiliteStyle(kDataBrowserTableViewFillHilite);
834 }
835
836 //
837 // column related methods (inherited from wxDataViewWidgetImpl)
838 //
839 bool wxMacDataViewDataBrowserListViewControl::ClearColumns()
840 {
841 UInt32 noOfColumns;
842
843
844 wxCHECK_MSG(GetColumnCount(&noOfColumns) == noErr,false,_("Could not determine number of columns."));
845 for (UInt32 i=0; i<noOfColumns; ++i)
846 wxCHECK_MSG(RemoveColumnByIndex(0) == noErr,false,_("Could not remove column."));
847 return true;
848 }
849
850 bool wxMacDataViewDataBrowserListViewControl::DeleteColumn(wxDataViewColumn* columnPtr)
851 {
852 return (RemoveColumnByProperty(columnPtr->GetNativeData()->GetPropertyID()) == noErr);
853 }
854
855 void wxMacDataViewDataBrowserListViewControl::DoSetExpanderColumn(wxDataViewColumn const* columnPtr)
856 {
857 SetDisclosureColumn(columnPtr->GetNativeData()->GetPropertyID(),false); // second parameter explicitly passed to ensure that arrow is centered
858 }
859
860 wxDataViewColumn* wxMacDataViewDataBrowserListViewControl::GetColumn(unsigned int pos) const
861 {
862 DataBrowserPropertyID propertyID;
863
864
865 if (GetPropertyID(pos,&propertyID) == noErr)
866 return GetColumnPtr(propertyID);
867 else
868 return NULL;
869 }
870
871 int wxMacDataViewDataBrowserListViewControl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
872 {
873 if (columnPtr != NULL)
874 {
875 DataBrowserTableViewColumnIndex Position;
876
877 wxCHECK_MSG(GetColumnIndex(columnPtr->GetNativeData()->GetPropertyID(),&Position) == noErr,wxNOT_FOUND,_("Could not determine column's position"));
878 return static_cast<int>(Position);
879 }
880 else
881 return wxNOT_FOUND;
882 }
883
884 bool wxMacDataViewDataBrowserListViewControl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
885 {
886 DataBrowserListViewColumnDesc columnDescription;
887
888 DataBrowserPropertyID newPropertyID;
889
890 UInt32 noOfColumns;
891
892 wxCFStringRef title(columnPtr->GetTitle(),m_font.IsOk() ? dynamic_cast<wxDataViewCtrl*>(GetWXPeer())->GetFont().GetEncoding() : wxLocale::GetSystemEncoding());
893
894
895 // try to get new ID for the column:
896 wxCHECK_MSG(GetFreePropertyID(&newPropertyID) == noErr,false,_("Cannot create new column's ID. Probably max. number of columns reached."));
897 // set native data:
898 columnPtr->GetNativeData()->SetPropertyID(newPropertyID);
899 // create a column description, add column to the native control and do some final layout adjustments:
900 wxCHECK_MSG(::InitializeColumnDescription(columnDescription,columnPtr,title), false,_("Column description could not be initialized."));
901 wxCHECK_MSG(AddColumn(&columnDescription,pos) == noErr, false,_("Column could not be added."));
902 wxCHECK_MSG(SetColumnWidth(newPropertyID,columnPtr->GetWidth()) == noErr,false,_("Column width could not be set."));
903 wxCHECK_MSG(GetColumnCount(&noOfColumns) == noErr, false,_("Number of columns could not be determined."));
904 if (noOfColumns == 1)
905 {
906 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
907
908 wxCHECK_MSG(dataViewCtrlPtr != NULL,false,_("wxWidget's control not initialized."));
909 dataViewCtrlPtr->AddChildren(wxDataViewItem());
910 return true;
911 }
912 else
913 return Update(columnPtr);
914 }
915
916 //
917 // item related methods (inherited from wxDataViewWidgetImpl)
918 //
919 bool wxMacDataViewDataBrowserListViewControl::Add(wxDataViewItem const& parent, wxDataViewItem const& item)
920 {
921 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
922
923
924 return (( parent.IsOk() && AddItem(reinterpret_cast<DataBrowserItemID>(parent.GetID()),&itemID) == noErr) ||
925 (!(parent.IsOk()) && AddItem(kDataBrowserNoItem,&itemID) == noErr));
926 }
927
928 bool wxMacDataViewDataBrowserListViewControl::Add(wxDataViewItem const& parent, wxDataViewItemArray const& items)
929 {
930 bool noFailureFlag;
931
932 DataBrowserItemID* itemIDs;
933
934 size_t noOfEntries;
935
936
937 // convert all valid data view items to data browser items:
938 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
939 // insert all valid items into control:
940 noFailureFlag = ((noOfEntries == 0) ||
941 !(parent.IsOk()) && (AddItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
942 parent.IsOk() && (AddItems(reinterpret_cast<DataBrowserItemID>(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
943 // give allocated array space free again:
944 delete[] itemIDs;
945 // done:
946 return noFailureFlag;
947 }
948
949 void wxMacDataViewDataBrowserListViewControl::Collapse(wxDataViewItem const& item)
950 {
951 CloseContainer(reinterpret_cast<DataBrowserItemID>(item.GetID()));
952 }
953
954 void wxMacDataViewDataBrowserListViewControl::EnsureVisible(wxDataViewItem const& item, const wxDataViewColumn* columnPtr)
955 {
956 DataBrowserPropertyID propertyID;
957
958
959 if (columnPtr != NULL)
960 propertyID = columnPtr->GetNativeData()->GetPropertyID();
961 else
962 propertyID = kDataBrowserNoItem;
963 RevealItem(reinterpret_cast<DataBrowserItemID>(item.GetID()),propertyID,kDataBrowserRevealOnly);
964 }
965
966 void wxMacDataViewDataBrowserListViewControl::Expand(wxDataViewItem const& item)
967 {
968 OpenContainer(reinterpret_cast<DataBrowserItemID>(item.GetID()));
969 }
970
971 unsigned int wxMacDataViewDataBrowserListViewControl::GetCount() const
972 {
973 ItemCount noOfItems;
974
975
976 wxCHECK_MSG(GetItemCount(&noOfItems) == noErr,0,_("Could not determine number of items"));
977 return noOfItems;
978 }
979
980 wxRect wxMacDataViewDataBrowserListViewControl::GetRectangle(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
981 {
982 Rect MacRectangle;
983
984
985 if (GetPartBounds(reinterpret_cast<DataBrowserItemID>(item.GetID()),columnPtr->GetNativeData()->GetPropertyID(),kDataBrowserPropertyContentPart,&MacRectangle) == noErr)
986 {
987 wxRect rectangle;
988
989 ::wxMacNativeToRect(&MacRectangle,&rectangle);
990 return rectangle;
991 }
992 else
993 return wxRect();
994 }
995
996 bool wxMacDataViewDataBrowserListViewControl::IsExpanded(wxDataViewItem const& item) const
997 {
998 DataBrowserItemState state = 0;
999
1000 if (GetItemState(reinterpret_cast<DataBrowserItemID>(item.GetID()),&state) != noErr)
1001 return false;
1002
1003 return ((state & kDataBrowserContainerIsOpen) != 0);
1004 }
1005
1006 bool wxMacDataViewDataBrowserListViewControl::Reload()
1007 {
1008 bool noFailureFlag;
1009
1010 wxDataViewItemArray dataViewChildren;
1011
1012
1013 noFailureFlag = (RemoveItems() == noErr);
1014 SetScrollPosition(0,0); // even after having removed all items the scrollbars may remain at their old position -> reset them
1015 GetDataViewCtrl()->GetModel()->GetChildren(wxDataViewItem(),dataViewChildren);
1016 GetDataViewCtrl()->GetModel()->ItemsAdded(wxDataViewItem(),dataViewChildren);
1017
1018 return noFailureFlag;
1019 }
1020
1021 bool wxMacDataViewDataBrowserListViewControl::Remove(wxDataViewItem const& parent, wxDataViewItem const& item)
1022 {
1023 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1024
1025
1026 return (RemoveItem(reinterpret_cast<DataBrowserItemID>(parent.GetID()),&itemID) == noErr);
1027 }
1028
1029 bool wxMacDataViewDataBrowserListViewControl::Remove(wxDataViewItem const& parent, wxDataViewItemArray const& items)
1030 {
1031 bool noFailureFlag;
1032
1033 DataBrowserItemID* itemIDs;
1034
1035 size_t noOfEntries;
1036
1037
1038 // convert all valid data view items to data browser items:
1039 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
1040 // insert all valid items into control:
1041 noFailureFlag = ((noOfEntries == 0) ||
1042 !(parent.IsOk()) && (RemoveItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
1043 parent.IsOk() && (RemoveItems(reinterpret_cast<DataBrowserItemID>(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
1044 // give allocated array space free again:
1045 delete[] itemIDs;
1046 // done:
1047 return noFailureFlag;
1048 }
1049
1050 bool wxMacDataViewDataBrowserListViewControl::Update(wxDataViewColumn const* columnPtr)
1051 {
1052 return (UpdateItems(kDataBrowserNoItem,0,NULL,kDataBrowserItemNoProperty,columnPtr->GetNativeData()->GetPropertyID()) == noErr);
1053 }
1054
1055 bool wxMacDataViewDataBrowserListViewControl::Update(wxDataViewItem const& parent, wxDataViewItem const& item)
1056 {
1057 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1058
1059
1060 if (parent.IsOk())
1061 return (UpdateItem(reinterpret_cast<DataBrowserItemID>(parent.GetID()),&itemID) == noErr);
1062 else
1063 return (UpdateItem(kDataBrowserNoItem,&itemID) == noErr);
1064 }
1065
1066 bool wxMacDataViewDataBrowserListViewControl::Update(wxDataViewItem const& parent, wxDataViewItemArray const& items)
1067 {
1068 bool noFailureFlag;
1069
1070 DataBrowserItemID* itemIDs;
1071
1072 size_t noOfEntries;
1073
1074
1075 // convert all valid data view items to data browser items:
1076 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
1077 if (parent.IsOk())
1078 noFailureFlag = (UpdateItems(reinterpret_cast<DataBrowserItemID>(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty,kDataBrowserItemNoProperty) == noErr);
1079 else
1080 noFailureFlag = (UpdateItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty,kDataBrowserItemNoProperty) == noErr);
1081 // release allocated array space:
1082 delete[] itemIDs;
1083 // done:
1084 return noFailureFlag;
1085 }
1086
1087 //
1088 // model related methods
1089 //
1090 bool wxMacDataViewDataBrowserListViewControl::AssociateModel(wxDataViewModel* WXUNUSED(model))
1091 {
1092 return true;
1093 }
1094
1095 //
1096 // selection related methods (inherited from wxDataViewWidgetImpl)
1097 //
1098 wxDataViewItem wxMacDataViewDataBrowserListViewControl::GetCurrentItem() const
1099 {
1100 wxFAIL_MSG( "unimplemented for Carbon" );
1101
1102 return wxDataViewItem();
1103 }
1104
1105 void wxMacDataViewDataBrowserListViewControl::SetCurrentItem(const wxDataViewItem& WXUNUSED(item))
1106 {
1107 wxFAIL_MSG( "unimplemented for Carbon" );
1108 }
1109
1110 int wxMacDataViewDataBrowserListViewControl::GetSelections(wxDataViewItemArray& sel) const
1111 {
1112 size_t noOfSelectedItems;
1113
1114 wxArrayDataBrowserItemID itemIDs;
1115
1116
1117 noOfSelectedItems = GetSelectedItemIDs(itemIDs);
1118 sel.Empty();
1119 sel.SetCount(noOfSelectedItems);
1120 for (size_t i=0; i<noOfSelectedItems; ++i)
1121 sel[i] = wxDataViewItem(reinterpret_cast<void*>(itemIDs[i]));
1122 return static_cast<int>(noOfSelectedItems);
1123 }
1124
1125 bool wxMacDataViewDataBrowserListViewControl::IsSelected(wxDataViewItem const& item) const
1126 {
1127 return IsItemSelected(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1128 }
1129
1130 void wxMacDataViewDataBrowserListViewControl::Select(wxDataViewItem const& item)
1131 {
1132 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1133
1134
1135 SetSelectedItems(1,&itemID,kDataBrowserItemsAdd);
1136 }
1137
1138 void wxMacDataViewDataBrowserListViewControl::SelectAll()
1139 {
1140 DataBrowserItemID* itemIDPtr;
1141
1142 Handle handle(::NewHandle(0));
1143
1144 size_t noOfItems;
1145
1146
1147 wxCHECK_RET(GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1148 noOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1149 ::HLock(handle);
1150 itemIDPtr = (DataBrowserItemID*) (*handle);
1151 SetSelectedItems(noOfItems,itemIDPtr,kDataBrowserItemsAssign);
1152 ::HUnlock(handle);
1153 ::DisposeHandle(handle);
1154 }
1155
1156 void wxMacDataViewDataBrowserListViewControl::Unselect(wxDataViewItem const& item)
1157 {
1158 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1159
1160
1161 SetSelectedItems(1,&itemID,kDataBrowserItemsRemove);
1162 }
1163
1164 void wxMacDataViewDataBrowserListViewControl::UnselectAll()
1165 {
1166 DataBrowserItemID* itemIDPtr;
1167
1168 Handle handle(::NewHandle(0));
1169
1170 size_t noOfItems;
1171
1172
1173 wxCHECK_RET(GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1174 noOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1175 ::HLock(handle);
1176 itemIDPtr = (DataBrowserItemID*) (*handle);
1177 SetSelectedItems(noOfItems,itemIDPtr,kDataBrowserItemsRemove);
1178 ::HUnlock(handle);
1179 ::DisposeHandle(handle);
1180 }
1181
1182 //
1183 // sorting related methods
1184 //
1185 wxDataViewColumn* wxMacDataViewDataBrowserListViewControl::GetSortingColumn() const
1186 {
1187 DataBrowserPropertyID propertyID;
1188
1189
1190 if (GetSortProperty(&propertyID) == noErr)
1191 return GetColumnPtr(propertyID);
1192 else
1193 return NULL;
1194 }
1195
1196 void wxMacDataViewDataBrowserListViewControl::Resort()
1197 {
1198 (void) wxMacDataBrowserListViewControl::Resort();
1199 }
1200
1201 //
1202 // other methods (inherited from wxDataViewWidgetImpl)
1203 //
1204 void
1205 wxMacDataViewDataBrowserListViewControl::HitTest(const wxPoint& WXUNUSED(point),
1206 wxDataViewItem& item,
1207 wxDataViewColumn*& columnPtr) const
1208 {
1209 // not yet implemented:
1210 item = wxDataViewItem();
1211 columnPtr = NULL;
1212 }
1213
1214 void wxMacDataViewDataBrowserListViewControl::DoSetIndent(int indent)
1215 {
1216 SetIndent(static_cast<float>(indent));
1217 }
1218
1219 void wxMacDataViewDataBrowserListViewControl::SetRowHeight(wxDataViewItem const& item, unsigned int height)
1220 {
1221 SetItemRowHeight(reinterpret_cast<DataBrowserItemID>(item.GetID()),static_cast<UInt16>(height));
1222 }
1223
1224 void wxMacDataViewDataBrowserListViewControl::OnSize()
1225 {
1226 UInt32 noOfColumns;
1227
1228
1229 GetColumnCount(&noOfColumns);
1230 if (noOfColumns <= 1) // no horizontal scroll bar and the only column expands to the width of the whole control
1231 {
1232 SetHasScrollBars(false,true);
1233 AutoSizeColumns();
1234 }
1235 else // otherwise keep the current column size and have scrollbars in both directions
1236 SetHasScrollBars(true,true);
1237 }
1238
1239 void wxMacDataViewDataBrowserListViewControl::StartEditor( const wxDataViewItem & item, unsigned int column )
1240 {
1241 // implement me
1242 }
1243
1244 //
1245 // callback functions (inherited from wxMacDataBrowserTableViewControl)
1246 //
1247 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
1248 {
1249 DataBrowserSortOrder sortOrder;
1250
1251 DataBrowserTableViewColumnIndex modelColumnIndex;
1252
1253 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1254
1255
1256 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1257 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1258 if (sortProperty >= kMinPropertyID)
1259 {
1260 // variable definition and initialization:
1261 wxDataViewColumn* ColumnPtr(GetColumnPtr(sortProperty));
1262
1263 wxCHECK_MSG(ColumnPtr != NULL,false,_("Could not determine column index."));
1264 modelColumnIndex = ColumnPtr->GetModelColumn();
1265 }
1266 else
1267 modelColumnIndex = 0;
1268 GetSortOrder(&sortOrder);
1269 return static_cast<Boolean>(dataViewCtrlPtr->GetModel()->Compare(wxDataViewItem(reinterpret_cast<void*>(itemOneID)),wxDataViewItem(reinterpret_cast<void*>(itemTwoID)),
1270 modelColumnIndex,sortOrder != kDataBrowserOrderDecreasing) < 0);
1271 }
1272
1273 void wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* WXUNUSED(selection))
1274 // In this method we do not supply a contextual menu handler at all but only send a wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU.
1275 {
1276 wxArrayDataBrowserItemID itemIDs;
1277
1278 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1279
1280
1281 wxCHECK_RET(dataViewCtrlPtr != NULL,_("wxWidget control pointer is not a data view pointer"));
1282 // initialize parameters so that no context menu will be displayed automatically by the native data browser:
1283 *menu = NULL;
1284 *helpType = kCMHelpItemNoHelp;
1285 *helpItemString = NULL;
1286 // create information for a context menu event:
1287 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU,dataViewCtrlPtr->GetId());
1288
1289 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1290 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1291 // get the item information;
1292 // theoretically more than one ID can be returned but the event can only handle one item, therefore all item related data is using the data of the first item in the array:
1293 if (GetSelectedItemIDs(itemIDs) > 0)
1294 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemIDs[0])));
1295 // finally send the equivalent wxWidget event:
1296 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1297 }
1298
1299 OSStatus wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
1300 {
1301 if (getValue)
1302 {
1303 // variable definitions:
1304 wxDataViewCtrl* dataViewCtrlPtr;
1305
1306 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1307 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1308 if (dataViewCtrlPtr->IsDeleting())
1309 return noErr; // if a delete process is running the data of editable fields cannot be saved because the associated model variable may already have been deleted
1310 else
1311 {
1312 // variable definitions:
1313 OSStatus errorStatus;
1314 wxDataViewColumn* dataViewColumnPtr;
1315
1316 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1317 dataViewColumnPtr = GetColumnPtr(propertyID);
1318 wxCHECK_MSG((dataViewColumnPtr != NULL) && (dataViewColumnPtr->GetRenderer() != NULL),errDataBrowserNotConfigured,_("There is no column or renderer for the specified column index."));
1319
1320 wxDataViewItem dvItem(reinterpret_cast<void*>(itemID));
1321 unsigned int col = dataViewColumnPtr->GetModelColumn();
1322
1323 switch (dataViewColumnPtr->GetRenderer()->GetNativeData()->GetPropertyType())
1324 {
1325 case kDataBrowserCheckboxType:
1326 {
1327 // variable definition:
1328 ThemeButtonValue buttonValue;
1329
1330 errorStatus = ::GetDataBrowserItemDataButtonValue(itemData,&buttonValue);
1331 if (errorStatus == noErr)
1332 {
1333 if (buttonValue == kThemeButtonOn)
1334 {
1335 // variable definition and initialization:
1336 wxVariant modifiedData(true);
1337
1338 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1339 return noErr;
1340 else
1341 return errDataBrowserInvalidPropertyData;
1342 }
1343 else if (buttonValue == kThemeButtonOff)
1344 {
1345 // variable definition and initialization:
1346 wxVariant modifiedData(false);
1347
1348 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1349 return noErr;
1350 else
1351 return errDataBrowserInvalidPropertyData;
1352 }
1353 else
1354 return errDataBrowserInvalidPropertyData;
1355 }
1356 else
1357 return errorStatus;
1358 } /* block */
1359 case kDataBrowserTextType:
1360 {
1361 // variable definitions:
1362 CFStringRef stringReference;
1363
1364 errorStatus = ::GetDataBrowserItemDataText(itemData,&stringReference);
1365 if (errorStatus == noErr)
1366 {
1367 // variable definitions and initializations:
1368 #if wxCHECK_VERSION(2,9,0)
1369 wxCFStringRef modifiedString(stringReference);
1370 #else
1371 wxMacCFStringHolder modifiedString(stringReference);
1372 #endif
1373 wxVariant modifiedData(modifiedString.AsString());
1374
1375 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1376 return noErr;
1377 else
1378 return errDataBrowserInvalidPropertyData;
1379 }
1380 else
1381 return errorStatus;
1382 } /* block */
1383 default:
1384 return errDataBrowserPropertyNotSupported;
1385 }
1386 }
1387 }
1388 else
1389 {
1390 if (propertyID >= kMinPropertyID) // in case data columns set the data
1391 {
1392 // variable definitions:
1393 wxVariant variant;
1394 wxDataViewColumn* dataViewColumnPtr;
1395 wxDataViewCtrl* dataViewCtrlPtr;
1396
1397 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1398 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1399 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1400 dataViewColumnPtr = GetColumnPtr(propertyID);
1401 wxCHECK_MSG(dataViewColumnPtr != NULL,errDataBrowserNotConfigured,_("No column for the specified column position existing."));
1402 wxCHECK_MSG(dataViewColumnPtr->GetRenderer() != NULL,errDataBrowserNotConfigured,_("No renderer specified for column."));
1403 dataViewCtrlPtr->GetModel()->GetValue(variant,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
1404 if (!(variant.IsNull()))
1405 {
1406 dataViewColumnPtr->GetRenderer()->GetNativeData()->SetItemDataRef(itemData);
1407 dataViewColumnPtr->GetRenderer()->SetValue(variant);
1408 wxCHECK_MSG(dataViewColumnPtr->GetRenderer()->MacRender(),errDataBrowserNotConfigured,_("Rendering failed."));
1409 }
1410 return noErr;
1411 }
1412 else // react on special system requests
1413 {
1414 switch (propertyID)
1415 {
1416 case kDataBrowserContainerIsClosableProperty:
1417 {
1418 // variable definitions:
1419 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1420
1421 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1422 // initialize wxWidget event:
1423 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,dataViewCtrlPtr->GetId()); // variable definition
1424
1425 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1426 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
1427 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1428 // finally send the equivalent wxWidget event:
1429 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1430 // opening the container is allowed if not vetoed:
1431 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
1432 } /* block */
1433 case kDataBrowserContainerIsOpenableProperty:
1434 {
1435 // variable definitions:
1436 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1437
1438 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1439 // initialize wxWidget event:
1440 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,dataViewCtrlPtr->GetId()); // variable definition
1441
1442 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1443 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
1444 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1445 // finally send the equivalent wxWidget event:
1446 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1447 // opening the container is allowed if not vetoed:
1448 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
1449 } /* block */
1450 case kDataBrowserItemIsContainerProperty:
1451 {
1452 // variable definition:
1453 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1454
1455 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1456 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1457 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewCtrlPtr->GetModel()->IsContainer(wxDataViewItem(reinterpret_cast<void*>(itemID))));
1458 } /* block */
1459 case kDataBrowserItemIsEditableProperty:
1460 return ::SetDataBrowserItemDataBooleanValue(itemData,true);
1461 }
1462 }
1463 }
1464 return errDataBrowserPropertyNotSupported;
1465 }
1466
1467 void wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
1468 {
1469 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1470
1471
1472 // check if the data view control pointer still exists because this call back function can still be called when the control has already been deleted:
1473 if (dataViewCtrlPtr != NULL)
1474 switch (message)
1475 {
1476 case kDataBrowserContainerClosed:
1477 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1478 {
1479 // initialize wxWidget event:
1480 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,dataViewCtrlPtr->GetId()); // variable definition
1481
1482 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1483 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1484 // finally send the equivalent wxWidget event:
1485 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1486 } /* block */
1487 break;
1488 case kDataBrowserContainerOpened:
1489 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1490 {
1491 // initialize wxWidget event:
1492 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,dataViewCtrlPtr->GetId()); // variable definition
1493
1494 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1495 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1496 // finally send the equivalent wxWidget event:
1497 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1498 // add children to the expanded container:
1499 dataViewCtrlPtr->AddChildren(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1500 } /* block */
1501 break;
1502 case kDataBrowserEditStarted:
1503 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1504 {
1505 // initialize wxWidget event:
1506 DataBrowserPropertyID propertyID;
1507 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition
1508
1509 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1510 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1511 if (GetPropertyID(itemData,&propertyID) == noErr)
1512 {
1513 // variable definition and initialization:
1514 DataBrowserTableViewColumnIndex columnIndex;
1515
1516 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
1517 dataViewEvent.SetColumn(columnIndex);
1518 dataViewEvent.SetDataViewColumn(GetColumnPtr(propertyID));
1519 }
1520 // finally send the equivalent wxWidget event:
1521 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1522 } /* block */
1523 break;
1524 case kDataBrowserEditStopped:
1525 {
1526 // initialize wxWidget event:
1527 DataBrowserPropertyID propertyID;
1528 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition
1529
1530 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1531 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1532 if (GetPropertyID(itemData,&propertyID) == noErr)
1533 {
1534 // variable definition and initialization:
1535 DataBrowserTableViewColumnIndex columnIndex;
1536
1537 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
1538 dataViewEvent.SetColumn(columnIndex);
1539 dataViewEvent.SetDataViewColumn(GetColumnPtr(propertyID));
1540 }
1541 // finally send the equivalent wxWidget event:
1542 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1543 } /* block */
1544 break;
1545 case kDataBrowserItemAdded:
1546 dataViewCtrlPtr->FinishCustomItemEditing();
1547 break;
1548 case kDataBrowserItemDeselected:
1549 dataViewCtrlPtr->FinishCustomItemEditing();
1550 break;
1551 case kDataBrowserItemDoubleClicked:
1552 {
1553 // initialize wxWidget event:
1554 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,dataViewCtrlPtr->GetId()); // variable definition
1555
1556 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1557 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1558 // finally send the equivalent wxWidget event:
1559 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1560 } /* block */
1561 break;
1562 case kDataBrowserItemRemoved:
1563 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1564 break;
1565 case kDataBrowserItemSelected:
1566 break; // not implemented by wxWidgets; see kDataBrowserSelectionSetChanged
1567 case kDataBrowserSelectionSetChanged:
1568 {
1569 // initialize wxWidget event:
1570 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED,dataViewCtrlPtr->GetId()); // variable definition
1571
1572 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1573 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1574 // finally send the equivalent wxWidget event:
1575 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1576 } /* block */
1577 break;
1578 case kDataBrowserTargetChanged: // no idea if this notification is ever sent
1579 break;
1580 case kDataBrowserUserStateChanged:
1581 {
1582 // finish custom item editing if necessary:
1583 dataViewCtrlPtr->FinishCustomItemEditing();
1584 // update column widths:
1585 for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); ++i)
1586 {
1587 // constant definition for abbreviational purposes:
1588 wxDataViewColumn* const columnPtr = dataViewCtrlPtr->GetColumnPtr(i);
1589 // variable definition:
1590 UInt16 columnWidth;
1591
1592 wxCHECK_RET(GetColumnWidth(columnPtr->GetNativeData()->GetPropertyID(),&columnWidth) == noErr,_("Column width could not be determined"));
1593 columnPtr->SetWidthVariable(columnWidth);
1594 }
1595 // update sorting orders:
1596 DataBrowserPropertyID propertyID; // variable definition
1597
1598 if ((GetSortProperty(&propertyID) == noErr) && (propertyID >= kMinPropertyID))
1599 {
1600 DataBrowserSortOrder sortOrder;
1601 DataBrowserTableViewColumnIndex columnIndex;
1602
1603 if ((GetSortOrder(&sortOrder) == noErr) && (GetColumnIndex(propertyID,&columnIndex) == noErr))
1604 {
1605 // variable definition and initialization:
1606 wxDataViewColumn* columnPtr;
1607 columnPtr = dataViewCtrlPtr->GetColumn(columnIndex);
1608 // check if the sort order has changed:
1609 if ( columnPtr->IsSortOrderAscending() && (sortOrder == kDataBrowserOrderDecreasing) ||
1610 !(columnPtr->IsSortOrderAscending()) && (sortOrder == kDataBrowserOrderIncreasing))
1611 {
1612 columnPtr->SetSortOrder(!(columnPtr->IsSortOrderAscending()));
1613 // initialize wxWidget event:
1614 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED,dataViewCtrlPtr->GetId()); // variable defintion
1615
1616 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1617 dataViewEvent.SetColumn(columnIndex);
1618 dataViewEvent.SetDataViewColumn(columnPtr);
1619 // finally send the equivalent wxWidget event:
1620 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1621 }
1622 }
1623 }
1624 } /* block */
1625 break;
1626 }
1627 }
1628
1629 void
1630 wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID itemID,
1631 DataBrowserPropertyID propertyID,
1632 DataBrowserItemState state,
1633 Rect const* rectangle,
1634 SInt16 WXUNUSED(bitDepth),
1635 Boolean WXUNUSED(colorDevice))
1636 {
1637 DataBrowserTableViewColumnIndex columnIndex;
1638
1639 wxDataViewColumn* dataViewColumnPtr;
1640
1641 wxDataViewCtrl* dataViewCtrlPtr;
1642
1643 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1644
1645 wxVariant dataToRender;
1646
1647 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1648 wxCHECK_RET(dataViewCtrlPtr != NULL, _("Pointer to data view control not set correctly."));
1649 wxCHECK_RET(dataViewCtrlPtr->GetModel() != NULL, _("Pointer to model not set correctly."));
1650 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex) == noErr,_("Could not determine column index."));
1651 dataViewColumnPtr = GetColumnPtr(propertyID);
1652 wxCHECK_RET(dataViewColumnPtr != NULL,_("No column for the specified column existing."));
1653 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1654 wxCHECK_RET(dataViewCustomRendererPtr != NULL,_("No renderer or invalid renderer type specified for custom data column."));
1655 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
1656 dataViewCustomRendererPtr->SetValue(dataToRender);
1657
1658 wxDataViewItem dataItem( reinterpret_cast<void*>(itemID) );
1659 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,dataItem,dataViewColumnPtr->GetModelColumn());
1660 dataViewCustomRendererPtr->SetValue(dataToRender);
1661
1662 // try to determine the content's size (drawable part):
1663 Rect content;
1664 RgnHandle rgn(NewRgn());
1665 UInt16 headerHeight;
1666
1667 if (GetControlRegion(m_controlRef,kControlContentMetaPart,rgn) == noErr)
1668 GetRegionBounds(rgn,&content);
1669 else
1670 GetControlBounds(m_controlRef, &content);
1671 ::DisposeRgn(rgn);
1672 // space for the header
1673 GetHeaderButtonHeight(&headerHeight);
1674 content.top += headerHeight;
1675 // extra space for the frame (todo: do not how to determine the space automatically from the control)
1676 content.top += 5;
1677 content.left += 5;
1678 content.right -= 3;
1679 content.bottom -= 3;
1680 // extra space for the scrollbars:
1681 content.bottom -= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
1682 content.right -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1683
1684 wxDC *dc = dataViewCustomRendererPtr->GetDC();
1685
1686 int active_border_fudge = 0;
1687 if (dataViewCtrlPtr->HasFocus() && !dataViewCtrlPtr->HasFlag( wxBORDER_NONE ))
1688 active_border_fudge = 1;
1689 else
1690 active_border_fudge = -2;
1691
1692 wxRect cellrect( static_cast<int>(rectangle->left + active_border_fudge),
1693 static_cast<int>(rectangle->top + active_border_fudge),
1694 static_cast<int>(1+rectangle->right-rectangle->left),
1695 static_cast<int>(rectangle->bottom-rectangle->top) );
1696
1697 bool is_active = IsControlActive( m_controlRef );
1698 if (state == kDataBrowserItemIsSelected)
1699 {
1700 wxColour col( wxMacCreateCGColorFromHITheme( (is_active) ?
1701 kThemeBrushAlternatePrimaryHighlightColor
1702 : kThemeBrushSecondaryHighlightColor ) );
1703
1704 wxRect rect = cellrect;
1705 Rect itemrect;
1706 GetDataBrowserItemPartBounds( m_controlRef, itemID, propertyID,
1707 kDataBrowserPropertyEnclosingPart, &itemrect );
1708 rect.x = itemrect.left-2;
1709 rect.width = itemrect.right-itemrect.left+3;
1710
1711 wxDCPenChanger setPen(*dc, *wxTRANSPARENT_PEN);
1712 wxDCBrushChanger setBrush(*dc, col);
1713 dc->DrawRectangle(rect);
1714 }
1715
1716 wxDataViewModel *model = dataViewCtrlPtr->GetModel();
1717 if ((columnIndex == 0) || !model->IsContainer(dataItem) || model->HasContainerColumns(dataItem))
1718 {
1719 // make sure that 'Render' can draw only in the allowed area:
1720 dc->SetClippingRegion(content.left,content.top,content.right-content.left+1,content.bottom-content.top+1);
1721 (void) (dataViewCustomRendererPtr->WXCallRender( cellrect, dc,
1722 ((state == kDataBrowserItemIsSelected) ? wxDATAVIEW_CELL_SELECTED : 0)));
1723 dc->DestroyClippingRegion(); // probably not necessary
1724 }
1725
1726 dataViewCustomRendererPtr->SetDC(NULL);
1727 }
1728
1729 Boolean
1730 wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(
1731 DataBrowserItemID WXUNUSED(itemID),
1732 DataBrowserPropertyID WXUNUSED(propertyID),
1733 CFStringRef WXUNUSED(theString),
1734 Rect* WXUNUSED(maxEditTextRect),
1735 Boolean* WXUNUSED(shrinkToFit))
1736 {
1737 return false;
1738 }
1739
1740 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID WXUNUSED(itemID), DataBrowserPropertyID WXUNUSED(property), Rect const* WXUNUSED(theRect), Rect const* WXUNUSED(mouseRect))
1741 {
1742 return true;
1743 }
1744
1745 DataBrowserTrackingResult wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point WXUNUSED(startPt), EventModifiers WXUNUSED(modifiers))
1746 {
1747 wxDataViewColumn* dataViewColumnPtr;
1748
1749 wxDataViewCtrl* dataViewCtrlPtr;
1750
1751 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1752
1753 wxDataViewItem dataViewCustomRendererItem;
1754
1755
1756 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1757 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1758 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1759 dataViewCustomRendererItem = wxDataViewItem(reinterpret_cast<void*>(itemID));
1760 wxCHECK_MSG(dataViewCustomRendererItem.IsOk(),kDataBrowserNothingHit,_("Invalid data view item"));
1761 dataViewColumnPtr = GetColumnPtr(propertyID);
1762 wxCHECK_MSG(dataViewColumnPtr != NULL,kDataBrowserNothingHit,_("No column existing."));
1763 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1764 wxCHECK_MSG(dataViewCustomRendererPtr != NULL,kDataBrowserNothingHit,_("No renderer or invalid renderer type specified for custom data column."));
1765 // if the currently edited item is identical to the to be edited nothing is done (this hit should only be handled in the control itself):
1766 if (dataViewCtrlPtr->GetCustomRendererItem() == dataViewCustomRendererItem)
1767 return kDataBrowserContentHit;
1768 // an(other) item is going to be edited and therefore the current editing - if existing - has to be finished:
1769 if (dataViewCtrlPtr->GetCustomRendererPtr() != NULL)
1770 {
1771 dataViewCtrlPtr->GetCustomRendererPtr()->FinishEditing();
1772 dataViewCtrlPtr->SetCustomRendererItem(wxDataViewItem());
1773 dataViewCtrlPtr->SetCustomRendererPtr (NULL);
1774 }
1775 // check if renderer has got a valid editor control for editing; if this is the case start editing of the new item:
1776 if (dataViewCustomRendererPtr->HasEditorCtrl())
1777 {
1778 // variable definition:
1779 wxRect wxRectangle;
1780
1781 ::wxMacNativeToRect(theRect,&wxRectangle);
1782 dataViewCustomRendererPtr->StartEditing(dataViewCustomRendererItem,wxRectangle);
1783 dataViewCtrlPtr->SetCustomRendererItem(dataViewCustomRendererItem);
1784 dataViewCtrlPtr->SetCustomRendererPtr (dataViewCustomRendererPtr);
1785 }
1786 return kDataBrowserContentHit;
1787 }
1788
1789 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference dragRef, DataBrowserItemID itemID)
1790 {
1791 bool acceptDrag;
1792
1793 UInt16 noOfDraggedItems;
1794
1795 wxDataViewCtrl* dataViewCtrlPtr;
1796
1797
1798 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1799 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1800 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1801
1802 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1803 ::CountDragItems(dragRef,&noOfDraggedItems);
1804 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1805 {
1806 // collect native information:
1807 ItemReference itemRef;
1808 wxDataObjectComposite* dataObjects;
1809 wxMemoryBuffer buffer;
1810
1811 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1812 dataObjects = GetDnDDataObjects(dragRef,itemRef);
1813 // create wxWidget's event:
1814 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE,dataViewCtrlPtr->GetId());
1815
1816 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1817
1818 // this is the item that receives the event (can be an invalid item ID, this is
1819 // especially useful if the dataview does not contain any items)
1820 dataViewEvent.SetItem( wxDataViewItem(reinterpret_cast<void*>(itemID)) );
1821
1822 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1823 dataViewEvent.SetDataObject(dataObjects);
1824 dataViewEvent.SetDataFormat(GetDnDDataFormat(dataObjects));
1825 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1826 {
1827 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1828 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1829 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1830 dataViewEvent.SetDataBuffer(buffer.GetData());
1831 }
1832
1833 // send event:
1834 acceptDrag = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
1835 delete dataObjects;
1836 if (!acceptDrag)
1837 return false;
1838 }
1839 return true;
1840 }
1841
1842 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
1843 {
1844 Boolean addDragItem;
1845
1846 wxDataViewCtrl* dataViewCtrlPtr;
1847
1848 wxDataViewItem dataViewItem;
1849
1850
1851 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1852 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1853 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1854 dataViewItem = wxDataViewItem(reinterpret_cast<void*>(itemID));
1855 wxCHECK_MSG(dataViewItem.IsOk(),false,_("Invalid data view item"));
1856
1857 // send a begin drag event and proceed with dragging unless the event is vetoed:
1858 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG,dataViewCtrlPtr->GetId());
1859
1860 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1861 dataViewEvent.SetItem(dataViewItem);
1862 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1863 // the dataview event object is also initialized with a default set of data; as it is a set of data and the user should be able to easily complete
1864 // the object a wxDataObjectComposite object is used;
1865 // currently, the composite object only contains a TAB concatenated string of all data:
1866 wxDataObjectComposite* dataObject(new wxDataObjectComposite());
1867
1868 dataObject->Add(new wxTextDataObject(::ConcatenateDataViewItemValues(dataViewCtrlPtr,dataViewItem)));
1869 dataViewEvent.SetDataObject(dataObject);
1870 // check if event has not been vetoed:
1871 addDragItem = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
1872 if (addDragItem)
1873 {
1874 // for the internal drag & drop functions create two flavors:
1875 // - the data browser's item id;
1876 // - the data contained the dataview event object (if available).
1877 // Definition: a flavor is the type dependent representation of identical data.
1878 // Example: a number can be represented by its value and by its value converted to a string. In this case the flavor
1879 // of the number's internal representation is typeSInt32 while its string representation has got the flavor 'TEXT'.
1880 // Item id is one of the flavors:
1881 wxCHECK_MSG(::AddDragItemFlavor(dragRef,*itemRef,typeUInt32,&itemID,sizeof(itemID),0) == noErr,false,_("Unable to handle native drag&drop data"));
1882 // if the dataview event object contains data it is used for additional flavors; all natively known flavors are supported:
1883 if (dataViewEvent.GetDataObject() != NULL)
1884 {
1885 // constant definition for abbreviational purposes:
1886 size_t const noOfFormats = dataViewEvent.GetDataObject()->GetFormatCount();
1887
1888 if (noOfFormats > 0)
1889 {
1890 // variable definition:
1891 wxDataFormat* dataFormats;
1892
1893 dataFormats = new wxDataFormat[noOfFormats];
1894 dataViewEvent.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get);
1895 for (size_t i=0; i<noOfFormats; ++i)
1896 switch (dataFormats[i].GetType())
1897 {
1898 case wxDF_INVALID:
1899 wxFAIL_MSG(_("Data object has invalid data format"));
1900 break;
1901 case wxDF_TEXT:
1902 {
1903 // constant definition for abbreviational purposes:
1904 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1905 // variable definition and initialization:
1906 wxMemoryBuffer dataObject(dataSize);
1907
1908 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1909 dataObject.UngetWriteBuf(dataSize);
1910 if (::AddDragItemFlavor(dragRef,*itemRef,'TEXT',dataObject.GetData(),dataSize,0) != noErr)
1911 wxFAIL_MSG(_("Adding flavor TEXT failed"));
1912 } /* block */
1913 break;
1914 case wxDF_UNICODETEXT:
1915 {
1916 // constant definition for abbreviational purposes:
1917 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1918 // as there is no direct access to the data copy it to a memory buffer:
1919 wxMemoryBuffer dataObject(dataSize);
1920
1921 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1922 dataObject.UngetWriteBuf(dataSize);
1923 // if the data is stored in unicode format the internal representation is utf-8 (not mentioned in the documentation but in the source code);
1924 // DnD uses fixed utf-16 representation -> use the OSX functions for a conversion:
1925 CFDataRef osxData (::CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,reinterpret_cast<UInt8*>(dataObject.GetData()),dataSize,kCFAllocatorNull));
1926 CFStringRef osxString(::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,osxData,kCFStringEncodingUTF8));
1927
1928 // the osxString contains now the data and therefore the previously occupied memory can be released and re-used:
1929 ::CFRelease(osxData);
1930 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF16,32);
1931 if (::AddDragItemFlavor(dragRef,*itemRef,'utxt',::CFDataGetBytePtr(osxData),::CFDataGetLength(osxData),0) != noErr)
1932 wxFAIL_MSG(_("Adding flavor utxt failed"));
1933 // clean up:
1934 ::CFRelease(osxData);
1935 ::CFRelease(osxString);
1936 } /* block */
1937 break;
1938 case wxDF_BITMAP:
1939 case wxDF_METAFILE:
1940 case wxDF_SYLK:
1941 case wxDF_DIF:
1942 case wxDF_TIFF:
1943 case wxDF_OEMTEXT:
1944 case wxDF_DIB:
1945 case wxDF_PALETTE:
1946 case wxDF_PENDATA:
1947 case wxDF_RIFF:
1948 case wxDF_WAVE:
1949 case wxDF_ENHMETAFILE:
1950 case wxDF_FILENAME:
1951 case wxDF_LOCALE:
1952 case wxDF_PRIVATE:
1953 case wxDF_HTML:
1954 break; // not (yet) supported data formats
1955 default:
1956 wxFAIL_MSG(_("Unknown data format"));
1957 }
1958 delete[] dataFormats;
1959 }
1960 }
1961 }
1962 // clean-up and return result:
1963 delete dataObject;
1964 return addDragItem;
1965 }
1966
1967 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference dragRef, DataBrowserItemID itemID)
1968 {
1969 UInt16 noOfDraggedItems;
1970
1971 wxDataViewCtrl* dataViewCtrlPtr;
1972
1973
1974 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1975 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1976 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1977
1978 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1979 ::CountDragItems(dragRef,&noOfDraggedItems);
1980 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1981 {
1982 bool receiveDrag;
1983 ItemReference itemRef;
1984 wxDataObjectComposite* dataObjects;
1985 wxMemoryBuffer buffer;
1986
1987 // collect native information:
1988 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1989 dataObjects = GetDnDDataObjects(dragRef,itemRef);
1990 // create wxWidget's event:
1991 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP,dataViewCtrlPtr->GetId());
1992
1993 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1994
1995 // this is the item that receives the event (can be an invalid item ID, this is
1996 // especially useful if the dataview does not contain any items)
1997 dataViewEvent.SetItem( wxDataViewItem(reinterpret_cast<void*>(itemID)) );
1998
1999 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
2000 dataViewEvent.SetDataObject(dataObjects);
2001 dataViewEvent.SetDataFormat(GetDnDDataFormat(dataObjects));
2002 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
2003 {
2004 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
2005 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
2006 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
2007 dataViewEvent.SetDataBuffer(buffer.GetData());
2008 }
2009
2010 // send event:
2011 receiveDrag = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
2012 delete dataObjects;
2013 if (!receiveDrag)
2014 return false;
2015 }
2016 return true;
2017 }
2018
2019 //
2020 // drag & drop helper methods
2021 //
2022 wxDataFormat wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite* dataObjects)
2023 {
2024 wxDataFormat resultFormat;
2025
2026
2027 if (dataObjects != NULL)
2028 {
2029 bool compatible(true);
2030
2031 size_t const noOfFormats = dataObjects->GetFormatCount();
2032 size_t indexFormat;
2033
2034 wxDataFormat* formats;
2035
2036 // get all formats and check afterwards if the formats are compatible; if they are compatible the preferred format is returned otherwise
2037 // wxDF_INVALID is returned;
2038 // currently compatible types (ordered by priority are):
2039 // - wxDF_UNICODETEXT - wxDF_TEXT
2040 formats = new wxDataFormat[noOfFormats];
2041 dataObjects->GetAllFormats(formats);
2042 indexFormat = 0;
2043 while ((indexFormat < noOfFormats) && compatible)
2044 {
2045 switch (resultFormat.GetType())
2046 {
2047 case wxDF_INVALID:
2048 resultFormat.SetType(formats[indexFormat].GetType()); // first format (should only be reached if indexFormat == 0
2049 break;
2050 case wxDF_TEXT:
2051 if (formats[indexFormat].GetType() == wxDF_UNICODETEXT)
2052 resultFormat.SetType(wxDF_UNICODETEXT);
2053 else // incompatible
2054 {
2055 resultFormat.SetType(wxDF_INVALID);
2056 compatible = false;
2057 }
2058 break;
2059 case wxDF_UNICODETEXT:
2060 if (formats[indexFormat].GetType() != wxDF_TEXT)
2061 {
2062 resultFormat.SetType(wxDF_INVALID);
2063 compatible = false;
2064 }
2065 break;
2066 default:
2067 resultFormat.SetType(wxDF_INVALID); // not (yet) supported format
2068 compatible = false;
2069 }
2070 ++indexFormat;
2071 } /* while */
2072 // clean up:
2073 delete[] formats;
2074 }
2075 else
2076 resultFormat = wxDF_INVALID;
2077 return resultFormat;
2078 }
2079
2080 wxDataObjectComposite* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference dragRef, ItemReference itemRef) const
2081 {
2082 UInt16 noOfFlavors;
2083
2084 wxDataObjectComposite* dataObject;
2085
2086
2087 ::CountDragItemFlavors(dragRef,itemRef,&noOfFlavors);
2088 if (noOfFlavors > 0)
2089 {
2090 // as the native drag data can be separated into TEXT and UTXT a pointer to a wxTextDataObject is used to track the existence of 'TEXT' and 'utxt' flavors:
2091 wxTextDataObject* textDataObject(NULL);
2092
2093 dataObject = new wxDataObjectComposite();
2094 for (UInt16 indexFlavor=1; indexFlavor<=noOfFlavors; ++indexFlavor)
2095 {
2096 // variable definition:
2097 FlavorType flavorDataObject;
2098
2099 if (::GetFlavorType(dragRef,itemRef,indexFlavor,&flavorDataObject) == noErr) // GetFlavorType uses a 1 based index!
2100 switch (flavorDataObject)
2101 {
2102 case 'TEXT':
2103 if (textDataObject == NULL) // otherwise a 'utxt' flavor has already been found that gets priority compared to the 'TEXT' flavor
2104 {
2105 // variable definitions:
2106 Size nativeDataSize;
2107 wxMemoryBuffer nativeData;
2108
2109 if ((::GetFlavorDataSize(dragRef,itemRef,'TEXT',&nativeDataSize) == noErr) &&
2110 (::GetFlavorData(dragRef,itemRef,'TEXT',nativeData.GetWriteBuf(nativeDataSize),&nativeDataSize,0) == noErr))
2111 {
2112 nativeData.UngetWriteBuf(nativeDataSize);
2113 textDataObject = new wxTextDataObject();
2114 if (textDataObject->SetData(nativeData.GetDataLen(),nativeData.GetData()))
2115 dataObject->Add(textDataObject);
2116 else
2117 {
2118 wxDELETE(textDataObject);
2119 }
2120 }
2121 } /* block */
2122 break;
2123 case 'utxt':
2124 {
2125 // variable definition:
2126 Size nativeDataSize;
2127
2128 if (::GetFlavorDataSize(dragRef,itemRef,'utxt',&nativeDataSize) == noErr)
2129 {
2130 CFMutableDataRef draggedData;
2131
2132 draggedData = ::CFDataCreateMutable(kCFAllocatorDefault,nativeDataSize);
2133 ::CFDataSetLength(draggedData,nativeDataSize);
2134 if (::GetFlavorData(dragRef,itemRef,'utxt',::CFDataGetMutableBytePtr(draggedData),&nativeDataSize,0) == noErr)
2135 {
2136 // convert internally used UTF-16 representation to a UTF-8 representation:
2137 CFDataRef osxData;
2138 CFStringRef osxString;
2139
2140 osxString = ::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,draggedData,kCFStringEncodingUTF16); // BOM character is handled by this function automatically
2141 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF8,32);
2142 if (textDataObject == NULL)
2143 {
2144 textDataObject = new wxTextDataObject();
2145 if (textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData)))
2146 dataObject->Add(textDataObject);
2147 else
2148 {
2149 wxDELETE(textDataObject);
2150 }
2151 }
2152 else // overwrite data because the 'utxt' flavor has priority over the 'TEXT' flavor
2153 (void) textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData));
2154 // clean up:
2155 ::CFRelease(osxData);
2156 ::CFRelease(osxString);
2157 }
2158 // clean up:
2159 ::CFRelease(draggedData);
2160 }
2161 } /* block */
2162 break;
2163 }
2164 }
2165 }
2166 else
2167 dataObject = NULL;
2168 return dataObject;
2169 }
2170
2171 //
2172 // other methods
2173 //
2174 wxDataViewColumn* wxMacDataViewDataBrowserListViewControl::GetColumnPtr(DataBrowserPropertyID propertyID) const
2175 {
2176 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
2177
2178 if (dataViewCtrlPtr != NULL)
2179 {
2180 size_t const noOfColumns = dataViewCtrlPtr->GetColumnCount();
2181
2182 for (size_t i=0; i<noOfColumns; ++i)
2183 if (dataViewCtrlPtr->GetColumnPtr(i)->GetNativeData()->GetPropertyID() == propertyID)
2184 return dataViewCtrlPtr->GetColumnPtr(i);
2185 }
2186 return NULL;
2187 }
2188
2189 // ---------------------------------------------------------
2190 // wxDataViewRenderer
2191 // ---------------------------------------------------------
2192 wxDataViewRenderer::wxDataViewRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2193 :wxDataViewRendererBase(varianttype,mode,align), m_alignment(align), m_mode(mode), m_NativeDataPtr(NULL)
2194 {
2195 }
2196
2197 wxDataViewRenderer::~wxDataViewRenderer()
2198 {
2199 delete m_NativeDataPtr;
2200 }
2201
2202 void wxDataViewRenderer::SetAlignment(int align)
2203 {
2204 m_alignment = align;
2205 }
2206
2207 namespace
2208 {
2209
2210 // get the browser control or NULL if anything went wrong (it's not supposed to
2211 // so we assert if it did)
2212 wxMacDataViewDataBrowserListViewControl *
2213 GetBrowserFromCol(wxDataViewColumn *col)
2214 {
2215 wxCHECK_MSG( col, NULL, "should have a valid column" );
2216
2217 wxDataViewCtrl * const dvc = col->GetOwner();
2218 wxCHECK_MSG( dvc, NULL, "column must be associated with the control" );
2219
2220 return static_cast<wxMacDataViewDataBrowserListViewControl *>(dvc->GetPeer());
2221 }
2222
2223 } // anonymous namespace
2224
2225 void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
2226 {
2227 wxDataViewColumn * const col = GetOwner();
2228 wxMacDataViewDataBrowserListViewControl * const
2229 browser = GetBrowserFromCol(col);
2230 wxCHECK_RET( browser, "must be fully initialized" );
2231
2232 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2233
2234 DataBrowserPropertyFlags flags;
2235 verify_noerr( browser->GetPropertyFlags(colID, &flags) );
2236
2237 if ( (mode == wxDATAVIEW_CELL_EDITABLE) ||
2238 (mode == wxDATAVIEW_CELL_ACTIVATABLE) )
2239 flags |= kDataBrowserPropertyIsEditable;
2240 else
2241 flags &= ~kDataBrowserPropertyIsEditable;
2242
2243 verify_noerr( browser->SetPropertyFlags(colID, flags) );
2244 }
2245
2246 void wxDataViewRenderer::EnableEllipsize(wxEllipsizeMode mode)
2247 {
2248 wxDataViewColumn * const col = GetOwner();
2249
2250 wxMacDataViewDataBrowserListViewControl * const
2251 browser = GetBrowserFromCol(col);
2252 wxCHECK_RET( browser, "must be fully initialized" );
2253
2254 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2255
2256 DataBrowserPropertyFlags flags;
2257 browser->GetPropertyFlags(colID, &flags);
2258
2259 flags &= ~(kDataBrowserDoNotTruncateText |
2260 kDataBrowserTruncateTextAtStart |
2261 kDataBrowserTruncateTextMiddle |
2262 kDataBrowserTruncateTextAtEnd);
2263
2264 int flagToSet = 0;
2265 switch ( mode )
2266 {
2267 case wxELLIPSIZE_NONE:
2268 flagToSet = kDataBrowserDoNotTruncateText;
2269 break;
2270
2271 case wxELLIPSIZE_START:
2272 flagToSet = kDataBrowserTruncateTextAtStart;
2273 break;
2274
2275 case wxELLIPSIZE_MIDDLE:
2276 flagToSet = kDataBrowserTruncateTextMiddle;
2277 break;
2278
2279 case wxELLIPSIZE_END:
2280 flagToSet = kDataBrowserTruncateTextAtEnd;
2281 break;
2282 }
2283
2284 wxCHECK_RET( flagToSet, "unknown wxEllipsizeMode value" );
2285
2286 flags |= flagToSet;
2287 verify_noerr( browser->SetPropertyFlags(colID, flags) );
2288 }
2289
2290 wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
2291 {
2292 wxDataViewColumn * const col = GetOwner();
2293
2294 wxMacDataViewDataBrowserListViewControl * const
2295 browser = GetBrowserFromCol(col);
2296 wxCHECK_MSG( browser, wxELLIPSIZE_NONE, "must be fully initialized" );
2297
2298 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2299
2300 DataBrowserPropertyFlags flags;
2301 browser->GetPropertyFlags(colID, &flags);
2302
2303 if ( flags & kDataBrowserDoNotTruncateText )
2304 return wxELLIPSIZE_NONE;
2305 if ( flags & kDataBrowserTruncateTextAtStart )
2306 return wxELLIPSIZE_START;
2307 if ( flags & kDataBrowserTruncateTextAtEnd )
2308 return wxELLIPSIZE_END;
2309
2310 // kDataBrowserTruncateTextMiddle == 0 so there is no need to test for it
2311 return wxELLIPSIZE_MIDDLE;
2312 }
2313
2314 void wxDataViewRenderer::SetNativeData(wxDataViewRendererNativeData* newNativeDataPtr)
2315 {
2316 delete m_NativeDataPtr;
2317 m_NativeDataPtr = newNativeDataPtr;
2318 }
2319
2320 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
2321
2322 // ---------------------------------------------------------
2323 // wxDataViewCustomRenderer
2324 // ---------------------------------------------------------
2325 wxDataViewCustomRenderer::wxDataViewCustomRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2326 :wxDataViewCustomRendererBase(varianttype,mode,align),
2327 m_editorCtrlPtr(NULL),
2328 m_DCPtr(NULL)
2329 {
2330 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserCustomType));
2331 }
2332
2333 bool wxDataViewCustomRenderer::MacRender()
2334 {
2335 return true;
2336 }
2337
2338 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
2339
2340 // ---------------------------------------------------------
2341 // wxDataViewTextRenderer
2342 // ---------------------------------------------------------
2343 wxDataViewTextRenderer::wxDataViewTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2344 :wxDataViewRenderer(varianttype,mode,align)
2345 {
2346 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserTextType));
2347 }
2348
2349 bool wxDataViewTextRenderer::MacRender()
2350 {
2351 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Text renderer cannot render value; value type: ")) << GetValue().GetType());
2352
2353 wxCFStringRef cfString(GetValue().GetString(),(GetView()->GetFont().IsOk() ? GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2354 return (::SetDataBrowserItemDataText(GetNativeData()->GetItemDataRef(),cfString) == noErr);
2355 }
2356
2357 IMPLEMENT_CLASS(wxDataViewTextRenderer,wxDataViewRenderer)
2358
2359 // ---------------------------------------------------------
2360 // wxDataViewBitmapRenderer
2361 // ---------------------------------------------------------
2362 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2363 :wxDataViewRenderer(varianttype,mode,align)
2364 {
2365 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserIconType));
2366 }
2367
2368 bool wxDataViewBitmapRenderer::MacRender()
2369 // This method returns 'true' if
2370 // - the passed bitmap is valid and it could be assigned to the native data browser;
2371 // - the passed bitmap is invalid (or is not initialized); this case simulates a non-existing bitmap.
2372 // In all other cases the method returns 'false'.
2373 {
2374 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Bitmap renderer cannot render value; value type: ")) << GetValue().GetType());
2375
2376 wxBitmap bitmap;
2377
2378 bitmap << GetValue();
2379 return (!(bitmap.IsOk()) || (::SetDataBrowserItemDataIcon(GetNativeData()->GetItemDataRef(),bitmap.GetIconRef()) == noErr));
2380 }
2381
2382 IMPLEMENT_CLASS(wxDataViewBitmapRenderer,wxDataViewRenderer)
2383
2384 // ---------------------------------------------------------
2385 // wxDataViewIconTextRenderer
2386 // ---------------------------------------------------------
2387 wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(
2388 const wxString& varianttype,
2389 wxDataViewCellMode mode,
2390 int WXUNUSED(align))
2391 :wxDataViewRenderer(varianttype,mode)
2392 {
2393 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserIconAndTextType));
2394 }
2395
2396 bool wxDataViewIconTextRenderer::MacRender()
2397 {
2398 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Icon & text renderer cannot render value; value type: ")) << GetValue().GetType());
2399
2400 wxDataViewIconText iconText;
2401
2402 iconText << GetValue();
2403
2404 wxCFStringRef cfString(iconText.GetText(),(GetView()->GetFont().IsOk() ? GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2405
2406 if (iconText.GetIcon().IsOk())
2407 if (::SetDataBrowserItemDataIcon(GetNativeData()->GetItemDataRef(),MAC_WXHICON(iconText.GetIcon().GetHICON())) != noErr)
2408 return false;
2409 return (::SetDataBrowserItemDataText(GetNativeData()->GetItemDataRef(),cfString) == noErr);
2410 }
2411
2412 IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
2413
2414
2415 // ---------------------------------------------------------
2416 // wxDataViewToggleRenderer
2417 // ---------------------------------------------------------
2418 wxDataViewToggleRenderer::wxDataViewToggleRenderer(
2419 const wxString& varianttype,
2420 wxDataViewCellMode mode,
2421 int WXUNUSED(align))
2422 :wxDataViewRenderer(varianttype,mode)
2423 {
2424 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserCheckboxType));
2425 }
2426
2427 bool wxDataViewToggleRenderer::MacRender()
2428 {
2429 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Toggle renderer cannot render value; value type: ")) << GetValue().GetType());
2430 return (::SetDataBrowserItemDataButtonValue(GetNativeData()->GetItemDataRef(),GetValue().GetBool()) == noErr);
2431 }
2432
2433 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer,wxDataViewRenderer)
2434
2435 // ---------------------------------------------------------
2436 // wxDataViewProgressRenderer
2437 // ---------------------------------------------------------
2438 wxDataViewProgressRenderer::wxDataViewProgressRenderer(
2439 const wxString& WXUNUSED(label),
2440 wxString const& varianttype,
2441 wxDataViewCellMode mode,
2442 int align)
2443 :wxDataViewRenderer(varianttype,mode,align)
2444 {
2445 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserProgressBarType));
2446 }
2447
2448 bool wxDataViewProgressRenderer::MacRender()
2449 {
2450 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Progress renderer cannot render value type; value type: ")) << GetValue().GetType());
2451 return ((::SetDataBrowserItemDataMinimum(GetNativeData()->GetItemDataRef(), 0) == noErr) &&
2452 (::SetDataBrowserItemDataMaximum(GetNativeData()->GetItemDataRef(),100) == noErr) &&
2453 (::SetDataBrowserItemDataValue (GetNativeData()->GetItemDataRef(),GetValue().GetLong()) == noErr));
2454 }
2455
2456 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer,wxDataViewRenderer)
2457
2458 // ---------------------------------------------------------
2459 // wxDataViewDateRenderer
2460 // ---------------------------------------------------------
2461 wxDataViewDateRenderer::wxDataViewDateRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2462 :wxDataViewRenderer(varianttype,mode,align)
2463 {
2464 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserDateTimeType));
2465 }
2466
2467 bool wxDataViewDateRenderer::MacRender()
2468 {
2469 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Date renderer cannot render value; value type: ")) << GetValue().GetType());
2470 return (::SetDataBrowserItemDataDateTime(GetNativeData()->GetItemDataRef(),GetValue().GetDateTime().Subtract(wxDateTime(1,wxDateTime::Jan,1904)).GetSeconds().GetLo()) == noErr);
2471 }
2472
2473 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer,wxDataViewRenderer)
2474
2475 // ---------------------------------------------------------
2476 // wxDataViewColumn
2477 // ---------------------------------------------------------
2478 wxDataViewColumn::wxDataViewColumn(const wxString& title, wxDataViewRenderer* renderer, unsigned int model_column, int width, wxAlignment align, int flags)
2479 :wxDataViewColumnBase(renderer, model_column), m_NativeDataPtr(new wxDataViewColumnNativeData()), m_title(title)
2480 {
2481 InitCommon(width, align, flags);
2482 if ((renderer != NULL) && !renderer->IsCustomRenderer() &&
2483 (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
2484 renderer->SetAlignment(align);
2485 }
2486
2487 wxDataViewColumn::wxDataViewColumn(const wxBitmap& bitmap, wxDataViewRenderer* renderer, unsigned int model_column, int width, wxAlignment align, int flags)
2488 :wxDataViewColumnBase(bitmap, renderer, model_column), m_NativeDataPtr(new wxDataViewColumnNativeData())
2489 {
2490 InitCommon(width, align, flags);
2491 if ((renderer != NULL) && !renderer->IsCustomRenderer() &&
2492 (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
2493 renderer->SetAlignment(align);
2494 }
2495
2496 wxDataViewColumn::~wxDataViewColumn()
2497 {
2498 delete m_NativeDataPtr;
2499 }
2500
2501 int wxDataViewColumn::GetWidth() const
2502 {
2503 // FIXME: This returns the last programmatically set width and will not work if
2504 // the user changes the column's width by dragging it with the mouse.
2505 return m_width;
2506 }
2507
2508 bool wxDataViewColumn::IsSortKey() const
2509 {
2510 wxDataViewCtrl * const dataViewCtrlPtr(GetOwner());
2511 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(
2512 dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(
2513 dataViewCtrlPtr->GetPeer()));
2514
2515 DataBrowserPropertyID propertyID;
2516 return (macDataViewListCtrlPtr->GetSortProperty(&propertyID) == noErr) &&
2517 (propertyID == GetNativeData()->GetPropertyID());
2518 }
2519
2520 void wxDataViewColumn::SetAlignment(wxAlignment align)
2521 {
2522 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2523
2524
2525 m_alignment = align;
2526 if (dataViewCtrlPtr != NULL)
2527 {
2528 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2529
2530 if (macDataViewListCtrlPtr != NULL)
2531 {
2532 DataBrowserListViewHeaderDesc headerDescription;
2533
2534 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2535 switch (align)
2536 {
2537 case wxALIGN_CENTER:
2538 case wxALIGN_CENTER_HORIZONTAL:
2539 headerDescription.btnFontStyle.just = teCenter;
2540 break;
2541 case wxALIGN_LEFT:
2542 headerDescription.btnFontStyle.just = teFlushLeft;
2543 break;
2544 case wxALIGN_RIGHT:
2545 headerDescription.btnFontStyle.just = teFlushRight;
2546 break;
2547 default:
2548 headerDescription.btnFontStyle.just = teFlushDefault;
2549 }
2550 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set alignment."));
2551 }
2552 }
2553 }
2554
2555 void wxDataViewColumn::SetBitmap(wxBitmap const& bitmap)
2556 {
2557 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2558
2559
2560 wxDataViewColumnBase::SetBitmap(bitmap);
2561 if (dataViewCtrlPtr != NULL)
2562 {
2563 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2564
2565 if (macDataViewListCtrlPtr != NULL)
2566 {
2567 DataBrowserListViewHeaderDesc headerDescription;
2568
2569 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2570 if (GetBitmap().IsOk())
2571 headerDescription.btnContentInfo.u.iconRef = GetBitmap().GetIconRef();
2572 else
2573 headerDescription.btnContentInfo.u.iconRef = NULL;
2574 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set icon."));
2575 }
2576 }
2577 }
2578
2579 void wxDataViewColumn::SetMaxWidth(int maxWidth)
2580 {
2581 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2582
2583
2584 m_maxWidth = maxWidth;
2585 if (dataViewCtrlPtr != NULL)
2586 {
2587 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2588
2589 if (macDataViewListCtrlPtr != NULL)
2590 {
2591 DataBrowserListViewHeaderDesc headerDescription;
2592
2593 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2594 headerDescription.maximumWidth = static_cast<UInt16>(maxWidth);
2595 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set maximum width."));
2596 }
2597 }
2598 }
2599
2600 void wxDataViewColumn::SetMinWidth(int minWidth)
2601 {
2602 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2603
2604
2605 m_minWidth = minWidth;
2606 if (dataViewCtrlPtr != NULL)
2607 {
2608 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2609
2610 if (macDataViewListCtrlPtr != NULL)
2611 {
2612 DataBrowserListViewHeaderDesc headerDescription;
2613
2614 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2615 headerDescription.minimumWidth = static_cast<UInt16>(minWidth);
2616 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set minimum width."));
2617 }
2618 }
2619 }
2620
2621 void wxDataViewColumn::SetReorderable(bool reorderable)
2622 {
2623 // first set the internal flag of the column:
2624 if (reorderable)
2625 m_flags |= wxDATAVIEW_COL_REORDERABLE;
2626 else
2627 m_flags &= ~wxDATAVIEW_COL_REORDERABLE;
2628 // if the column is associated with a control change also immediately the flags of the control:
2629 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2630
2631 if (dataViewCtrlPtr != NULL)
2632 {
2633 DataBrowserPropertyFlags flags;
2634 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2635
2636 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
2637 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(GetNativeData()->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
2638 if (reorderable)
2639 flags |= kDataBrowserListViewMovableColumn;
2640 else
2641 flags &= ~kDataBrowserListViewMovableColumn;
2642 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(GetNativeData()->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
2643 }
2644 }
2645
2646 void wxDataViewColumn::SetResizeable(bool resizable)
2647 {
2648 // first set the internal flag of the column:
2649 if (resizable)
2650 m_flags |= wxDATAVIEW_COL_RESIZABLE;
2651 else
2652 m_flags &= ~wxDATAVIEW_COL_RESIZABLE;
2653 // if the column is associated with a control change also immediately the flags of the control:
2654 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2655
2656 if (dataViewCtrlPtr != NULL)
2657 {
2658 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2659
2660 if (macDataViewListCtrlPtr != NULL)
2661 {
2662 DataBrowserListViewHeaderDesc headerDescription;
2663
2664 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2665 if (resizable)
2666 {
2667 if (GetMinWidth() >= GetMaxWidth())
2668 {
2669 m_minWidth = 0;
2670 m_maxWidth = 30000;
2671 }
2672 headerDescription.minimumWidth = m_minWidth;
2673 headerDescription.maximumWidth = m_maxWidth;
2674 }
2675 else
2676 {
2677 headerDescription.minimumWidth = m_width;
2678 headerDescription.maximumWidth = m_width;
2679 }
2680 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2681 macDataViewListCtrlPtr->SetSortProperty(GetNativeData()->GetPropertyID());
2682 }
2683 }
2684 }
2685
2686 void wxDataViewColumn::SetSortable(bool sortable)
2687 {
2688 // first set the internal flag of the column:
2689 if (sortable)
2690 m_flags |= wxDATAVIEW_COL_SORTABLE;
2691 else
2692 m_flags &= ~wxDATAVIEW_COL_SORTABLE;
2693 // if the column is associated with a control change also immediately the flags of the control:
2694 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2695
2696 if (dataViewCtrlPtr != NULL)
2697 {
2698 DataBrowserPropertyFlags flags;
2699 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2700
2701 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
2702 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(GetNativeData()->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
2703 if (sortable)
2704 flags |= kDataBrowserListViewSortableColumn;
2705 else
2706 flags &= ~kDataBrowserListViewSortableColumn;
2707 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(GetNativeData()->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
2708 }
2709 }
2710
2711 void wxDataViewColumn::SetSortOrder(bool ascending)
2712 {
2713 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2714
2715
2716 m_ascending = ascending;
2717 if (dataViewCtrlPtr != NULL)
2718 {
2719 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2720
2721 if (macDataViewListCtrlPtr != NULL)
2722 {
2723 DataBrowserListViewHeaderDesc headerDescription;
2724
2725 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2726 if (ascending)
2727 headerDescription.initialOrder = kDataBrowserOrderIncreasing;
2728 else
2729 headerDescription.initialOrder = kDataBrowserOrderDecreasing;
2730 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2731 macDataViewListCtrlPtr->SetSortProperty(GetNativeData()->GetPropertyID());
2732 }
2733 }
2734 }
2735
2736 void wxDataViewColumn::SetTitle(wxString const& title)
2737 {
2738 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2739
2740
2741 m_title = title;
2742 if (dataViewCtrlPtr != NULL)
2743 {
2744 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2745
2746 if (macDataViewListCtrlPtr != NULL)
2747 {
2748 DataBrowserListViewHeaderDesc headerDescription;
2749 wxCFStringRef cfTitle(title,(dataViewCtrlPtr->GetFont().IsOk() ? dataViewCtrlPtr->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2750
2751 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2752 headerDescription.titleString = cfTitle;
2753 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set header description."));
2754 }
2755 }
2756 }
2757
2758 void wxDataViewColumn::SetWidth(int width)
2759 {
2760 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2761
2762 switch ( width )
2763 {
2764 case wxCOL_WIDTH_AUTOSIZE:
2765 // not implemented, fall through
2766 case wxCOL_WIDTH_DEFAULT:
2767 width = wxDVC_DEFAULT_WIDTH;
2768 break;
2769 default:
2770 break;
2771 }
2772
2773 if ((width >= m_minWidth) && (width <= m_maxWidth))
2774 {
2775 m_width = width;
2776 if (dataViewCtrlPtr != NULL)
2777 {
2778 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2779
2780 if (macDataViewListCtrlPtr != NULL)
2781 wxCHECK_RET(macDataViewListCtrlPtr->SetColumnWidth(GetNativeData()->GetPropertyID(),static_cast<UInt16>(width)) == noErr,_("Could not set column width."));
2782 }
2783 }
2784 }
2785
2786 void wxDataViewColumn::SetHidden(bool WXUNUSED(hidden))
2787 {
2788 // How to do that?
2789 }
2790
2791 bool wxDataViewColumn::IsHidden() const
2792 {
2793 return true;
2794 }
2795
2796
2797 void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
2798 {
2799 // see wxGTK native wxDataViewColumn implementation
2800 wxFAIL_MSG( "not implemented" );
2801 }
2802
2803 void wxDataViewColumn::SetNativeData(wxDataViewColumnNativeData* newNativeDataPtr)
2804 {
2805 delete m_NativeDataPtr;
2806 m_NativeDataPtr = newNativeDataPtr;
2807 }
2808
2809 #endif // wxUSE_DATAVIEWCTRL && !wxUSE_GENERICDATAVIEWCTRL