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