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