]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/databrow.cpp
fix wxDataObjectComposite::GetFormatCount and add some comments to explain the reason...
[wxWidgets.git] / src / osx / carbon / databrow.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/databrow.cpp
3 // Purpose: Classes and functions for the Carbon data browser
4 // Author:
5 // Modified by:
6 // Created: 2007-05-18
7 // RCS-ID: $Id$
8 // Copyright: (c)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_DATAVIEWCTRL
15 #ifndef wxUSE_GENERICDATAVIEWCTRL
16
17 #ifndef WX_PRECOMP
18 #include "wx/app.h"
19 #include "wx/toplevel.h"
20 #include "wx/font.h"
21 #include "wx/settings.h"
22 #include "wx/utils.h"
23 #endif
24
25 #include "wx/dataview.h"
26 #include "wx/osx/carbon/databrow.h"
27 #include "wx/osx/private.h"
28 #include "wx/osx/uma.h"
29
30 #include <limits>
31
32 // ============================================================================
33 // Variables used globally in databrow.cpp
34 // ============================================================================
35 DataBrowserGetContextualMenuUPP gDataBrowserTableViewGetContextualMenuUPP = NULL;
36 DataBrowserItemCompareUPP gDataBrowserTableViewItemCompareUPP = NULL;
37 DataBrowserItemDataUPP gDataBrowserTableViewItemDataUPP = NULL;
38 DataBrowserItemNotificationUPP gDataBrowserTableViewItemNotificationUPP = NULL;
39
40 DataBrowserAcceptDragUPP gDataBrowserTableViewAcceptDragUPP = NULL;
41 DataBrowserAddDragItemUPP gDataBrowserTableViewAddDragItemUPP = NULL;
42 DataBrowserReceiveDragUPP gDataBrowserTableViewReceiveDragUPP = NULL;
43
44 DataBrowserDrawItemUPP gDataBrowserTableViewDrawItemUPP = NULL;
45 DataBrowserEditItemUPP gDataBrowserTableViewEditItemUPP = NULL;
46 DataBrowserHitTestUPP gDataBrowserTableViewHitTestUPP = NULL;
47 DataBrowserTrackingUPP gDataBrowserTableViewTrackingUPP = NULL;
48
49 // ============================================================================
50 // wxMacDataBrowserTableViewControl
51 // ============================================================================
52
53 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserCompareProc(ControlRef browser, DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
54 {
55 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
56
57
58 if (ControlPtr != NULL)
59 return ControlPtr->DataBrowserCompareProc(itemOneID,itemTwoID,sortProperty);
60 else
61 return errDataBrowserPropertyNotSupported;
62 } /* wxMacDataBrowserTableViewControl::DataBrowserCompareProc(ControlRef, DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID) */
63
64 pascal void wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc(ControlRef browser, MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* selection)
65 {
66 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
67
68
69 if (ControlPtr != NULL)
70 ControlPtr->DataBrowserGetContextualMenuProc(menu,helpType,helpItemString,selection);
71 } /* wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc(ControlRef, MenuRef*, UInt32*, CFStringRef*, AEDesc*) */
72
73 pascal OSStatus wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
74 {
75 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
76
77
78 if (ControlPtr != NULL)
79 return ControlPtr->DataBrowserGetSetItemDataProc(itemID,propertyID,itemData,getValue);
80 else
81 return errDataBrowserPropertyNotSupported;
82 } /* wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean) */
83
84 pascal void wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
85 {
86 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
87
88
89 if (ControlPtr != NULL)
90 ControlPtr->DataBrowserItemNotificationProc(itemID,message,itemData);
91 } /* wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc(ControlRef, DataBrowserItemID, DataBrowserItemNotification, DataBrowserItemDataRef) */
92
93 pascal void wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemState state, Rect const* rectangle, SInt16 bitDepth, Boolean colorDevice)
94 {
95 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
96
97
98 if (ControlPtr != NULL)
99 ControlPtr->DataBrowserDrawItemProc(itemID,propertyID,state,rectangle,bitDepth,colorDevice);
100 } /* wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemState, Rect const*, SInt16, Boolean) */
101
102 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserEditItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
103 {
104 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
105
106
107 return ((ControlPtr != NULL) && ControlPtr->DataBrowserEditItemProc(itemID,propertyID,theString,maxEditTextRect,shrinkToFit));
108 } /* wxMacDataBrowserTableViewControl::DataBrowserEditItemProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, CFStringRef, Rect*, Boolean*) */
109
110 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserHitTestProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Rect const* mouseRect)
111 {
112 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
113
114
115 return ((ControlPtr != NULL) && ControlPtr->DataBrowserHitTestProc(itemID,propertyID,theRect,mouseRect));
116 } /* wxMacDataBrowserTableViewControl::DataBrowserHitTestProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, Rect const*, Rect const*) */
117
118 pascal DataBrowserTrackingResult wxMacDataBrowserTableViewControl::DataBrowserTrackingProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point startPt, EventModifiers modifiers)
119 {
120 wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
121
122
123 if (ControlPtr != NULL)
124 return ControlPtr->DataBrowserTrackingProc(itemID,propertyID,theRect,startPt,modifiers);
125 else
126 return kDataBrowserNothingHit;
127 } /* wxMacDataBrowserTableViewControl::DataBrowserTrackingProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, Rect const*, Point, EventModifiers) */
128
129 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserAcceptDragProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID)
130 {
131 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
132
133
134 return ((controlPtr != NULL) && controlPtr->DataBrowserAcceptDragProc(dragRef,itemID));
135 } /* wxMacDataBrowserTableViewControl::DataBrowserAcceptDragProc(ControlRef, DragReference, DataBrowserItemID) */
136
137 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserAddDragItemProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
138 {
139 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
140
141
142 return ((controlPtr != NULL) && controlPtr->DataBrowserAddDragItemProc(dragRef,itemID,itemRef));
143 } /* wxMacDataBrowserTableViewControl::DataBrowserAddDragItemProc(ControlRef, DragReference, DataBrowserItemID, ItemReference*) */
144
145 pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserReceiveDragProc(ControlRef browser, DragReference dragRef, DataBrowserItemID itemID)
146 {
147 wxMacDataBrowserTableViewControl* controlPtr(dynamic_cast<wxMacDataBrowserTableViewControl*>(wxMacControl::GetReferenceFromNativeControl(browser)));
148
149
150 return ((controlPtr != NULL) && controlPtr->DataBrowserReceiveDragProc(dragRef,itemID));
151 } /* wxMacDataBrowserTableViewControl::DataBrowserReceiveDragProc(ControlRef, DragReference, DataBrowserItemID) */
152
153 wxMacDataBrowserTableViewControl::wxMacDataBrowserTableViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
154 :wxMacControl(peer)
155 {
156 Rect bounds = wxMacGetBoundsForControl(peer,pos,size);
157 OSStatus err = ::CreateDataBrowserControl(MAC_WXHWND(peer->MacGetTopLevelWindowRef()),&bounds,kDataBrowserListView,&(this->m_controlRef));
158
159
160 SetReferenceInNativeControl();
161 verify_noerr(err);
162 // setup standard callbacks:
163 if (gDataBrowserTableViewGetContextualMenuUPP == NULL) gDataBrowserTableViewGetContextualMenuUPP = NewDataBrowserGetContextualMenuUPP(wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc);
164 if (gDataBrowserTableViewItemCompareUPP == NULL) gDataBrowserTableViewItemCompareUPP = NewDataBrowserItemCompareUPP (wxMacDataBrowserTableViewControl::DataBrowserCompareProc);
165 if (gDataBrowserTableViewItemDataUPP == NULL) gDataBrowserTableViewItemDataUPP = NewDataBrowserItemDataUPP (wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc);
166 if (gDataBrowserTableViewItemNotificationUPP == NULL)
167 {
168 gDataBrowserTableViewItemNotificationUPP =
169 #if TARGET_API_MAC_OSX
170 (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
171 #else
172 NewDataBrowserItemNotificationUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
173 #endif
174 }
175 // setup drag and drop callbacks:
176 if (gDataBrowserTableViewAcceptDragUPP == NULL) gDataBrowserTableViewAcceptDragUPP = NewDataBrowserAcceptDragUPP (wxMacDataBrowserTableViewControl::DataBrowserAcceptDragProc);
177 if (gDataBrowserTableViewAddDragItemUPP == NULL) gDataBrowserTableViewAddDragItemUPP = NewDataBrowserAddDragItemUPP(wxMacDataBrowserTableViewControl::DataBrowserAddDragItemProc);
178 if (gDataBrowserTableViewReceiveDragUPP == NULL) gDataBrowserTableViewReceiveDragUPP = NewDataBrowserReceiveDragUPP(wxMacDataBrowserTableViewControl::DataBrowserReceiveDragProc);
179
180 DataBrowserCallbacks callbacks; // variable definition
181
182 InitializeDataBrowserCallbacks(&callbacks,kDataBrowserLatestCallbacks);
183 callbacks.u.v1.getContextualMenuCallback = gDataBrowserTableViewGetContextualMenuUPP;
184 callbacks.u.v1.itemDataCallback = gDataBrowserTableViewItemDataUPP;
185 callbacks.u.v1.itemCompareCallback = gDataBrowserTableViewItemCompareUPP;
186 callbacks.u.v1.itemNotificationCallback = gDataBrowserTableViewItemNotificationUPP;
187 callbacks.u.v1.acceptDragCallback = gDataBrowserTableViewAcceptDragUPP;
188 callbacks.u.v1.addDragItemCallback = gDataBrowserTableViewAddDragItemUPP;
189 callbacks.u.v1.receiveDragCallback = gDataBrowserTableViewReceiveDragUPP;
190 this->SetCallbacks(&callbacks);
191
192 // setup callbacks for customized items:
193 if (gDataBrowserTableViewDrawItemUPP == NULL) gDataBrowserTableViewDrawItemUPP = NewDataBrowserDrawItemUPP(wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc);
194 if (gDataBrowserTableViewEditItemUPP == NULL) gDataBrowserTableViewEditItemUPP = NewDataBrowserEditItemUPP(wxMacDataBrowserTableViewControl::DataBrowserEditItemProc);
195 if (gDataBrowserTableViewHitTestUPP == NULL) gDataBrowserTableViewHitTestUPP = NewDataBrowserHitTestUPP (wxMacDataBrowserTableViewControl::DataBrowserHitTestProc);
196 if (gDataBrowserTableViewTrackingUPP == NULL) gDataBrowserTableViewTrackingUPP = NewDataBrowserTrackingUPP(wxMacDataBrowserTableViewControl::DataBrowserTrackingProc);
197
198 DataBrowserCustomCallbacks customCallbacks; // variable definition
199
200 InitializeDataBrowserCustomCallbacks(&customCallbacks,kDataBrowserLatestCallbacks);
201 customCallbacks.u.v1.drawItemCallback = gDataBrowserTableViewDrawItemUPP;
202 customCallbacks.u.v1.editTextCallback = gDataBrowserTableViewEditItemUPP;
203 customCallbacks.u.v1.hitTestCallback = gDataBrowserTableViewHitTestUPP;
204 customCallbacks.u.v1.trackingCallback = gDataBrowserTableViewTrackingUPP;
205 this->SetCustomCallbacks(&customCallbacks);
206
207 // style setting:
208 this->EnableCellSizeModification( ((style & wxDV_VARIABLE_LINE_HEIGHT) != 0), true );
209
210 DataBrowserSelectionFlags flags; // variable definition
211
212 if (this->GetSelectionFlags(&flags) == noErr) // get default settings
213 {
214 if ((style & wxDV_MULTIPLE) != 0)
215 flags &= ~kDataBrowserSelectOnlyOne;
216 else
217 flags |= kDataBrowserSelectOnlyOne;
218 (void) this->SetSelectionFlags(flags);
219 } /* if */
220
221 OptionBits attributes; // variable definition
222
223 if (this->GetAttributes(&attributes) == noErr) // get default settings
224 {
225 if ((style & wxDV_VERT_RULES) != 0)
226 attributes |= kDataBrowserAttributeListViewDrawColumnDividers;
227 else
228 attributes &= ~kDataBrowserAttributeListViewDrawColumnDividers;
229 if ((style & wxDV_ROW_LINES) != 0)
230 attributes |= kDataBrowserAttributeListViewAlternatingRowColors;
231 else
232 attributes &= ~kDataBrowserAttributeListViewAlternatingRowColors;
233 (void) this->SetAttributes(attributes);
234 } /* if */
235
236 if ((style & wxDV_NO_HEADER) != 0)
237 this->SetHeaderButtonHeight(0);
238 } /* wxMacDataBrowserTableViewControl::wxMacDataBrowserTableViewControl(wxWindow*, wxPoint const&, wxSize const&, long) */
239
240 //
241 // callback handling
242 //
243 OSStatus wxMacDataBrowserTableViewControl::SetCallbacks(DataBrowserCallbacks const* callbacks)
244 {
245 return ::SetDataBrowserCallbacks(this->m_controlRef,callbacks);
246 } /* wxMacDataBrowserTableViewControl::SetCallbacks(DataBrowserCallbacks const*) */
247
248 OSStatus wxMacDataBrowserTableViewControl::SetCustomCallbacks(DataBrowserCustomCallbacks const* customCallbacks)
249 {
250 return ::SetDataBrowserCustomCallbacks(this->m_controlRef,customCallbacks);
251 } /* xMacDataBrowserTableViewControl::SetCustomCallbacks(DataBrowserCustomCallbacks const*) */
252
253 //
254 // header handling
255 //
256 OSStatus wxMacDataBrowserTableViewControl::GetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc) const
257 {
258 desc->version = kDataBrowserListViewLatestHeaderDesc; // if this statement is missing the next call will fail (NOT DOCUMENTED!!)
259 return ::GetDataBrowserListViewHeaderDesc(this->m_controlRef,propertyID,desc);
260 }
261
262 OSStatus wxMacDataBrowserTableViewControl::SetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc)
263 {
264 return ::SetDataBrowserListViewHeaderDesc(this->m_controlRef,propertyID,desc);
265 }
266
267 //
268 // layout handling
269 //
270 OSStatus wxMacDataBrowserTableViewControl::AutoSizeColumns()
271 {
272 return AutoSizeDataBrowserListViewColumns(this->m_controlRef);
273 }
274
275 OSStatus wxMacDataBrowserTableViewControl::EnableCellSizeModification(bool enableHeight, bool enableWidth)
276 {
277 return ::SetDataBrowserTableViewGeometry(this->GetControlRef(),enableWidth,enableHeight);
278 } /* wxMacDataBrowserTableViewControl::EnableCellSizeModification(bool, bool) */
279
280 OSStatus wxMacDataBrowserTableViewControl::GetAttributes(OptionBits* attributes)
281 {
282 return ::DataBrowserGetAttributes(this->GetControlRef(),attributes);
283 } /* wxMacDataBrowserTableViewControl::GetAttributes(OptionBits*) */
284
285 OSStatus wxMacDataBrowserTableViewControl::GetColumnWidth(DataBrowserPropertyID propertyID, UInt16* width) const
286 {
287 return ::GetDataBrowserTableViewNamedColumnWidth(this->m_controlRef,propertyID,width);
288 }
289
290 OSStatus wxMacDataBrowserTableViewControl::GetDefaultColumnWidth( UInt16 *width ) const
291 {
292 return GetDataBrowserTableViewColumnWidth(this->m_controlRef, width );
293 }
294
295 OSStatus wxMacDataBrowserTableViewControl::GetDefaultRowHeight(UInt16* height) const
296 {
297 return ::GetDataBrowserTableViewRowHeight(this->m_controlRef,height);
298 }
299
300 OSStatus wxMacDataBrowserTableViewControl::GetHeaderButtonHeight(UInt16 *height)
301 {
302 return ::GetDataBrowserListViewHeaderBtnHeight(this->m_controlRef,height);
303 }
304
305 OSStatus wxMacDataBrowserTableViewControl::GetPartBounds(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserPropertyPart part, Rect* bounds)
306 {
307 return ::GetDataBrowserItemPartBounds(this->m_controlRef,item,propertyID,part,bounds);
308 } /* wxMacDataBrowserTableViewControl::GetPartBounds(DataBrowserItemID, DataBrowswerPropertyID, DataBrowserPropertyPart, Rect*) */
309
310 OSStatus wxMacDataBrowserTableViewControl::GetRowHeight(DataBrowserItemID item, UInt16* height) const
311 {
312 return ::GetDataBrowserTableViewItemRowHeight(this->m_controlRef,item,height);
313 } /* wxMacDataBrowserTableViewControl::GetRowHeight(DataBrowserItemID, UInt16*) const */
314
315 OSStatus wxMacDataBrowserTableViewControl::GetScrollPosition( UInt32 *top , UInt32 *left ) const
316 {
317 return GetDataBrowserScrollPosition(this->m_controlRef, top , left );
318 }
319
320 OSStatus wxMacDataBrowserTableViewControl::SetAttributes(OptionBits attributes)
321 {
322 return ::DataBrowserChangeAttributes(this->GetControlRef(),attributes,~attributes);
323 } /* wxMacDataBrowserTableViewControl::SetAttributes(OptionBits) */
324
325 OSStatus wxMacDataBrowserTableViewControl::SetColumnWidth(DataBrowserPropertyID propertyID, UInt16 width)
326 {
327 return ::SetDataBrowserTableViewNamedColumnWidth(this->m_controlRef,propertyID,width);
328 }
329
330 OSStatus wxMacDataBrowserTableViewControl::SetDefaultColumnWidth(UInt16 width)
331 {
332 return ::SetDataBrowserTableViewColumnWidth(this->m_controlRef,width);
333 }
334
335 OSStatus wxMacDataBrowserTableViewControl::SetDefaultRowHeight(UInt16 height)
336 {
337 return ::SetDataBrowserTableViewRowHeight(this->m_controlRef,height);
338 }
339
340 OSStatus wxMacDataBrowserTableViewControl::SetHasScrollBars(bool horiz, bool vert)
341 {
342 return ::SetDataBrowserHasScrollBars(this->m_controlRef,horiz,vert);
343 } /* wxMacDataBrowserTableViewControl::SetHasScrollBars(bool, bool) */
344
345 OSStatus wxMacDataBrowserTableViewControl::SetHeaderButtonHeight(UInt16 height)
346 {
347 return ::SetDataBrowserListViewHeaderBtnHeight(this->m_controlRef,height);
348 } /* wxMacDataBrowserTableViewControl::SetHeaderButtonHeight(UInt16) */
349
350 OSStatus wxMacDataBrowserTableViewControl::SetHiliteStyle(DataBrowserTableViewHiliteStyle hiliteStyle)
351 {
352 return ::SetDataBrowserTableViewHiliteStyle(this->m_controlRef,hiliteStyle);
353 } /*wxMacDataBrowserTableViewControl::SetHiliteStyle(DataBrowserTableViewHiliteStyle) */
354
355 OSStatus wxMacDataBrowserTableViewControl::SetIndent(float Indent)
356 {
357 return ::DataBrowserSetMetric(this->m_controlRef,kDataBrowserMetricDisclosureColumnPerDepthGap,true,Indent);
358 } /* wxMacDataBrowserTableViewControl::SetIndent(float* Indent) */
359
360 OSStatus wxMacDataBrowserTableViewControl::SetRowHeight(DataBrowserItemID item, UInt16 height)
361 {
362 return ::SetDataBrowserTableViewItemRowHeight(this->m_controlRef,item,height);
363 }
364
365 OSStatus wxMacDataBrowserTableViewControl::SetScrollPosition(UInt32 top, UInt32 left)
366 {
367 return ::SetDataBrowserScrollPosition(this->m_controlRef,top,left);
368 }
369
370 //
371 // column handling
372 //
373 OSStatus wxMacDataBrowserTableViewControl::GetColumnCount(UInt32* numColumns) const
374 {
375 return ::GetDataBrowserTableViewColumnCount(this->m_controlRef,numColumns);
376 }
377
378 OSStatus wxMacDataBrowserTableViewControl::GetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex* index) const
379 {
380 return ::GetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,index);
381 } /* wxMacDataBrowserTableViewControl::GetColumnIndex(DataBrowserPropertyID, DataBrowserTableViewColumnIndex*) const */
382
383 OSStatus wxMacDataBrowserTableViewControl::GetFreePropertyID(DataBrowserPropertyID* propertyID) const
384 {
385 for (*propertyID=kMinPropertyID; *propertyID<std::numeric_limits<DataBrowserPropertyID>::max(); ++(*propertyID))
386 if (this->IsUsedPropertyID(*propertyID) == errDataBrowserPropertyNotFound)
387 return noErr;
388 return errDataBrowserPropertyNotSupported;
389 } /* wxMacDataBrowserTableViewControl::GetFreePropertyID(DataBrowserPropertyID*) const */
390
391 OSStatus wxMacDataBrowserTableViewControl::GetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags *flags) const
392 {
393 return ::GetDataBrowserPropertyFlags(this->m_controlRef,propertyID,flags);
394 }
395
396 OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserItemDataRef itemData, DataBrowserPropertyID* propertyID)
397 {
398 return ::GetDataBrowserItemDataProperty(itemData,propertyID);
399 } /* wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserItemDataRef, DataBrowserPropertyID*) */
400
401 OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserTableViewColumnIndex index, DataBrowserTableViewColumnID* propertyID)
402 {
403 return ::GetDataBrowserTableViewColumnProperty(this->m_controlRef,index,propertyID);
404 } /* wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserTableViewColumnIndex, DataBrowserTableViewColumnID*) */
405
406 OSStatus wxMacDataBrowserTableViewControl::IsUsedPropertyID(DataBrowserPropertyID propertyID) const
407 {
408 // 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
409 // 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
410 // the column position for the property id:
411 DataBrowserTableViewColumnIndex index;
412
413 return ::GetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,&index);
414 } /* wxMacDataBrowserTableViewControl::IsUsedPropertyId(DataBrowserPropertyID) const */
415
416 OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByProperty(DataBrowserTableViewColumnID propertyID)
417 {
418 return ::RemoveDataBrowserTableViewColumn(this->m_controlRef,propertyID);
419 } /* wxMacDataBrowserTableViewControl::RemoveColumnByProperty(DataBrowserTableViewColumnID) */
420
421 OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByIndex(DataBrowserTableViewColumnIndex index)
422 {
423 DataBrowserTableViewColumnID propertyID;
424
425
426 this->GetPropertyID(index,&propertyID);
427 return ::RemoveDataBrowserTableViewColumn(this->m_controlRef,propertyID);
428 } /* wxMacDataBrowserTableViewControl::RemoveColumnByIndex(DataBrowserTableViewColumnIndex) */
429
430 OSStatus wxMacDataBrowserTableViewControl::SetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex index)
431 {
432 return ::SetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,index);
433 } /* wxMacDataBrowserTableViewControl::SetColumnIndex(DataBrowserPropertyID, DataBrowserTableViewColumnIndex) */
434
435 OSStatus wxMacDataBrowserTableViewControl::SetDisclosureColumn(DataBrowserPropertyID propertyID, Boolean expandableRows)
436 {
437 return ::SetDataBrowserListViewDisclosureColumn(this->m_controlRef,propertyID,expandableRows);
438 }
439
440 OSStatus wxMacDataBrowserTableViewControl::SetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags flags)
441 {
442 return ::SetDataBrowserPropertyFlags(this->m_controlRef,propertyID,flags);
443 } /* wxMacDataBrowserTableViewControl::SetPropertyFlags(DataBrowserPropertyID, DataBrowserPropertyFlags) */
444
445 //
446 // item handling
447 //
448 OSStatus wxMacDataBrowserTableViewControl::AddItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
449 {
450 return ::AddDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty);
451 } /* wxMacDataBrowserTableViewControl::AddItems(DataBrowserItemID, UInt32, DataBrowserItemID const*, DataBrowserPropertyID) */
452
453 OSStatus wxMacDataBrowserTableViewControl::GetFreeItemID(DataBrowserItemID* id) const
454 {
455 ItemCount NoOfItems;
456
457 OSStatus status;
458
459
460 status = this->GetItemCount(&NoOfItems);
461 wxCHECK_MSG(status == noErr,status,_("Could not retrieve number of items"));
462 if (NoOfItems == 0)
463 {
464 *id = 1;
465 return noErr;
466 } /* if */
467 else
468 {
469 // 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
470 // as the number of items; therefore, start from the number of items to look for a new ID:
471 for (*id=NoOfItems; *id<std::numeric_limits<DataBrowserItemID>::max(); ++(*id))
472 if (this->IsUsedItemID(*id) == errDataBrowserItemNotFound)
473 return noErr;
474 // as the first approach was not successful, try from the beginning:
475 for (*id=0; *id<NoOfItems; ++(*id))
476 if (this->IsUsedItemID(*id) == errDataBrowserItemNotFound)
477 return noErr;
478 // sorry, data browser is full:
479 return errDataBrowserItemNotAdded;
480 } /* if */
481 } /* wxMacDataBrowserTableViewControl::GetFreeItemID(DataBrowserItemID*) const */
482
483 OSStatus wxMacDataBrowserTableViewControl::GetItemCount(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, ItemCount* numItems) const
484 {
485 return GetDataBrowserItemCount(this->m_controlRef,container,recurse,state,numItems);
486 } /* wxMacDataBrowserTableViewControl::GetItemCount(DataBrowserItemID, Boolean, DataBrowserItemState, ItemCount*) const */
487
488 OSStatus wxMacDataBrowserTableViewControl::GetItemID( DataBrowserTableViewRowIndex row, DataBrowserItemID * item ) const
489 {
490 return GetDataBrowserTableViewItemID(this->m_controlRef,row,item);
491 }
492
493 OSStatus wxMacDataBrowserTableViewControl::GetItems(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, Handle items) const
494 {
495 return GetDataBrowserItems(this->m_controlRef,container,recurse,state,items);
496 } /* wxMacDataBrowserTableViewControl::GetItems(DataBrowserItemID, Boolean, DataBrowserItemState, Handle) const */
497
498 OSStatus wxMacDataBrowserTableViewControl::GetItemRow(DataBrowserItemID item, DataBrowserTableViewRowIndex* row) const
499 {
500 return GetDataBrowserTableViewItemRow(this->m_controlRef,item,row);
501 }
502
503 OSStatus wxMacDataBrowserTableViewControl::IsUsedItemID(DataBrowserItemID itemID) const
504 {
505 // 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
506 // 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
507 // the column position for the property id:
508 DataBrowserTableViewColumnIndex index;
509
510 return ::GetDataBrowserTableViewItemRow(this->m_controlRef,itemID,&index);
511 } /* wxMacDataBrowserTableViewControl::IsUsedItemID(DataBrowserItemID) const */
512
513 OSStatus wxMacDataBrowserTableViewControl::RemoveItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
514 {
515 return ::RemoveDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty);
516 }
517
518 OSStatus wxMacDataBrowserTableViewControl::RevealItem(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserRevealOptions options) const
519 {
520 return ::RevealDataBrowserItem(this->m_controlRef,item,propertyID,options);
521 } /* wxMacDataBrowserTableViewControl::RevealItem(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserRevealOptions options) const */
522
523 OSStatus wxMacDataBrowserTableViewControl::UpdateItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty,
524 DataBrowserPropertyID propertyID) const
525 {
526 return UpdateDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty,propertyID);
527 }
528
529 //
530 // item selection
531 //
532 size_t wxMacDataBrowserTableViewControl::GetSelectedItemIDs(wxArrayDataBrowserItemID& itemIDs) const
533 {
534 DataBrowserItemID* itemIDPtr;
535 Handle handle(::NewHandle(0));
536
537 size_t NoOfItems;
538
539
540 wxCHECK_MSG(this->GetItems(kDataBrowserNoItem,true,kDataBrowserItemIsSelected,handle) == noErr,0,_("Could not get selected items."));
541 NoOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
542 itemIDs.Empty();
543 itemIDs.Alloc(NoOfItems);
544 HLock(handle);
545 itemIDPtr = (DataBrowserItemID*) (*handle);
546 for (size_t i=0; i<NoOfItems; ++i)
547 {
548 itemIDs.Add(*itemIDPtr);
549 ++itemIDPtr;
550 } /* for */
551 HUnlock(handle);
552 DisposeHandle(handle);
553 return NoOfItems;
554 } /* wxMacDataBrowserTableViewControl::GetSelectedItemIDs(wxArrayDataBrowserItemID&) const*/
555
556 OSStatus wxMacDataBrowserTableViewControl::GetSelectionAnchor(DataBrowserItemID* first, DataBrowserItemID* last) const
557 {
558 return ::GetDataBrowserSelectionAnchor(this->m_controlRef,first,last);
559 } /* wxMacDataBrowserTableViewControl::GetSelectionAnchor(DataBrowserItemID*, DataBrowserItemID*) const */
560
561 OSStatus wxMacDataBrowserTableViewControl::GetSelectionFlags(DataBrowserSelectionFlags* flags) const
562 {
563 return ::GetDataBrowserSelectionFlags(this->m_controlRef,flags);
564 } /* wxMacDataBrowserTableViewControl::GetSelectionFlags(DataBrowserSelectionFlags*) const */
565
566 bool wxMacDataBrowserTableViewControl::IsItemSelected(DataBrowserItemID item) const
567 {
568 return ::IsDataBrowserItemSelected(this->m_controlRef,item);
569 } /* wxMacDataBrowserTableViewControl::IsItemSelected(DataBrowserItemID) const */
570
571 OSStatus wxMacDataBrowserTableViewControl::SetSelectionFlags(DataBrowserSelectionFlags flags)
572 {
573 return ::SetDataBrowserSelectionFlags(this->m_controlRef,flags);
574 } /* wxMacDataBrowserTableViewControl::SetSelectionFlags(DataBrowserSelectionFlags) */
575
576 OSStatus wxMacDataBrowserTableViewControl::SetSelectedItems(UInt32 numItems, DataBrowserItemID const* items, DataBrowserSetOption operation)
577 {
578 return ::SetDataBrowserSelectedItems(this->m_controlRef, numItems, items, operation );
579 } /* wxMacDataBrowserTableViewControl::SetSelectedItems(UInt32, DataBrowserItemID const*, DataBrowserSetOption) */
580
581 OSStatus wxMacDataBrowserTableViewControl::GetSortOrder(DataBrowserSortOrder* order) const
582 {
583 return ::GetDataBrowserSortOrder(this->m_controlRef,order);
584 }
585
586 OSStatus wxMacDataBrowserTableViewControl::GetSortProperty(DataBrowserPropertyID* propertyID) const
587 {
588 return ::GetDataBrowserSortProperty(this->m_controlRef,propertyID);
589 }
590
591 OSStatus wxMacDataBrowserTableViewControl::Resort(DataBrowserItemID container, Boolean sortChildren)
592 {
593 return ::SortDataBrowserContainer(this->m_controlRef,container,sortChildren);
594 } /* wxMacDataBrowserTableViewControl::Resort(DataBrowserItemID, Boolean) */
595
596 OSStatus wxMacDataBrowserTableViewControl::SetSortOrder(DataBrowserSortOrder order)
597 {
598 return ::SetDataBrowserSortOrder(this->m_controlRef,order);
599 }
600
601 OSStatus wxMacDataBrowserTableViewControl::SetSortProperty(DataBrowserPropertyID propertyID)
602 {
603 return ::SetDataBrowserSortProperty(this->m_controlRef,propertyID);
604 }
605
606 //
607 // container handling
608 //
609 OSStatus wxMacDataBrowserTableViewControl::CloseContainer(DataBrowserItemID containerID)
610 {
611 return ::CloseDataBrowserContainer(this->m_controlRef,containerID);
612 } /* wxMacDataBrowserTableViewControl::CloseContainer(DataBrowserItemID) */
613
614 OSStatus wxMacDataBrowserTableViewControl::OpenContainer(DataBrowserItemID containerID)
615 {
616 return ::OpenDataBrowserContainer(this->m_controlRef,containerID);
617 } /* wxMacDataBrowserTableViewControl::OpenContainer(DataBrowserItemID) */
618
619 IMPLEMENT_ABSTRACT_CLASS(wxMacDataBrowserTableViewControl,wxMacControl)
620
621 // ============================================================================
622 // wxMacDataBrowserListViewControl
623 // ============================================================================
624 #pragma mark -
625 //
626 // column handling
627 //
628 OSStatus wxMacDataBrowserListViewControl::AddColumn(DataBrowserListViewColumnDesc *columnDesc, DataBrowserTableViewColumnIndex position)
629 {
630 return AddDataBrowserListViewColumn(this->m_controlRef,columnDesc,position);
631 } /* wxMacDataBrowserListViewControl::AddColumn(DataBrowserListViewColumnDesc*, DataBrowserTableViewColumnIndex) */
632
633 // ============================================================================
634 // wxMacDataViewDataBrowserListViewControl
635 // ============================================================================
636 #pragma mark -
637 //
638 // constructors / destructor
639 //
640 wxMacDataViewDataBrowserListViewControl::wxMacDataViewDataBrowserListViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
641 :wxMacDataBrowserListViewControl(peer,pos,size,style)
642 {
643 } /* wxMacDataViewDataBrowserListViewControl::wxMacDataViewDataBrowserListViewControl(wxWindow* , const wxPoint&, const wxSize&, long) */
644
645 //
646 // callback functions (inherited from wxMacDataBrowserTableViewControl)
647 //
648 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
649 {
650 DataBrowserSortOrder sortOrder;
651
652 DataBrowserTableViewColumnIndex modelColumnIndex;
653
654 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
655
656
657 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
658 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
659 if (sortProperty >= kMinPropertyID)
660 {
661 // variable definition and initialization:
662 wxDataViewColumn* ColumnPtr(dataViewCtrlPtr->GetColumnPtr(sortProperty));
663
664 wxCHECK_MSG(ColumnPtr != NULL,false,_("Could not determine column index."));
665 modelColumnIndex = ColumnPtr->GetModelColumn();
666 } /* if */
667 else
668 modelColumnIndex = 0;
669 this->GetSortOrder(&sortOrder);
670 return static_cast<Boolean>(dataViewCtrlPtr->GetModel()->Compare(wxDataViewItem(reinterpret_cast<void*>(itemOneID)),wxDataViewItem(reinterpret_cast<void*>(itemTwoID)),
671 modelColumnIndex,sortOrder != kDataBrowserOrderDecreasing) < 0);
672 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID) */
673
674 void wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* WXUNUSED(selection))
675 // In this method we do not supply a contextual menu handler at all but only send a wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU.
676 {
677 wxArrayDataBrowserItemID itemIDs;
678
679 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
680
681
682 wxCHECK_RET(dataViewCtrlPtr != NULL,_("wxWidget control pointer is not a data view pointer"));
683 // initialize parameters so that no context menu will be displayed automatically by the native data browser:
684 *menu = NULL;
685 *helpType = kCMHelpItemNoHelp;
686 *helpItemString = NULL;
687 // create information for a context menu event:
688 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU,dataViewCtrlPtr->GetId());
689
690 dataViewEvent.SetEventObject(dataViewCtrlPtr);
691 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
692 // get the item information;
693 // 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:
694 if (this->GetSelectedItemIDs(itemIDs) > 0)
695 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemIDs[0])));
696 // finally send the equivalent wxWidget event:
697 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
698 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef*, UInt32*, CFStringRef*, AEDesc*) */
699
700 OSStatus wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
701 {
702 if (getValue)
703 {
704 // variable definitions:
705 wxDataViewCtrl* dataViewCtrlPtr;
706
707 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
708 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
709 if (dataViewCtrlPtr->IsDeleting())
710 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
711 else
712 {
713 // variable definitions:
714 OSStatus errorStatus;
715 wxDataViewColumn* dataViewColumnPtr;
716
717 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
718 dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
719 wxCHECK_MSG((dataViewColumnPtr != NULL) && (dataViewColumnPtr->GetRenderer() != NULL),errDataBrowserNotConfigured,_("There is no column or renderer for the specified column index."));
720
721 wxDataViewItem dvItem(reinterpret_cast<void*>(itemID));
722 unsigned int col = dataViewColumnPtr->GetModelColumn();
723
724 switch (dataViewColumnPtr->GetRenderer()->GetPropertyType())
725 {
726 case kDataBrowserCheckboxType:
727 {
728 // variable definition:
729 ThemeButtonValue buttonValue;
730
731 errorStatus = ::GetDataBrowserItemDataButtonValue(itemData,&buttonValue);
732 if (errorStatus == noErr)
733 {
734 if (buttonValue == kThemeButtonOn)
735 {
736 // variable definition and initialization:
737 wxVariant modifiedData(true);
738
739 if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
740 dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
741 return noErr;
742 else
743 return errDataBrowserInvalidPropertyData;
744 } /* if */
745 else if (buttonValue == kThemeButtonOff)
746 {
747 // variable definition and initialization:
748 wxVariant modifiedData(false);
749
750 if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
751 dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
752 return noErr;
753 else
754 return errDataBrowserInvalidPropertyData;
755 } /* if */
756 else
757 return errDataBrowserInvalidPropertyData;
758 } /* if */
759 else
760 return errorStatus;
761 } /* block */
762 case kDataBrowserTextType:
763 {
764 // variable definitions:
765 CFStringRef stringReference;
766
767 errorStatus = ::GetDataBrowserItemDataText(itemData,&stringReference);
768 if (errorStatus == noErr)
769 {
770 // variable definitions and initializations:
771 #if wxCHECK_VERSION(2,9,0)
772 wxCFStringRef modifiedString(stringReference);
773 #else
774 wxMacCFStringHolder modifiedString(stringReference);
775 #endif
776 wxVariant modifiedData(modifiedString.AsString());
777
778 if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
779 dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
780 return noErr;
781 else
782 return errDataBrowserInvalidPropertyData;
783 } /* if */
784 else
785 return errorStatus;
786 } /* block */
787 default:
788 return errDataBrowserPropertyNotSupported;
789 } /* switch */
790 } /* if */
791 } /* if */
792 else
793 {
794 if (propertyID >= kMinPropertyID) // in case data columns set the data
795 {
796 // variable definitions:
797 wxVariant variant;
798 wxDataViewColumn* dataViewColumnPtr;
799 wxDataViewCtrl* dataViewCtrlPtr;
800
801 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
802 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
803 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
804 dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
805 wxCHECK_MSG(dataViewColumnPtr != NULL,errDataBrowserNotConfigured,_("No column for the specified column position existing."));
806 wxCHECK_MSG(dataViewColumnPtr->GetRenderer() != NULL,errDataBrowserNotConfigured,_("No renderer specified for column."));
807 dataViewCtrlPtr->GetModel()->GetValue(variant,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
808 if (!(variant.IsNull()))
809 {
810 dataViewColumnPtr->GetRenderer()->SetDataReference(itemData);
811 dataViewColumnPtr->GetRenderer()->SetValue(variant);
812 wxCHECK_MSG(dataViewColumnPtr->GetRenderer()->Render(),errDataBrowserNotConfigured,_("Rendering failed."));
813 } /* if */
814 return noErr;
815 } /* if */
816 else // react on special system requests
817 {
818 switch (propertyID)
819 {
820 case kDataBrowserContainerIsClosableProperty:
821 {
822 // variable definitions:
823 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
824
825 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
826 // initialize wxWidget event:
827 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,dataViewCtrlPtr->GetId()); // variable definition
828
829 dataViewEvent.SetEventObject(dataViewCtrlPtr);
830 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
831 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
832 // finally send the equivalent wxWidget event:
833 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
834 // opening the container is allowed if not vetoed:
835 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
836 } /* block */
837 case kDataBrowserContainerIsOpenableProperty:
838 {
839 // variable definitions:
840 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
841
842 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
843 // initialize wxWidget event:
844 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,dataViewCtrlPtr->GetId()); // variable definition
845
846 dataViewEvent.SetEventObject(dataViewCtrlPtr);
847 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
848 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
849 // finally send the equivalent wxWidget event:
850 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
851 // opening the container is allowed if not vetoed:
852 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
853 } /* block */
854 case kDataBrowserItemIsContainerProperty:
855 {
856 // variable definition:
857 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
858
859 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
860 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
861 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewCtrlPtr->GetModel()->IsContainer(wxDataViewItem(reinterpret_cast<void*>(itemID))));
862 } /* block */
863 case kDataBrowserItemIsEditableProperty:
864 return ::SetDataBrowserItemDataBooleanValue(itemData,true);
865 } /* switch */
866 } /* if */
867 } /* if */
868 return errDataBrowserPropertyNotSupported;
869 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean) */
870
871 void wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
872 {
873 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer()));
874
875
876 // 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:
877 if (dataViewCtrlPtr != NULL)
878 switch (message)
879 {
880 case kDataBrowserContainerClosed:
881 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
882 {
883 // initialize wxWidget event:
884 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,dataViewCtrlPtr->GetId()); // variable definition
885
886 dataViewEvent.SetEventObject(dataViewCtrlPtr);
887 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
888 // finally send the equivalent wxWidget event:
889 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
890 } /* block */
891 break;
892 case kDataBrowserContainerOpened:
893 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
894 {
895 // initialize wxWidget event:
896 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,dataViewCtrlPtr->GetId()); // variable definition
897
898 dataViewEvent.SetEventObject(dataViewCtrlPtr);
899 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
900 // finally send the equivalent wxWidget event:
901 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
902 // add children to the expanded container:
903 dataViewCtrlPtr->AddChildrenLevel(wxDataViewItem(reinterpret_cast<void*>(itemID)));
904 } /* block */
905 break;
906 case kDataBrowserEditStarted:
907 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
908 {
909 // initialize wxWidget event:
910 DataBrowserPropertyID propertyID;
911 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition
912
913 dataViewEvent.SetEventObject(dataViewCtrlPtr);
914 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
915 if (this->GetPropertyID(itemData,&propertyID) == noErr)
916 {
917 // variable definition and initialization:
918 DataBrowserTableViewColumnIndex columnIndex;
919
920 wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
921 dataViewEvent.SetColumn(columnIndex);
922 dataViewEvent.SetDataViewColumn(dataViewCtrlPtr->GetColumnPtr(propertyID));
923 } /* if */
924 // finally send the equivalent wxWidget event:
925 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
926 } /* block */
927 break;
928 case kDataBrowserEditStopped:
929 {
930 // initialize wxWidget event:
931 DataBrowserPropertyID propertyID;
932 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition
933
934 dataViewEvent.SetEventObject(dataViewCtrlPtr);
935 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
936 if (this->GetPropertyID(itemData,&propertyID) == noErr)
937 {
938 // variable definition and initialization:
939 DataBrowserTableViewColumnIndex columnIndex;
940
941 wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
942 dataViewEvent.SetColumn(columnIndex);
943 dataViewEvent.SetDataViewColumn(dataViewCtrlPtr->GetColumnPtr(propertyID));
944 } /* if */
945 // finally send the equivalent wxWidget event:
946 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
947 } /* block */
948 break;
949 case kDataBrowserItemAdded:
950 dataViewCtrlPtr->FinishCustomItemEditing();
951 break;
952 case kDataBrowserItemDeselected:
953 dataViewCtrlPtr->FinishCustomItemEditing();
954 break;
955 case kDataBrowserItemDoubleClicked:
956 {
957 // initialize wxWidget event:
958 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,dataViewCtrlPtr->GetId()); // variable definition
959
960 dataViewEvent.SetEventObject(dataViewCtrlPtr);
961 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
962 // finally send the equivalent wxWidget event:
963 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
964 } /* block */
965 break;
966 case kDataBrowserItemRemoved:
967 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
968 break;
969 case kDataBrowserItemSelected:
970 break; // not implemented by wxWidgets; see kDataBrowserSelectionSetChanged
971 case kDataBrowserSelectionSetChanged:
972 {
973 // initialize wxWidget event:
974 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED,dataViewCtrlPtr->GetId()); // variable definition
975
976 dataViewEvent.SetEventObject(dataViewCtrlPtr);
977 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
978 // finally send the equivalent wxWidget event:
979 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
980 } /* block */
981 break;
982 case kDataBrowserTargetChanged: // no idea if this notification is ever sent
983 break;
984 case kDataBrowserUserStateChanged:
985 {
986 // finish custom item editing if necessary:
987 dataViewCtrlPtr->FinishCustomItemEditing();
988 // update column widths:
989 for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); ++i)
990 {
991 // constant definition for abbreviational purposes:
992 wxDataViewColumn* const columnPtr = dataViewCtrlPtr->GetColumn(i);
993 // variable definition:
994 UInt16 columnWidth;
995
996 wxCHECK_RET(this->GetColumnWidth(columnPtr->GetPropertyID(),&columnWidth) == noErr,_("Column width could not be determined"));
997 columnPtr->SetWidthVariable(columnWidth);
998 } /* for */
999 // update sorting orders:
1000 DataBrowserPropertyID propertyID; // variable definition
1001
1002 if ((this->GetSortProperty(&propertyID) == noErr) && (propertyID >= kMinPropertyID))
1003 {
1004 DataBrowserSortOrder sortOrder;
1005 DataBrowserTableViewColumnIndex columnIndex;
1006
1007 if ((this->GetSortOrder(&sortOrder) == noErr) && (this->GetColumnIndex(propertyID,&columnIndex) == noErr))
1008 {
1009 // variable definition and initialization:
1010 wxDataViewColumn* columnPtr;
1011 columnPtr = dataViewCtrlPtr->GetColumn(columnIndex);
1012 // check if the sort order has changed:
1013 if ( columnPtr->IsSortOrderAscending() && (sortOrder == kDataBrowserOrderDecreasing) ||
1014 !(columnPtr->IsSortOrderAscending()) && (sortOrder == kDataBrowserOrderIncreasing))
1015 {
1016 columnPtr->SetSortOrder(!(columnPtr->IsSortOrderAscending()));
1017 // initialize wxWidget event:
1018 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED,dataViewCtrlPtr->GetId()); // variable defintion
1019
1020 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1021 dataViewEvent.SetColumn(columnIndex);
1022 dataViewEvent.SetDataViewColumn(columnPtr);
1023 // finally send the equivalent wxWidget event:
1024 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1025 } /* if */
1026 } /* if */
1027 } /* if */
1028 } /* block */
1029 break;
1030 } /* switch */
1031 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID, DataBrowserItemNotification, DataBrowserItemDataRef) */
1032
1033 void wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemState state, Rect const* rectangle, SInt16 bitDepth, Boolean colorDevice)
1034 {
1035 DataBrowserTableViewColumnIndex columnIndex;
1036
1037 wxDataViewColumn* dataViewColumnPtr;
1038
1039 wxDataViewCtrl* dataViewCtrlPtr;
1040
1041 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1042
1043 wxVariant dataToRender;
1044
1045 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1046 wxCHECK_RET(dataViewCtrlPtr != NULL, _("Pointer to data view control not set correctly."));
1047 wxCHECK_RET(dataViewCtrlPtr->GetModel() != NULL,_("Pointer to model not set correctly."));
1048 wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex) == noErr,_("Could not determine column index."));
1049 dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
1050 wxCHECK_RET(dataViewColumnPtr != NULL,_("No column for the specified column index existing."));
1051 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1052 wxCHECK_RET(dataViewCustomRendererPtr != NULL,_("No renderer or invalid renderer type specified for custom data column."));
1053 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
1054 dataViewCustomRendererPtr->SetValue(dataToRender);
1055
1056 wxDataViewItem dataitem( reinterpret_cast<void*>(itemID) );
1057 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,dataitem,dataViewColumnPtr->GetModelColumn());
1058 dataViewCustomRendererPtr->SetValue(dataToRender);
1059
1060 // try to determine the content's size (drawable part):
1061 Rect content;
1062 HIShapeRef rgn = NULL;
1063
1064 UInt16 headerHeight;
1065
1066 if ( HIViewCopyShape(m_controlRef, kHIViewContentMetaPart, &rgn) == noErr)
1067 {
1068 CGRect cgrect;
1069 HIShapeGetBounds(rgn, &cgrect);
1070 content = (Rect){ cgrect.origin.y, cgrect.origin.x, cgrect.origin.y+cgrect.size.height, cgrect.origin.x+cgrect.size.width };
1071 CFRelease(rgn);
1072 }
1073 else
1074 GetControlBounds(m_controlRef, &content);
1075 // space for the header
1076 this->GetHeaderButtonHeight(&headerHeight);
1077 content.top += headerHeight;
1078 // extra space for the frame (todo: do not how to determine the space automatically from the control)
1079 content.top += 5;
1080 content.left += 5;
1081 content.right -= 3;
1082 content.bottom -= 3;
1083 // extra space for the scrollbars:
1084 content.bottom -= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
1085 content.right -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1086
1087 wxDC *dc = dataViewCustomRendererPtr->GetDC();
1088
1089 wxRect cellrect( static_cast<int>(rectangle->left),
1090 static_cast<int>(rectangle->top),
1091 static_cast<int>(1+rectangle->right-rectangle->left),
1092 static_cast<int>(rectangle->bottom-rectangle->top) );
1093
1094 bool is_active = IsControlActive( this->m_controlRef );
1095 if (state == kDataBrowserItemIsSelected)
1096 {
1097
1098 wxColour col( wxMacCreateCGColorFromHITheme( (is_active) ?
1099 kThemeBrushAlternatePrimaryHighlightColor
1100 : kThemeBrushSecondaryHighlightColor ) );
1101
1102 wxRect rect = cellrect;
1103 Rect itemrect;
1104 GetDataBrowserItemPartBounds( this->m_controlRef, itemID, propertyID,
1105 kDataBrowserPropertyEnclosingPart, &itemrect );
1106 rect.x = itemrect.left;
1107 rect.width = itemrect.right-itemrect.left+1;
1108
1109 wxBrush selBrush( col );
1110 wxPen oldpen( dc->GetPen() );
1111 wxBrush oldbrush( dc->GetBrush() );
1112 dc->SetPen( *wxTRANSPARENT_PEN );
1113 dc->SetBrush( selBrush );
1114 dc->DrawRectangle(rect);
1115 dc->SetBrush( oldbrush );
1116 dc->SetPen( oldpen );
1117 }
1118
1119 wxDataViewModel *model = dataViewCtrlPtr->GetModel();
1120 if ((columnIndex == 0) || !model->IsContainer(dataitem) || model->HasContainerColumns(dataitem))
1121 {
1122 // make sure that 'Render' can draw only in the allowed area:
1123 dc->SetClippingRegion(content.left,content.top,content.right-content.left+1,content.bottom-content.top+1);
1124 (void) (dataViewCustomRendererPtr->Render( cellrect, dc,
1125 ((state == kDataBrowserItemIsSelected) ? wxDATAVIEW_CELL_SELECTED : 0)));
1126 dc->DestroyClippingRegion(); // probably not necessary
1127 }
1128
1129 dataViewCustomRendererPtr->SetDC(NULL);
1130 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemState, Rect const*, SInt16, Boolean) */
1131
1132 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
1133 {
1134 return false;
1135 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID, DataBrowserPropertyID, CFStringRef, Rect*, Boolean*) */
1136
1137 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID WXUNUSED(itemID), DataBrowserPropertyID WXUNUSED(property), Rect const* WXUNUSED(theRect), Rect const* WXUNUSED(mouseRect))
1138 {
1139 return true;
1140 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Rect const*) */
1141
1142 DataBrowserTrackingResult wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point WXUNUSED(startPt), EventModifiers WXUNUSED(modifiers))
1143 {
1144 wxDataViewColumn* dataViewColumnPtr;
1145
1146 wxDataViewCtrl* dataViewCtrlPtr;
1147
1148 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1149
1150 wxDataViewItem dataViewCustomRendererItem;
1151
1152
1153 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1154 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1155 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1156 dataViewCustomRendererItem = reinterpret_cast<void*>(itemID);
1157 wxCHECK_MSG(dataViewCustomRendererItem.IsOk(),kDataBrowserNothingHit,_("Invalid data view item"));
1158 dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
1159 wxCHECK_MSG(dataViewColumnPtr != NULL,kDataBrowserNothingHit,_("No column existing."));
1160 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1161 wxCHECK_MSG(dataViewCustomRendererPtr != NULL,kDataBrowserNothingHit,_("No renderer or invalid renderer type specified for custom data column."));
1162 // 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):
1163 if (dataViewCtrlPtr->GetCustomRendererItem() == dataViewCustomRendererItem)
1164 return kDataBrowserContentHit;
1165 // an(other) item is going to be edited and therefore the current editing - if existing - has to be finished:
1166 if (dataViewCtrlPtr->GetCustomRendererPtr() != NULL)
1167 {
1168 dataViewCtrlPtr->GetCustomRendererPtr()->FinishEditing();
1169 dataViewCtrlPtr->SetCustomRendererItem(wxDataViewItem());
1170 dataViewCtrlPtr->SetCustomRendererPtr (NULL);
1171 }
1172 // check if renderer has got a valid editor control for editing; if this is the case start editing of the new item:
1173 if (dataViewCustomRendererPtr->HasEditorCtrl())
1174 {
1175 // variable definition:
1176 wxRect wxRectangle;
1177
1178 ::wxMacNativeToRect(theRect,&wxRectangle);
1179 dataViewCustomRendererPtr->StartEditing(dataViewCustomRendererItem,wxRectangle);
1180 dataViewCtrlPtr->SetCustomRendererItem(dataViewCustomRendererItem);
1181 dataViewCtrlPtr->SetCustomRendererPtr (dataViewCustomRendererPtr);
1182 }
1183 return kDataBrowserContentHit;
1184 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Point, EventModifiers) */
1185
1186 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference dragRef, DataBrowserItemID itemID)
1187 {
1188 UInt16 noOfDraggedItems;
1189
1190 wxDataViewCtrl* dataViewCtrlPtr;
1191
1192
1193 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1194 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1195 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1196
1197 // send a drag possible event for each available item and proceed with it unless the event is vetoed:
1198 ::CountDragItems(dragRef,&noOfDraggedItems);
1199 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1200 {
1201 // collect native information:
1202 ItemReference itemRef;
1203 wxDataObjectComposite* dataObjects;
1204 wxMemoryBuffer buffer;
1205
1206 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1207 dataObjects = this->GetDnDDataObjects(dragRef,itemRef);
1208 // create wxWidget's event:
1209 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE,dataViewCtrlPtr->GetId());
1210
1211 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1212 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1213 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1214 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1215 dataViewEvent.SetDataObject(dataObjects);
1216 dataViewEvent.SetDataFormat(this->GetDnDDataFormat(dataObjects));
1217 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1218 {
1219 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1220 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1221 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1222 dataViewEvent.SetDataBuffer(buffer.GetData());
1223 }
1224
1225 // send event:
1226 if (!(dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed()))
1227 return false;
1228 }
1229 return true;
1230 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference, DataBrowserItemID) */
1231
1232 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
1233 {
1234 wxDataViewCtrl* dataViewCtrlPtr;
1235
1236 wxDataViewItem dataViewItem;
1237
1238
1239 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1240 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1241 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1242 dataViewItem = reinterpret_cast<void*>(itemID);
1243 wxCHECK_MSG(dataViewItem.IsOk(),false,_("Invalid data view item"));
1244
1245 // send a begin drag event and proceed with dragging unless the event is vetoed:
1246 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG,dataViewCtrlPtr->GetId());
1247
1248 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1249 dataViewEvent.SetItem(dataViewItem);
1250 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1251 // 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
1252 // the object a wxDataObjectComposite object is used;
1253 // currently, the composite object only contains a TAB concatenated string of all data:
1254 wxDataObjectComposite* dataObject(new wxDataObjectComposite());
1255 wxString dataString; // contains the TAB concatenated data
1256
1257 for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); i++)
1258 {
1259 // variable definition:
1260 wxVariant dataValue;
1261
1262 dataViewCtrlPtr->GetModel()->GetValue(dataValue,dataViewItem,dataViewCtrlPtr->GetColumn(i)->GetModelColumn());
1263 if (i > 0)
1264 dataString << wxT('\t');
1265 dataString << dataValue.MakeString();
1266 }
1267 dataObject->Add(new wxTextDataObject(dataString));
1268 dataViewEvent.SetDataObject(dataObject);
1269 // check if event has not been vetoed:
1270 if (dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed())
1271 {
1272 // for the internal drag & drop functions create two flavors:
1273 // - the data browser's item id;
1274 // - the data contained the dataview event object (if available).
1275 // Definition: a flavor is the type dependent representation of identical data.
1276 // Example: a number can be represented by its value and by its value converted to a string. In this case the flavor
1277 // of the number's internal representation is typeSInt32 while its string representation has got the flavor 'TEXT'.
1278 // Item id is one of the flavors:
1279 wxCHECK_MSG(::AddDragItemFlavor(dragRef,*itemRef,typeUInt32,&itemID,sizeof(itemID),0) == noErr,false,_("Unable to handle native drag&drop data"));
1280 // if the dataview event object contains data it is used for additional flavors; all natively known flavors are supported:
1281 if (dataViewEvent.GetDataObject() != NULL)
1282 {
1283 // constant definition for abbreviational purposes:
1284 size_t const noOfFormats = dataViewEvent.GetDataObject()->GetFormatCount();
1285
1286 if (noOfFormats > 0)
1287 {
1288 // variable definition:
1289 wxDataFormat* dataFormats;
1290
1291 dataFormats = new wxDataFormat[noOfFormats];
1292 dataViewEvent.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get);
1293 for (size_t i=0; i<noOfFormats; ++i)
1294 switch (dataFormats[i].GetType())
1295 {
1296 case wxDF_INVALID:
1297 wxFAIL_MSG(_("Data object has invalid data format"));
1298 break;
1299 case wxDF_TEXT:
1300 {
1301 // constant definition for abbreviational purposes:
1302 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1303 // variable definition and initialization:
1304 wxMemoryBuffer dataObject(dataSize);
1305
1306 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1307 dataObject.UngetWriteBuf(dataSize);
1308 if (::AddDragItemFlavor(dragRef,*itemRef,'TEXT',dataObject.GetData(),dataSize,0) != noErr)
1309 wxFAIL_MSG(_("Adding flavor TEXT failed"));
1310 } /* block */
1311 break;
1312 case wxDF_UNICODETEXT:
1313 {
1314 // constant definition for abbreviational purposes:
1315 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1316 // as there is no direct access to the data copy it to a memory buffer:
1317 wxMemoryBuffer dataObject(dataSize);
1318
1319 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1320 dataObject.UngetWriteBuf(dataSize);
1321 // if the data is stored in unicode format the internal representation is utf-8 (not mentioned in the documentation but in the source code);
1322 // DnD uses fixed utf-16 representation -> use the OSX functions for a conversion:
1323 CFDataRef osxData (::CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,reinterpret_cast<UInt8*>(dataObject.GetData()),dataSize,kCFAllocatorNull));
1324 CFStringRef osxString(::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,osxData,kCFStringEncodingUTF8));
1325
1326 // the osxString contains now the data and therefore the previously occupied memory can be released and re-used:
1327 ::CFRelease(osxData);
1328 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF16,32);
1329 if (::AddDragItemFlavor(dragRef,*itemRef,'utxt',::CFDataGetBytePtr(osxData),::CFDataGetLength(osxData),0) != noErr)
1330 wxFAIL_MSG(_("Adding flavor utxt failed"));
1331 // clean up:
1332 ::CFRelease(osxData);
1333 ::CFRelease(osxString);
1334 } /* block */
1335 break;
1336 case wxDF_BITMAP:
1337 case wxDF_METAFILE:
1338 case wxDF_SYLK:
1339 case wxDF_DIF:
1340 case wxDF_TIFF:
1341 case wxDF_OEMTEXT:
1342 case wxDF_DIB:
1343 case wxDF_PALETTE:
1344 case wxDF_PENDATA:
1345 case wxDF_RIFF:
1346 case wxDF_WAVE:
1347 case wxDF_ENHMETAFILE:
1348 case wxDF_FILENAME:
1349 case wxDF_LOCALE:
1350 case wxDF_PRIVATE:
1351 case wxDF_HTML:
1352 break; // not (yet) supported data formats
1353 default:
1354 wxFAIL_MSG(_("Unknown data format"));
1355 }
1356 delete[] dataFormats;
1357 }
1358 }
1359 return true;
1360 }
1361 else
1362 return false;
1363 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference, DataBrowserItemID, ItemReference*) */
1364
1365 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference dragRef, DataBrowserItemID itemID)
1366 {
1367 UInt16 noOfDraggedItems;
1368
1369 wxDataViewCtrl* dataViewCtrlPtr;
1370
1371
1372 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1373 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1374 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1375
1376 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1377 ::CountDragItems(dragRef,&noOfDraggedItems);
1378 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1379 {
1380 // collect native information:
1381 ItemReference itemRef;
1382 wxDataObjectComposite* dataObjects;
1383 wxMemoryBuffer buffer;
1384
1385 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1386 dataObjects = this->GetDnDDataObjects(dragRef,itemRef);
1387 // create wxWidget's event:
1388 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP,dataViewCtrlPtr->GetId());
1389
1390 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1391 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1392 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1393 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1394 dataViewEvent.SetDataObject(dataObjects);
1395 dataViewEvent.SetDataFormat(this->GetDnDDataFormat(dataObjects));
1396 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1397 {
1398 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1399 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1400 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1401 dataViewEvent.SetDataBuffer(buffer.GetData());
1402 }
1403
1404 // send event:
1405 if (!(dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed()))
1406 return false;
1407 }
1408 return true;
1409 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference, DataBrowserItemID) */
1410
1411 //
1412 // drag & drop helper methods
1413 //
1414 wxDataFormat wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite* dataObjects)
1415 {
1416 wxDataFormat resultFormat;
1417
1418
1419 if (dataObjects != NULL)
1420 {
1421 bool compatible(true);
1422
1423 size_t const noOfFormats = dataObjects->GetFormatCount();
1424 size_t indexFormat;
1425
1426 wxDataFormat* formats;
1427
1428 // get all formats and check afterwards if the formats are compatible; if they are compatible the preferred format is returned otherwise
1429 // wxDF_INVALID is returned;
1430 // currently compatible types (ordered by priority are):
1431 // - wxDF_UNICODETEXT - wxDF_TEXT
1432 formats = new wxDataFormat[noOfFormats];
1433 dataObjects->GetAllFormats(formats);
1434 indexFormat = 0;
1435 while ((indexFormat < noOfFormats) && compatible)
1436 {
1437 switch (resultFormat.GetType())
1438 {
1439 case wxDF_INVALID:
1440 resultFormat.SetType(formats[indexFormat].GetType()); // first format (should only be reached if indexFormat == 0
1441 break;
1442 case wxDF_TEXT:
1443 if (formats[indexFormat].GetType() == wxDF_UNICODETEXT)
1444 resultFormat.SetType(wxDF_UNICODETEXT);
1445 else // incompatible
1446 {
1447 resultFormat.SetType(wxDF_INVALID);
1448 compatible = false;
1449 }
1450 break;
1451 case wxDF_UNICODETEXT:
1452 if (formats[indexFormat].GetType() != wxDF_TEXT)
1453 {
1454 resultFormat.SetType(wxDF_INVALID);
1455 compatible = false;
1456 }
1457 break;
1458 default:
1459 resultFormat.SetType(wxDF_INVALID); // not (yet) supported format
1460 compatible = false;
1461 }
1462 ++indexFormat;
1463 } /* while */
1464 // clean up:
1465 delete[] formats;
1466 }
1467 return resultFormat;
1468 } /* wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite*) */
1469
1470 wxDataObjectComposite* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference dragRef, ItemReference itemRef) const
1471 {
1472 UInt16 noOfFlavors;
1473
1474 wxDataObjectComposite* dataObject;
1475
1476
1477 ::CountDragItemFlavors(dragRef,itemRef,&noOfFlavors);
1478 if (noOfFlavors > 0)
1479 {
1480 // 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:
1481 wxTextDataObject* textDataObject(NULL);
1482
1483 dataObject = new wxDataObjectComposite();
1484 for (UInt16 indexFlavor=1; indexFlavor<=noOfFlavors; ++indexFlavor)
1485 {
1486 // variable definition:
1487 FlavorType flavorDataObject;
1488
1489 if (::GetFlavorType(dragRef,itemRef,indexFlavor,&flavorDataObject) == noErr) // GetFlavorType uses a 1 based index!
1490 switch (flavorDataObject)
1491 {
1492 case 'TEXT':
1493 if (textDataObject == NULL) // otherwise a 'utxt' flavor has already been found that gets priority compared to the 'TEXT' flavor
1494 {
1495 // variable definitions:
1496 Size nativeDataSize;
1497 wxMemoryBuffer nativeData;
1498
1499 if ((::GetFlavorDataSize(dragRef,itemRef,'TEXT',&nativeDataSize) == noErr) &&
1500 (::GetFlavorData(dragRef,itemRef,'TEXT',nativeData.GetWriteBuf(nativeDataSize),&nativeDataSize,0) == noErr))
1501 {
1502 nativeData.UngetWriteBuf(nativeDataSize);
1503 textDataObject = new wxTextDataObject();
1504 if (textDataObject->SetData(nativeData.GetDataLen(),nativeData.GetData()))
1505 dataObject->Add(textDataObject);
1506 else
1507 {
1508 delete textDataObject;
1509 textDataObject = NULL;
1510 }
1511 }
1512 } /* block */
1513 break;
1514 case 'utxt':
1515 {
1516 // variable definition:
1517 Size nativeDataSize;
1518
1519 if (::GetFlavorDataSize(dragRef,itemRef,'utxt',&nativeDataSize) == noErr)
1520 {
1521 CFMutableDataRef draggedData;
1522
1523 draggedData = ::CFDataCreateMutable(kCFAllocatorDefault,nativeDataSize);
1524 ::CFDataSetLength(draggedData,nativeDataSize);
1525 if (::GetFlavorData(dragRef,itemRef,'utxt',::CFDataGetMutableBytePtr(draggedData),&nativeDataSize,0) == noErr)
1526 {
1527 // convert internally used UTF-16 representation to a UTF-8 representation:
1528 CFDataRef osxData;
1529 CFStringRef osxString;
1530
1531 osxString = ::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,draggedData,kCFStringEncodingUTF16); // BOM character is handled by this function automatically
1532 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF8,32);
1533 if (textDataObject == NULL)
1534 {
1535 textDataObject = new wxTextDataObject();
1536 if (textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData)))
1537 dataObject->Add(textDataObject);
1538 else
1539 {
1540 delete textDataObject;
1541 textDataObject = NULL;
1542 }
1543 }
1544 else // overwrite data because the 'utxt' flavor has priority over the 'TEXT' flavor
1545 (void) textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData));
1546 // clean up:
1547 ::CFRelease(osxData);
1548 ::CFRelease(osxString);
1549 }
1550 // clean up:
1551 ::CFRelease(draggedData);
1552 }
1553 } /* block */
1554 break;
1555 }
1556 }
1557 }
1558 else
1559 dataObject = NULL;
1560 return dataObject;
1561 } /* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference, ItemReference) const */
1562
1563 #endif // wxUSE_GENERICDATAVIEWCTRL
1564 #endif // wxUSE_DATAVIEWCTRL