]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/databrow.cpp
restore the default bitmap icons size to 16*15, making them larger if necessary is...
[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 RgnHandle rgn(NewRgn());
1063 UInt16 headerHeight;
1064
1065 if (this->GetRegion(kControlContentMetaPart,rgn) == noErr)
1066 GetRegionBounds(rgn,&content);
1067 else
1068 GetControlBounds(m_controlRef, &content);
1069 ::DisposeRgn(rgn);
1070 // space for the header
1071 this->GetHeaderButtonHeight(&headerHeight);
1072 content.top += headerHeight;
1073 // extra space for the frame (todo: do not how to determine the space automatically from the control)
1074 content.top += 5;
1075 content.left += 5;
1076 content.right -= 3;
1077 content.bottom -= 3;
1078 // extra space for the scrollbars:
1079 content.bottom -= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
1080 content.right -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1081
1082 wxDC *dc = dataViewCustomRendererPtr->GetDC();
1083
1084 wxRect cellrect( static_cast<int>(rectangle->left),
1085 static_cast<int>(rectangle->top),
1086 static_cast<int>(1+rectangle->right-rectangle->left),
1087 static_cast<int>(rectangle->bottom-rectangle->top) );
1088
1089 bool is_active = IsControlActive( this->m_controlRef );
1090 if (state == kDataBrowserItemIsSelected)
1091 {
1092
1093 wxColour col( wxMacCreateCGColorFromHITheme( (is_active) ?
1094 kThemeBrushAlternatePrimaryHighlightColor
1095 : kThemeBrushSecondaryHighlightColor ) );
1096
1097 wxRect rect = cellrect;
1098 Rect itemrect;
1099 GetDataBrowserItemPartBounds( this->m_controlRef, itemID, propertyID,
1100 kDataBrowserPropertyEnclosingPart, &itemrect );
1101 rect.x = itemrect.left;
1102 rect.width = itemrect.right-itemrect.left+1;
1103
1104 wxBrush selBrush( col );
1105 wxPen oldpen( dc->GetPen() );
1106 wxBrush oldbrush( dc->GetBrush() );
1107 dc->SetPen( *wxTRANSPARENT_PEN );
1108 dc->SetBrush( selBrush );
1109 dc->DrawRectangle(rect);
1110 dc->SetBrush( oldbrush );
1111 dc->SetPen( oldpen );
1112 }
1113
1114 wxDataViewModel *model = dataViewCtrlPtr->GetModel();
1115 if ((columnIndex == 0) || !model->IsContainer(dataitem) || model->HasContainerColumns(dataitem))
1116 {
1117 // make sure that 'Render' can draw only in the allowed area:
1118 dc->SetClippingRegion(content.left,content.top,content.right-content.left+1,content.bottom-content.top+1);
1119 (void) (dataViewCustomRendererPtr->Render( cellrect, dc,
1120 ((state == kDataBrowserItemIsSelected) ? wxDATAVIEW_CELL_SELECTED : 0)));
1121 dc->DestroyClippingRegion(); // probably not necessary
1122 }
1123
1124 dataViewCustomRendererPtr->SetDC(NULL);
1125 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemState, Rect const*, SInt16, Boolean) */
1126
1127 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
1128 {
1129 return false;
1130 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID, DataBrowserPropertyID, CFStringRef, Rect*, Boolean*) */
1131
1132 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID WXUNUSED(itemID), DataBrowserPropertyID WXUNUSED(property), Rect const* WXUNUSED(theRect), Rect const* WXUNUSED(mouseRect))
1133 {
1134 return true;
1135 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Rect const*) */
1136
1137 DataBrowserTrackingResult wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point WXUNUSED(startPt), EventModifiers WXUNUSED(modifiers))
1138 {
1139 wxDataViewColumn* dataViewColumnPtr;
1140
1141 wxDataViewCtrl* dataViewCtrlPtr;
1142
1143 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1144
1145 wxDataViewItem dataViewCustomRendererItem;
1146
1147
1148 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1149 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1150 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1151 dataViewCustomRendererItem = reinterpret_cast<void*>(itemID);
1152 wxCHECK_MSG(dataViewCustomRendererItem.IsOk(),kDataBrowserNothingHit,_("Invalid data view item"));
1153 dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
1154 wxCHECK_MSG(dataViewColumnPtr != NULL,kDataBrowserNothingHit,_("No column existing."));
1155 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1156 wxCHECK_MSG(dataViewCustomRendererPtr != NULL,kDataBrowserNothingHit,_("No renderer or invalid renderer type specified for custom data column."));
1157 // 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):
1158 if (dataViewCtrlPtr->GetCustomRendererItem() == dataViewCustomRendererItem)
1159 return kDataBrowserContentHit;
1160 // an(other) item is going to be edited and therefore the current editing - if existing - has to be finished:
1161 if (dataViewCtrlPtr->GetCustomRendererPtr() != NULL)
1162 {
1163 dataViewCtrlPtr->GetCustomRendererPtr()->FinishEditing();
1164 dataViewCtrlPtr->SetCustomRendererItem(wxDataViewItem());
1165 dataViewCtrlPtr->SetCustomRendererPtr (NULL);
1166 }
1167 // check if renderer has got a valid editor control for editing; if this is the case start editing of the new item:
1168 if (dataViewCustomRendererPtr->HasEditorCtrl())
1169 {
1170 // variable definition:
1171 wxRect wxRectangle;
1172
1173 ::wxMacNativeToRect(theRect,&wxRectangle);
1174 dataViewCustomRendererPtr->StartEditing(dataViewCustomRendererItem,wxRectangle);
1175 dataViewCtrlPtr->SetCustomRendererItem(dataViewCustomRendererItem);
1176 dataViewCtrlPtr->SetCustomRendererPtr (dataViewCustomRendererPtr);
1177 }
1178 return kDataBrowserContentHit;
1179 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Point, EventModifiers) */
1180
1181 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference dragRef, DataBrowserItemID itemID)
1182 {
1183 UInt16 noOfDraggedItems;
1184
1185 wxDataViewCtrl* dataViewCtrlPtr;
1186
1187
1188 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1189 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1190 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1191
1192 // send a drag possible event for each available item and proceed with it unless the event is vetoed:
1193 ::CountDragItems(dragRef,&noOfDraggedItems);
1194 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1195 {
1196 // collect native information:
1197 ItemReference itemRef;
1198 wxDataObjectComposite* dataObjects;
1199 wxMemoryBuffer buffer;
1200
1201 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1202 dataObjects = this->GetDnDDataObjects(dragRef,itemRef);
1203 // create wxWidget's event:
1204 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE,dataViewCtrlPtr->GetId());
1205
1206 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1207 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1208 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1209 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1210 dataViewEvent.SetDataObject(dataObjects);
1211 dataViewEvent.SetDataFormat(this->GetDnDDataFormat(dataObjects));
1212 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1213 {
1214 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1215 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1216 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1217 dataViewEvent.SetDataBuffer(buffer.GetData());
1218 }
1219
1220 // send event:
1221 if (!(dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed()))
1222 return false;
1223 }
1224 return true;
1225 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference, DataBrowserItemID) */
1226
1227 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
1228 {
1229 wxDataViewCtrl* dataViewCtrlPtr;
1230
1231 wxDataViewItem dataViewItem;
1232
1233
1234 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1235 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1236 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1237 dataViewItem = reinterpret_cast<void*>(itemID);
1238 wxCHECK_MSG(dataViewItem.IsOk(),false,_("Invalid data view item"));
1239
1240 // send a begin drag event and proceed with dragging unless the event is vetoed:
1241 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG,dataViewCtrlPtr->GetId());
1242
1243 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1244 dataViewEvent.SetItem(dataViewItem);
1245 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1246 // 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
1247 // the object a wxDataObjectComposite object is used;
1248 // currently, the composite object only contains a TAB concatenated string of all data:
1249 wxDataObjectComposite* dataObject(new wxDataObjectComposite());
1250 wxString dataString; // contains the TAB concatenated data
1251
1252 for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); i++)
1253 {
1254 // variable definition:
1255 wxVariant dataValue;
1256
1257 dataViewCtrlPtr->GetModel()->GetValue(dataValue,dataViewItem,dataViewCtrlPtr->GetColumn(i)->GetModelColumn());
1258 if (i > 0)
1259 dataString << wxT('\t');
1260 dataString << dataValue.MakeString();
1261 }
1262 dataObject->Add(new wxTextDataObject(dataString));
1263 dataViewEvent.SetDataObject(dataObject);
1264 // check if event has not been vetoed:
1265 if (dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed())
1266 {
1267 // for the internal drag & drop functions create two flavors:
1268 // - the data browser's item id;
1269 // - the data contained the dataview event object (if available).
1270 // Definition: a flavor is the type dependent representation of identical data.
1271 // Example: a number can be represented by its value and by its value converted to a string. In this case the flavor
1272 // of the number's internal representation is typeSInt32 while its string representation has got the flavor 'TEXT'.
1273 // Item id is one of the flavors:
1274 wxCHECK_MSG(::AddDragItemFlavor(dragRef,*itemRef,typeUInt32,&itemID,sizeof(itemID),0) == noErr,false,_("Unable to handle native drag&drop data"));
1275 // if the dataview event object contains data it is used for additional flavors; all natively known flavors are supported:
1276 if (dataViewEvent.GetDataObject() != NULL)
1277 {
1278 // constant definition for abbreviational purposes:
1279 size_t const noOfFormats = dataViewEvent.GetDataObject()->GetFormatCount();
1280
1281 if (noOfFormats > 0)
1282 {
1283 // variable definition:
1284 wxDataFormat* dataFormats;
1285
1286 dataFormats = new wxDataFormat[noOfFormats];
1287 dataViewEvent.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get);
1288 for (size_t i=0; i<noOfFormats; ++i)
1289 switch (dataFormats[i].GetType())
1290 {
1291 case wxDF_INVALID:
1292 wxFAIL_MSG(_("Data object has invalid data format"));
1293 break;
1294 case wxDF_TEXT:
1295 {
1296 // constant definition for abbreviational purposes:
1297 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1298 // variable definition and initialization:
1299 wxMemoryBuffer dataObject(dataSize);
1300
1301 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1302 dataObject.UngetWriteBuf(dataSize);
1303 if (::AddDragItemFlavor(dragRef,*itemRef,'TEXT',dataObject.GetData(),dataSize,0) != noErr)
1304 wxFAIL_MSG(_("Adding flavor TEXT failed"));
1305 } /* block */
1306 break;
1307 case wxDF_UNICODETEXT:
1308 {
1309 // constant definition for abbreviational purposes:
1310 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1311 // as there is no direct access to the data copy it to a memory buffer:
1312 wxMemoryBuffer dataObject(dataSize);
1313
1314 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1315 dataObject.UngetWriteBuf(dataSize);
1316 // if the data is stored in unicode format the internal representation is utf-8 (not mentioned in the documentation but in the source code);
1317 // DnD uses fixed utf-16 representation -> use the OSX functions for a conversion:
1318 CFDataRef osxData (::CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,reinterpret_cast<UInt8*>(dataObject.GetData()),dataSize,kCFAllocatorNull));
1319 CFStringRef osxString(::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,osxData,kCFStringEncodingUTF8));
1320
1321 // the osxString contains now the data and therefore the previously occupied memory can be released and re-used:
1322 ::CFRelease(osxData);
1323 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF16,32);
1324 if (::AddDragItemFlavor(dragRef,*itemRef,'utxt',::CFDataGetBytePtr(osxData),::CFDataGetLength(osxData),0) != noErr)
1325 wxFAIL_MSG(_("Adding flavor utxt failed"));
1326 // clean up:
1327 ::CFRelease(osxData);
1328 ::CFRelease(osxString);
1329 } /* block */
1330 break;
1331 case wxDF_BITMAP:
1332 case wxDF_METAFILE:
1333 case wxDF_SYLK:
1334 case wxDF_DIF:
1335 case wxDF_TIFF:
1336 case wxDF_OEMTEXT:
1337 case wxDF_DIB:
1338 case wxDF_PALETTE:
1339 case wxDF_PENDATA:
1340 case wxDF_RIFF:
1341 case wxDF_WAVE:
1342 case wxDF_ENHMETAFILE:
1343 case wxDF_FILENAME:
1344 case wxDF_LOCALE:
1345 case wxDF_PRIVATE:
1346 case wxDF_HTML:
1347 break; // not (yet) supported data formats
1348 default:
1349 wxFAIL_MSG(_("Unknown data format"));
1350 }
1351 delete[] dataFormats;
1352 }
1353 }
1354 return true;
1355 }
1356 else
1357 return false;
1358 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference, DataBrowserItemID, ItemReference*) */
1359
1360 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference dragRef, DataBrowserItemID itemID)
1361 {
1362 UInt16 noOfDraggedItems;
1363
1364 wxDataViewCtrl* dataViewCtrlPtr;
1365
1366
1367 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(this->GetWXPeer());
1368 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1369 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1370
1371 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1372 ::CountDragItems(dragRef,&noOfDraggedItems);
1373 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1374 {
1375 // collect native information:
1376 ItemReference itemRef;
1377 wxDataObjectComposite* dataObjects;
1378 wxMemoryBuffer buffer;
1379
1380 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1381 dataObjects = this->GetDnDDataObjects(dragRef,itemRef);
1382 // create wxWidget's event:
1383 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP,dataViewCtrlPtr->GetId());
1384
1385 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1386 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1387 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1388 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1389 dataViewEvent.SetDataObject(dataObjects);
1390 dataViewEvent.SetDataFormat(this->GetDnDDataFormat(dataObjects));
1391 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1392 {
1393 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1394 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1395 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1396 dataViewEvent.SetDataBuffer(buffer.GetData());
1397 }
1398
1399 // send event:
1400 if (!(dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed()))
1401 return false;
1402 }
1403 return true;
1404 } /* wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference, DataBrowserItemID) */
1405
1406 //
1407 // drag & drop helper methods
1408 //
1409 wxDataFormat wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite* dataObjects)
1410 {
1411 wxDataFormat resultFormat;
1412
1413
1414 if (dataObjects != NULL)
1415 {
1416 bool compatible(true);
1417
1418 size_t const noOfFormats = dataObjects->GetFormatCount();
1419 size_t indexFormat;
1420
1421 wxDataFormat* formats;
1422
1423 // get all formats and check afterwards if the formats are compatible; if they are compatible the preferred format is returned otherwise
1424 // wxDF_INVALID is returned;
1425 // currently compatible types (ordered by priority are):
1426 // - wxDF_UNICODETEXT - wxDF_TEXT
1427 formats = new wxDataFormat[noOfFormats];
1428 dataObjects->GetAllFormats(formats);
1429 indexFormat = 0;
1430 while ((indexFormat < noOfFormats) && compatible)
1431 {
1432 switch (resultFormat.GetType())
1433 {
1434 case wxDF_INVALID:
1435 resultFormat.SetType(formats[indexFormat].GetType()); // first format (should only be reached if indexFormat == 0
1436 break;
1437 case wxDF_TEXT:
1438 if (formats[indexFormat].GetType() == wxDF_UNICODETEXT)
1439 resultFormat.SetType(wxDF_UNICODETEXT);
1440 else // incompatible
1441 {
1442 resultFormat.SetType(wxDF_INVALID);
1443 compatible = false;
1444 }
1445 break;
1446 case wxDF_UNICODETEXT:
1447 if (formats[indexFormat].GetType() != wxDF_TEXT)
1448 {
1449 resultFormat.SetType(wxDF_INVALID);
1450 compatible = false;
1451 }
1452 break;
1453 default:
1454 resultFormat.SetType(wxDF_INVALID); // not (yet) supported format
1455 compatible = false;
1456 }
1457 ++indexFormat;
1458 } /* while */
1459 // clean up:
1460 delete[] formats;
1461 }
1462 return resultFormat;
1463 } /* wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite*) */
1464
1465 wxDataObjectComposite* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference dragRef, ItemReference itemRef) const
1466 {
1467 UInt16 noOfFlavors;
1468
1469 wxDataObjectComposite* dataObject;
1470
1471
1472 ::CountDragItemFlavors(dragRef,itemRef,&noOfFlavors);
1473 if (noOfFlavors > 0)
1474 {
1475 // 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:
1476 wxTextDataObject* textDataObject(NULL);
1477
1478 dataObject = new wxDataObjectComposite();
1479 for (UInt16 indexFlavor=1; indexFlavor<=noOfFlavors; ++indexFlavor)
1480 {
1481 // variable definition:
1482 FlavorType flavorDataObject;
1483
1484 if (::GetFlavorType(dragRef,itemRef,indexFlavor,&flavorDataObject) == noErr) // GetFlavorType uses a 1 based index!
1485 switch (flavorDataObject)
1486 {
1487 case 'TEXT':
1488 if (textDataObject == NULL) // otherwise a 'utxt' flavor has already been found that gets priority compared to the 'TEXT' flavor
1489 {
1490 // variable definitions:
1491 Size nativeDataSize;
1492 wxMemoryBuffer nativeData;
1493
1494 if ((::GetFlavorDataSize(dragRef,itemRef,'TEXT',&nativeDataSize) == noErr) &&
1495 (::GetFlavorData(dragRef,itemRef,'TEXT',nativeData.GetWriteBuf(nativeDataSize),&nativeDataSize,0) == noErr))
1496 {
1497 nativeData.UngetWriteBuf(nativeDataSize);
1498 textDataObject = new wxTextDataObject();
1499 if (textDataObject->SetData(nativeData.GetDataLen(),nativeData.GetData()))
1500 dataObject->Add(textDataObject);
1501 else
1502 {
1503 delete textDataObject;
1504 textDataObject = NULL;
1505 }
1506 }
1507 } /* block */
1508 break;
1509 case 'utxt':
1510 {
1511 // variable definition:
1512 Size nativeDataSize;
1513
1514 if (::GetFlavorDataSize(dragRef,itemRef,'utxt',&nativeDataSize) == noErr)
1515 {
1516 CFMutableDataRef draggedData;
1517
1518 draggedData = ::CFDataCreateMutable(kCFAllocatorDefault,nativeDataSize);
1519 ::CFDataSetLength(draggedData,nativeDataSize);
1520 if (::GetFlavorData(dragRef,itemRef,'utxt',::CFDataGetMutableBytePtr(draggedData),&nativeDataSize,0) == noErr)
1521 {
1522 // convert internally used UTF-16 representation to a UTF-8 representation:
1523 CFDataRef osxData;
1524 CFStringRef osxString;
1525
1526 osxString = ::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,draggedData,kCFStringEncodingUTF16); // BOM character is handled by this function automatically
1527 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF8,32);
1528 if (textDataObject == NULL)
1529 {
1530 textDataObject = new wxTextDataObject();
1531 if (textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData)))
1532 dataObject->Add(textDataObject);
1533 else
1534 {
1535 delete textDataObject;
1536 textDataObject = NULL;
1537 }
1538 }
1539 else // overwrite data because the 'utxt' flavor has priority over the 'TEXT' flavor
1540 (void) textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData));
1541 // clean up:
1542 ::CFRelease(osxData);
1543 ::CFRelease(osxString);
1544 }
1545 // clean up:
1546 ::CFRelease(draggedData);
1547 }
1548 } /* block */
1549 break;
1550 }
1551 }
1552 }
1553 else
1554 dataObject = NULL;
1555 return dataObject;
1556 } /* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference, ItemReference) const */
1557
1558 #endif // wxUSE_GENERICDATAVIEWCTRL
1559 #endif // wxUSE_DATAVIEWCTRL