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