Add wxDataViewCtrl::{Set,Get}CurrentItem().
[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 explicitely 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.Ok() ? 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::GetSelections(wxDataViewItemArray& sel) const
1111 {
1112 size_t noOfSelectedItems;
1113
1114 wxArrayDataBrowserItemID itemIDs;
1115
1116
1117 noOfSelectedItems = GetSelectedItemIDs(itemIDs);
1118 sel.Empty();
1119 sel.SetCount(noOfSelectedItems);
1120 for (size_t i=0; i<noOfSelectedItems; ++i)
1121 sel[i] = wxDataViewItem(reinterpret_cast<void*>(itemIDs[i]));
1122 return static_cast<int>(noOfSelectedItems);
1123 }
1124
1125 bool wxMacDataViewDataBrowserListViewControl::IsSelected(wxDataViewItem const& item) const
1126 {
1127 return IsItemSelected(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1128 }
1129
1130 void wxMacDataViewDataBrowserListViewControl::Select(wxDataViewItem const& item)
1131 {
1132 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1133
1134
1135 SetSelectedItems(1,&itemID,kDataBrowserItemsAdd);
1136 }
1137
1138 void wxMacDataViewDataBrowserListViewControl::SelectAll()
1139 {
1140 DataBrowserItemID* itemIDPtr;
1141
1142 Handle handle(::NewHandle(0));
1143
1144 size_t noOfItems;
1145
1146
1147 wxCHECK_RET(GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1148 noOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1149 ::HLock(handle);
1150 itemIDPtr = (DataBrowserItemID*) (*handle);
1151 SetSelectedItems(noOfItems,itemIDPtr,kDataBrowserItemsAssign);
1152 ::HUnlock(handle);
1153 ::DisposeHandle(handle);
1154 }
1155
1156 void wxMacDataViewDataBrowserListViewControl::Unselect(wxDataViewItem const& item)
1157 {
1158 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1159
1160
1161 SetSelectedItems(1,&itemID,kDataBrowserItemsRemove);
1162 }
1163
1164 void wxMacDataViewDataBrowserListViewControl::UnselectAll()
1165 {
1166 DataBrowserItemID* itemIDPtr;
1167
1168 Handle handle(::NewHandle(0));
1169
1170 size_t noOfItems;
1171
1172
1173 wxCHECK_RET(GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1174 noOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1175 ::HLock(handle);
1176 itemIDPtr = (DataBrowserItemID*) (*handle);
1177 SetSelectedItems(noOfItems,itemIDPtr,kDataBrowserItemsRemove);
1178 ::HUnlock(handle);
1179 ::DisposeHandle(handle);
1180 }
1181
1182 //
1183 // sorting related methods
1184 //
1185 wxDataViewColumn* wxMacDataViewDataBrowserListViewControl::GetSortingColumn() const
1186 {
1187 DataBrowserPropertyID propertyID;
1188
1189
1190 if (GetSortProperty(&propertyID) == noErr)
1191 return GetColumnPtr(propertyID);
1192 else
1193 return NULL;
1194 }
1195
1196 void wxMacDataViewDataBrowserListViewControl::Resort()
1197 {
1198 (void) wxMacDataBrowserListViewControl::Resort();
1199 }
1200
1201 //
1202 // other methods (inherited from wxDataViewWidgetImpl)
1203 //
1204 void
1205 wxMacDataViewDataBrowserListViewControl::HitTest(const wxPoint& WXUNUSED(point),
1206 wxDataViewItem& item,
1207 wxDataViewColumn*& columnPtr) const
1208 {
1209 // not yet implemented:
1210 item = wxDataViewItem();
1211 columnPtr = NULL;
1212 }
1213
1214 void wxMacDataViewDataBrowserListViewControl::DoSetIndent(int indent)
1215 {
1216 SetIndent(static_cast<float>(indent));
1217 }
1218
1219 void wxMacDataViewDataBrowserListViewControl::SetRowHeight(wxDataViewItem const& item, unsigned int height)
1220 {
1221 SetItemRowHeight(reinterpret_cast<DataBrowserItemID>(item.GetID()),static_cast<UInt16>(height));
1222 }
1223
1224 void wxMacDataViewDataBrowserListViewControl::OnSize()
1225 {
1226 UInt32 noOfColumns;
1227
1228
1229 GetColumnCount(&noOfColumns);
1230 if (noOfColumns <= 1) // no horizontal scroll bar and the only column expands to the width of the whole control
1231 {
1232 SetHasScrollBars(false,true);
1233 AutoSizeColumns();
1234 }
1235 else // otherwise keep the current column size and have scrollbars in both directions
1236 SetHasScrollBars(true,true);
1237 }
1238
1239 //
1240 // callback functions (inherited from wxMacDataBrowserTableViewControl)
1241 //
1242 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
1243 {
1244 DataBrowserSortOrder sortOrder;
1245
1246 DataBrowserTableViewColumnIndex modelColumnIndex;
1247
1248 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1249
1250
1251 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1252 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1253 if (sortProperty >= kMinPropertyID)
1254 {
1255 // variable definition and initialization:
1256 wxDataViewColumn* ColumnPtr(GetColumnPtr(sortProperty));
1257
1258 wxCHECK_MSG(ColumnPtr != NULL,false,_("Could not determine column index."));
1259 modelColumnIndex = ColumnPtr->GetModelColumn();
1260 }
1261 else
1262 modelColumnIndex = 0;
1263 GetSortOrder(&sortOrder);
1264 return static_cast<Boolean>(dataViewCtrlPtr->GetModel()->Compare(wxDataViewItem(reinterpret_cast<void*>(itemOneID)),wxDataViewItem(reinterpret_cast<void*>(itemTwoID)),
1265 modelColumnIndex,sortOrder != kDataBrowserOrderDecreasing) < 0);
1266 }
1267
1268 void wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* WXUNUSED(selection))
1269 // In this method we do not supply a contextual menu handler at all but only send a wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU.
1270 {
1271 wxArrayDataBrowserItemID itemIDs;
1272
1273 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1274
1275
1276 wxCHECK_RET(dataViewCtrlPtr != NULL,_("wxWidget control pointer is not a data view pointer"));
1277 // initialize parameters so that no context menu will be displayed automatically by the native data browser:
1278 *menu = NULL;
1279 *helpType = kCMHelpItemNoHelp;
1280 *helpItemString = NULL;
1281 // create information for a context menu event:
1282 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU,dataViewCtrlPtr->GetId());
1283
1284 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1285 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1286 // get the item information;
1287 // 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:
1288 if (GetSelectedItemIDs(itemIDs) > 0)
1289 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemIDs[0])));
1290 // finally send the equivalent wxWidget event:
1291 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1292 }
1293
1294 OSStatus wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
1295 {
1296 if (getValue)
1297 {
1298 // variable definitions:
1299 wxDataViewCtrl* dataViewCtrlPtr;
1300
1301 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1302 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1303 if (dataViewCtrlPtr->IsDeleting())
1304 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
1305 else
1306 {
1307 // variable definitions:
1308 OSStatus errorStatus;
1309 wxDataViewColumn* dataViewColumnPtr;
1310
1311 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1312 dataViewColumnPtr = GetColumnPtr(propertyID);
1313 wxCHECK_MSG((dataViewColumnPtr != NULL) && (dataViewColumnPtr->GetRenderer() != NULL),errDataBrowserNotConfigured,_("There is no column or renderer for the specified column index."));
1314
1315 wxDataViewItem dvItem(reinterpret_cast<void*>(itemID));
1316 unsigned int col = dataViewColumnPtr->GetModelColumn();
1317
1318 switch (dataViewColumnPtr->GetRenderer()->GetNativeData()->GetPropertyType())
1319 {
1320 case kDataBrowserCheckboxType:
1321 {
1322 // variable definition:
1323 ThemeButtonValue buttonValue;
1324
1325 errorStatus = ::GetDataBrowserItemDataButtonValue(itemData,&buttonValue);
1326 if (errorStatus == noErr)
1327 {
1328 if (buttonValue == kThemeButtonOn)
1329 {
1330 // variable definition and initialization:
1331 wxVariant modifiedData(true);
1332
1333 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1334 return noErr;
1335 else
1336 return errDataBrowserInvalidPropertyData;
1337 }
1338 else if (buttonValue == kThemeButtonOff)
1339 {
1340 // variable definition and initialization:
1341 wxVariant modifiedData(false);
1342
1343 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1344 return noErr;
1345 else
1346 return errDataBrowserInvalidPropertyData;
1347 }
1348 else
1349 return errDataBrowserInvalidPropertyData;
1350 }
1351 else
1352 return errorStatus;
1353 } /* block */
1354 case kDataBrowserTextType:
1355 {
1356 // variable definitions:
1357 CFStringRef stringReference;
1358
1359 errorStatus = ::GetDataBrowserItemDataText(itemData,&stringReference);
1360 if (errorStatus == noErr)
1361 {
1362 // variable definitions and initializations:
1363 #if wxCHECK_VERSION(2,9,0)
1364 wxCFStringRef modifiedString(stringReference);
1365 #else
1366 wxMacCFStringHolder modifiedString(stringReference);
1367 #endif
1368 wxVariant modifiedData(modifiedString.AsString());
1369
1370 if (dataViewCtrlPtr->GetModel()->ChangeValue(modifiedData, dvItem, col))
1371 return noErr;
1372 else
1373 return errDataBrowserInvalidPropertyData;
1374 }
1375 else
1376 return errorStatus;
1377 } /* block */
1378 default:
1379 return errDataBrowserPropertyNotSupported;
1380 }
1381 }
1382 }
1383 else
1384 {
1385 if (propertyID >= kMinPropertyID) // in case data columns set the data
1386 {
1387 // variable definitions:
1388 wxVariant variant;
1389 wxDataViewColumn* dataViewColumnPtr;
1390 wxDataViewCtrl* dataViewCtrlPtr;
1391
1392 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1393 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1394 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1395 dataViewColumnPtr = GetColumnPtr(propertyID);
1396 wxCHECK_MSG(dataViewColumnPtr != NULL,errDataBrowserNotConfigured,_("No column for the specified column position existing."));
1397 wxCHECK_MSG(dataViewColumnPtr->GetRenderer() != NULL,errDataBrowserNotConfigured,_("No renderer specified for column."));
1398 dataViewCtrlPtr->GetModel()->GetValue(variant,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
1399 if (!(variant.IsNull()))
1400 {
1401 dataViewColumnPtr->GetRenderer()->GetNativeData()->SetItemDataRef(itemData);
1402 dataViewColumnPtr->GetRenderer()->SetValue(variant);
1403 wxCHECK_MSG(dataViewColumnPtr->GetRenderer()->MacRender(),errDataBrowserNotConfigured,_("Rendering failed."));
1404 }
1405 return noErr;
1406 }
1407 else // react on special system requests
1408 {
1409 switch (propertyID)
1410 {
1411 case kDataBrowserContainerIsClosableProperty:
1412 {
1413 // variable definitions:
1414 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1415
1416 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1417 // initialize wxWidget event:
1418 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,dataViewCtrlPtr->GetId()); // variable definition
1419
1420 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1421 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
1422 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1423 // finally send the equivalent wxWidget event:
1424 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1425 // opening the container is allowed if not vetoed:
1426 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
1427 } /* block */
1428 case kDataBrowserContainerIsOpenableProperty:
1429 {
1430 // variable definitions:
1431 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1432
1433 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1434 // initialize wxWidget event:
1435 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,dataViewCtrlPtr->GetId()); // variable definition
1436
1437 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1438 dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast<void*>(itemID)));
1439 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1440 // finally send the equivalent wxWidget event:
1441 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1442 // opening the container is allowed if not vetoed:
1443 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
1444 } /* block */
1445 case kDataBrowserItemIsContainerProperty:
1446 {
1447 // variable definition:
1448 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1449
1450 wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
1451 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
1452 return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewCtrlPtr->GetModel()->IsContainer(wxDataViewItem(reinterpret_cast<void*>(itemID))));
1453 } /* block */
1454 case kDataBrowserItemIsEditableProperty:
1455 return ::SetDataBrowserItemDataBooleanValue(itemData,true);
1456 }
1457 }
1458 }
1459 return errDataBrowserPropertyNotSupported;
1460 }
1461
1462 void wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
1463 {
1464 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
1465
1466
1467 // 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:
1468 if (dataViewCtrlPtr != NULL)
1469 switch (message)
1470 {
1471 case kDataBrowserContainerClosed:
1472 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1473 {
1474 // initialize wxWidget event:
1475 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,dataViewCtrlPtr->GetId()); // variable definition
1476
1477 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1478 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1479 // finally send the equivalent wxWidget event:
1480 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1481 } /* block */
1482 break;
1483 case kDataBrowserContainerOpened:
1484 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1485 {
1486 // initialize wxWidget event:
1487 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,dataViewCtrlPtr->GetId()); // variable definition
1488
1489 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1490 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1491 // finally send the equivalent wxWidget event:
1492 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1493 // add children to the expanded container:
1494 dataViewCtrlPtr->AddChildren(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1495 } /* block */
1496 break;
1497 case kDataBrowserEditStarted:
1498 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1499 {
1500 // initialize wxWidget event:
1501 DataBrowserPropertyID propertyID;
1502 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition
1503
1504 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1505 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1506 if (GetPropertyID(itemData,&propertyID) == noErr)
1507 {
1508 // variable definition and initialization:
1509 DataBrowserTableViewColumnIndex columnIndex;
1510
1511 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
1512 dataViewEvent.SetColumn(columnIndex);
1513 dataViewEvent.SetDataViewColumn(GetColumnPtr(propertyID));
1514 }
1515 // finally send the equivalent wxWidget event:
1516 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1517 } /* block */
1518 break;
1519 case kDataBrowserEditStopped:
1520 {
1521 // initialize wxWidget event:
1522 DataBrowserPropertyID propertyID;
1523 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition
1524
1525 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1526 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1527 if (GetPropertyID(itemData,&propertyID) == noErr)
1528 {
1529 // variable definition and initialization:
1530 DataBrowserTableViewColumnIndex columnIndex;
1531
1532 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
1533 dataViewEvent.SetColumn(columnIndex);
1534 dataViewEvent.SetDataViewColumn(GetColumnPtr(propertyID));
1535 }
1536 // finally send the equivalent wxWidget event:
1537 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1538 } /* block */
1539 break;
1540 case kDataBrowserItemAdded:
1541 dataViewCtrlPtr->FinishCustomItemEditing();
1542 break;
1543 case kDataBrowserItemDeselected:
1544 dataViewCtrlPtr->FinishCustomItemEditing();
1545 break;
1546 case kDataBrowserItemDoubleClicked:
1547 {
1548 // initialize wxWidget event:
1549 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,dataViewCtrlPtr->GetId()); // variable definition
1550
1551 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1552 dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast<void*>(itemID)));
1553 // finally send the equivalent wxWidget event:
1554 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1555 } /* block */
1556 break;
1557 case kDataBrowserItemRemoved:
1558 dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
1559 break;
1560 case kDataBrowserItemSelected:
1561 break; // not implemented by wxWidgets; see kDataBrowserSelectionSetChanged
1562 case kDataBrowserSelectionSetChanged:
1563 {
1564 // initialize wxWidget event:
1565 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED,dataViewCtrlPtr->GetId()); // variable definition
1566
1567 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1568 dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
1569 // finally send the equivalent wxWidget event:
1570 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1571 } /* block */
1572 break;
1573 case kDataBrowserTargetChanged: // no idea if this notification is ever sent
1574 break;
1575 case kDataBrowserUserStateChanged:
1576 {
1577 // finish custom item editing if necessary:
1578 dataViewCtrlPtr->FinishCustomItemEditing();
1579 // update column widths:
1580 for (size_t i=0; i<dataViewCtrlPtr->GetColumnCount(); ++i)
1581 {
1582 // constant definition for abbreviational purposes:
1583 wxDataViewColumn* const columnPtr = dataViewCtrlPtr->GetColumnPtr(i);
1584 // variable definition:
1585 UInt16 columnWidth;
1586
1587 wxCHECK_RET(GetColumnWidth(columnPtr->GetNativeData()->GetPropertyID(),&columnWidth) == noErr,_("Column width could not be determined"));
1588 columnPtr->SetWidthVariable(columnWidth);
1589 }
1590 // update sorting orders:
1591 DataBrowserPropertyID propertyID; // variable definition
1592
1593 if ((GetSortProperty(&propertyID) == noErr) && (propertyID >= kMinPropertyID))
1594 {
1595 DataBrowserSortOrder sortOrder;
1596 DataBrowserTableViewColumnIndex columnIndex;
1597
1598 if ((GetSortOrder(&sortOrder) == noErr) && (GetColumnIndex(propertyID,&columnIndex) == noErr))
1599 {
1600 // variable definition and initialization:
1601 wxDataViewColumn* columnPtr;
1602 columnPtr = dataViewCtrlPtr->GetColumn(columnIndex);
1603 // check if the sort order has changed:
1604 if ( columnPtr->IsSortOrderAscending() && (sortOrder == kDataBrowserOrderDecreasing) ||
1605 !(columnPtr->IsSortOrderAscending()) && (sortOrder == kDataBrowserOrderIncreasing))
1606 {
1607 columnPtr->SetSortOrder(!(columnPtr->IsSortOrderAscending()));
1608 // initialize wxWidget event:
1609 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED,dataViewCtrlPtr->GetId()); // variable defintion
1610
1611 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1612 dataViewEvent.SetColumn(columnIndex);
1613 dataViewEvent.SetDataViewColumn(columnPtr);
1614 // finally send the equivalent wxWidget event:
1615 dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
1616 }
1617 }
1618 }
1619 } /* block */
1620 break;
1621 }
1622 }
1623
1624 void
1625 wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID itemID,
1626 DataBrowserPropertyID propertyID,
1627 DataBrowserItemState state,
1628 Rect const* rectangle,
1629 SInt16 WXUNUSED(bitDepth),
1630 Boolean WXUNUSED(colorDevice))
1631 {
1632 DataBrowserTableViewColumnIndex columnIndex;
1633
1634 wxDataViewColumn* dataViewColumnPtr;
1635
1636 wxDataViewCtrl* dataViewCtrlPtr;
1637
1638 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1639
1640 wxVariant dataToRender;
1641
1642 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1643 wxCHECK_RET(dataViewCtrlPtr != NULL, _("Pointer to data view control not set correctly."));
1644 wxCHECK_RET(dataViewCtrlPtr->GetModel() != NULL, _("Pointer to model not set correctly."));
1645 wxCHECK_RET(GetColumnIndex(propertyID,&columnIndex) == noErr,_("Could not determine column index."));
1646 dataViewColumnPtr = GetColumnPtr(propertyID);
1647 wxCHECK_RET(dataViewColumnPtr != NULL,_("No column for the specified column existing."));
1648 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1649 wxCHECK_RET(dataViewCustomRendererPtr != NULL,_("No renderer or invalid renderer type specified for custom data column."));
1650 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,wxDataViewItem(reinterpret_cast<void*>(itemID)),dataViewColumnPtr->GetModelColumn());
1651 dataViewCustomRendererPtr->SetValue(dataToRender);
1652
1653 wxDataViewItem dataItem( reinterpret_cast<void*>(itemID) );
1654 dataViewCtrlPtr->GetModel()->GetValue(dataToRender,dataItem,dataViewColumnPtr->GetModelColumn());
1655 dataViewCustomRendererPtr->SetValue(dataToRender);
1656
1657 // try to determine the content's size (drawable part):
1658 Rect content;
1659 RgnHandle rgn(NewRgn());
1660 UInt16 headerHeight;
1661
1662 if (GetControlRegion(m_controlRef,kControlContentMetaPart,rgn) == noErr)
1663 GetRegionBounds(rgn,&content);
1664 else
1665 GetControlBounds(m_controlRef, &content);
1666 ::DisposeRgn(rgn);
1667 // space for the header
1668 GetHeaderButtonHeight(&headerHeight);
1669 content.top += headerHeight;
1670 // extra space for the frame (todo: do not how to determine the space automatically from the control)
1671 content.top += 5;
1672 content.left += 5;
1673 content.right -= 3;
1674 content.bottom -= 3;
1675 // extra space for the scrollbars:
1676 content.bottom -= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
1677 content.right -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1678
1679 wxDC *dc = dataViewCustomRendererPtr->GetDC();
1680
1681 int active_border_fudge = 0;
1682 if (dataViewCtrlPtr->HasFocus() && !dataViewCtrlPtr->HasFlag( wxBORDER_NONE ))
1683 active_border_fudge = 1;
1684 else
1685 active_border_fudge = -2;
1686
1687 wxRect cellrect( static_cast<int>(rectangle->left + active_border_fudge),
1688 static_cast<int>(rectangle->top + active_border_fudge),
1689 static_cast<int>(1+rectangle->right-rectangle->left),
1690 static_cast<int>(rectangle->bottom-rectangle->top) );
1691
1692 bool is_active = IsControlActive( m_controlRef );
1693 if (state == kDataBrowserItemIsSelected)
1694 {
1695 wxColour col( wxMacCreateCGColorFromHITheme( (is_active) ?
1696 kThemeBrushAlternatePrimaryHighlightColor
1697 : kThemeBrushSecondaryHighlightColor ) );
1698
1699 wxRect rect = cellrect;
1700 Rect itemrect;
1701 GetDataBrowserItemPartBounds( m_controlRef, itemID, propertyID,
1702 kDataBrowserPropertyEnclosingPart, &itemrect );
1703 rect.x = itemrect.left-2;
1704 rect.width = itemrect.right-itemrect.left+3;
1705
1706 wxDCPenChanger setPen(*dc, *wxTRANSPARENT_PEN);
1707 wxDCBrushChanger setBrush(*dc, col);
1708 dc->DrawRectangle(rect);
1709 }
1710
1711 wxDataViewModel *model = dataViewCtrlPtr->GetModel();
1712 if ((columnIndex == 0) || !model->IsContainer(dataItem) || model->HasContainerColumns(dataItem))
1713 {
1714 // make sure that 'Render' can draw only in the allowed area:
1715 dc->SetClippingRegion(content.left,content.top,content.right-content.left+1,content.bottom-content.top+1);
1716 (void) (dataViewCustomRendererPtr->WXCallRender( cellrect, dc,
1717 ((state == kDataBrowserItemIsSelected) ? wxDATAVIEW_CELL_SELECTED : 0)));
1718 dc->DestroyClippingRegion(); // probably not necessary
1719 }
1720
1721 dataViewCustomRendererPtr->SetDC(NULL);
1722 }
1723
1724 Boolean
1725 wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(
1726 DataBrowserItemID WXUNUSED(itemID),
1727 DataBrowserPropertyID WXUNUSED(propertyID),
1728 CFStringRef WXUNUSED(theString),
1729 Rect* WXUNUSED(maxEditTextRect),
1730 Boolean* WXUNUSED(shrinkToFit))
1731 {
1732 return false;
1733 }
1734
1735 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID WXUNUSED(itemID), DataBrowserPropertyID WXUNUSED(property), Rect const* WXUNUSED(theRect), Rect const* WXUNUSED(mouseRect))
1736 {
1737 return true;
1738 }
1739
1740 DataBrowserTrackingResult wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point WXUNUSED(startPt), EventModifiers WXUNUSED(modifiers))
1741 {
1742 wxDataViewColumn* dataViewColumnPtr;
1743
1744 wxDataViewCtrl* dataViewCtrlPtr;
1745
1746 wxDataViewCustomRenderer* dataViewCustomRendererPtr;
1747
1748 wxDataViewItem dataViewCustomRendererItem;
1749
1750
1751 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1752 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1753 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1754 dataViewCustomRendererItem = reinterpret_cast<void*>(itemID);
1755 wxCHECK_MSG(dataViewCustomRendererItem.IsOk(),kDataBrowserNothingHit,_("Invalid data view item"));
1756 dataViewColumnPtr = GetColumnPtr(propertyID);
1757 wxCHECK_MSG(dataViewColumnPtr != NULL,kDataBrowserNothingHit,_("No column existing."));
1758 dataViewCustomRendererPtr = dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer());
1759 wxCHECK_MSG(dataViewCustomRendererPtr != NULL,kDataBrowserNothingHit,_("No renderer or invalid renderer type specified for custom data column."));
1760 // 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):
1761 if (dataViewCtrlPtr->GetCustomRendererItem() == dataViewCustomRendererItem)
1762 return kDataBrowserContentHit;
1763 // an(other) item is going to be edited and therefore the current editing - if existing - has to be finished:
1764 if (dataViewCtrlPtr->GetCustomRendererPtr() != NULL)
1765 {
1766 dataViewCtrlPtr->GetCustomRendererPtr()->FinishEditing();
1767 dataViewCtrlPtr->SetCustomRendererItem(wxDataViewItem());
1768 dataViewCtrlPtr->SetCustomRendererPtr (NULL);
1769 }
1770 // check if renderer has got a valid editor control for editing; if this is the case start editing of the new item:
1771 if (dataViewCustomRendererPtr->HasEditorCtrl())
1772 {
1773 // variable definition:
1774 wxRect wxRectangle;
1775
1776 ::wxMacNativeToRect(theRect,&wxRectangle);
1777 dataViewCustomRendererPtr->StartEditing(dataViewCustomRendererItem,wxRectangle);
1778 dataViewCtrlPtr->SetCustomRendererItem(dataViewCustomRendererItem);
1779 dataViewCtrlPtr->SetCustomRendererPtr (dataViewCustomRendererPtr);
1780 }
1781 return kDataBrowserContentHit;
1782 }
1783
1784 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAcceptDragProc(DragReference dragRef, DataBrowserItemID itemID)
1785 {
1786 bool acceptDrag;
1787
1788 UInt16 noOfDraggedItems;
1789
1790 wxDataViewCtrl* dataViewCtrlPtr;
1791
1792
1793 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1794 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1795 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1796
1797 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1798 ::CountDragItems(dragRef,&noOfDraggedItems);
1799 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1800 {
1801 // collect native information:
1802 ItemReference itemRef;
1803 wxDataObjectComposite* dataObjects;
1804 wxMemoryBuffer buffer;
1805
1806 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1807 dataObjects = GetDnDDataObjects(dragRef,itemRef);
1808 // create wxWidget's event:
1809 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE,dataViewCtrlPtr->GetId());
1810
1811 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1812 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1813 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1814 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1815 dataViewEvent.SetDataObject(dataObjects);
1816 dataViewEvent.SetDataFormat(GetDnDDataFormat(dataObjects));
1817 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1818 {
1819 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1820 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1821 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1822 dataViewEvent.SetDataBuffer(buffer.GetData());
1823 }
1824
1825 // send event:
1826 acceptDrag = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
1827 delete dataObjects;
1828 if (!acceptDrag)
1829 return false;
1830 }
1831 return true;
1832 }
1833
1834 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserAddDragItemProc(DragReference dragRef, DataBrowserItemID itemID, ItemReference* itemRef)
1835 {
1836 Boolean addDragItem;
1837
1838 wxDataViewCtrl* dataViewCtrlPtr;
1839
1840 wxDataViewItem dataViewItem;
1841
1842
1843 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1844 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1845 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1846 dataViewItem = reinterpret_cast<void*>(itemID);
1847 wxCHECK_MSG(dataViewItem.IsOk(),false,_("Invalid data view item"));
1848
1849 // send a begin drag event and proceed with dragging unless the event is vetoed:
1850 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG,dataViewCtrlPtr->GetId());
1851
1852 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1853 dataViewEvent.SetItem(dataViewItem);
1854 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1855 // 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
1856 // the object a wxDataObjectComposite object is used;
1857 // currently, the composite object only contains a TAB concatenated string of all data:
1858 wxDataObjectComposite* dataObject(new wxDataObjectComposite());
1859
1860 dataObject->Add(new wxTextDataObject(::ConcatenateDataViewItemValues(dataViewCtrlPtr,dataViewItem)));
1861 dataViewEvent.SetDataObject(dataObject);
1862 // check if event has not been vetoed:
1863 addDragItem = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
1864 if (addDragItem)
1865 {
1866 // for the internal drag & drop functions create two flavors:
1867 // - the data browser's item id;
1868 // - the data contained the dataview event object (if available).
1869 // Definition: a flavor is the type dependent representation of identical data.
1870 // Example: a number can be represented by its value and by its value converted to a string. In this case the flavor
1871 // of the number's internal representation is typeSInt32 while its string representation has got the flavor 'TEXT'.
1872 // Item id is one of the flavors:
1873 wxCHECK_MSG(::AddDragItemFlavor(dragRef,*itemRef,typeUInt32,&itemID,sizeof(itemID),0) == noErr,false,_("Unable to handle native drag&drop data"));
1874 // if the dataview event object contains data it is used for additional flavors; all natively known flavors are supported:
1875 if (dataViewEvent.GetDataObject() != NULL)
1876 {
1877 // constant definition for abbreviational purposes:
1878 size_t const noOfFormats = dataViewEvent.GetDataObject()->GetFormatCount();
1879
1880 if (noOfFormats > 0)
1881 {
1882 // variable definition:
1883 wxDataFormat* dataFormats;
1884
1885 dataFormats = new wxDataFormat[noOfFormats];
1886 dataViewEvent.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get);
1887 for (size_t i=0; i<noOfFormats; ++i)
1888 switch (dataFormats[i].GetType())
1889 {
1890 case wxDF_INVALID:
1891 wxFAIL_MSG(_("Data object has invalid data format"));
1892 break;
1893 case wxDF_TEXT:
1894 {
1895 // constant definition for abbreviational purposes:
1896 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1897 // variable definition and initialization:
1898 wxMemoryBuffer dataObject(dataSize);
1899
1900 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1901 dataObject.UngetWriteBuf(dataSize);
1902 if (::AddDragItemFlavor(dragRef,*itemRef,'TEXT',dataObject.GetData(),dataSize,0) != noErr)
1903 wxFAIL_MSG(_("Adding flavor TEXT failed"));
1904 } /* block */
1905 break;
1906 case wxDF_UNICODETEXT:
1907 {
1908 // constant definition for abbreviational purposes:
1909 size_t const dataSize = dataViewEvent.GetDataObject()->GetDataSize(wxDF_TEXT);
1910 // as there is no direct access to the data copy it to a memory buffer:
1911 wxMemoryBuffer dataObject(dataSize);
1912
1913 dataViewEvent.GetDataObject()->GetDataHere(wxDF_TEXT,dataObject.GetWriteBuf(dataSize));
1914 dataObject.UngetWriteBuf(dataSize);
1915 // if the data is stored in unicode format the internal representation is utf-8 (not mentioned in the documentation but in the source code);
1916 // DnD uses fixed utf-16 representation -> use the OSX functions for a conversion:
1917 CFDataRef osxData (::CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,reinterpret_cast<UInt8*>(dataObject.GetData()),dataSize,kCFAllocatorNull));
1918 CFStringRef osxString(::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,osxData,kCFStringEncodingUTF8));
1919
1920 // the osxString contains now the data and therefore the previously occupied memory can be released and re-used:
1921 ::CFRelease(osxData);
1922 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF16,32);
1923 if (::AddDragItemFlavor(dragRef,*itemRef,'utxt',::CFDataGetBytePtr(osxData),::CFDataGetLength(osxData),0) != noErr)
1924 wxFAIL_MSG(_("Adding flavor utxt failed"));
1925 // clean up:
1926 ::CFRelease(osxData);
1927 ::CFRelease(osxString);
1928 } /* block */
1929 break;
1930 case wxDF_BITMAP:
1931 case wxDF_METAFILE:
1932 case wxDF_SYLK:
1933 case wxDF_DIF:
1934 case wxDF_TIFF:
1935 case wxDF_OEMTEXT:
1936 case wxDF_DIB:
1937 case wxDF_PALETTE:
1938 case wxDF_PENDATA:
1939 case wxDF_RIFF:
1940 case wxDF_WAVE:
1941 case wxDF_ENHMETAFILE:
1942 case wxDF_FILENAME:
1943 case wxDF_LOCALE:
1944 case wxDF_PRIVATE:
1945 case wxDF_HTML:
1946 break; // not (yet) supported data formats
1947 default:
1948 wxFAIL_MSG(_("Unknown data format"));
1949 }
1950 delete[] dataFormats;
1951 }
1952 }
1953 }
1954 // clean-up and return result:
1955 delete dataObject;
1956 return addDragItem;
1957 }
1958
1959 Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserReceiveDragProc(DragReference dragRef, DataBrowserItemID itemID)
1960 {
1961 UInt16 noOfDraggedItems;
1962
1963 wxDataViewCtrl* dataViewCtrlPtr;
1964
1965
1966 dataViewCtrlPtr = dynamic_cast<wxDataViewCtrl*>(GetWXPeer());
1967 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
1968 wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
1969
1970 // send a drag possible event for each available and item und proceed with it unless the event is vetoed:
1971 ::CountDragItems(dragRef,&noOfDraggedItems);
1972 for (UInt16 indexDraggedItem=1; indexDraggedItem<=noOfDraggedItems; ++indexDraggedItem)
1973 {
1974 bool receiveDrag;
1975 ItemReference itemRef;
1976 wxDataObjectComposite* dataObjects;
1977 wxMemoryBuffer buffer;
1978
1979 // collect native information:
1980 ::GetDragItemReferenceNumber(dragRef,indexDraggedItem,&itemRef); // the index begins with 1!
1981 dataObjects = GetDnDDataObjects(dragRef,itemRef);
1982 // create wxWidget's event:
1983 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_DROP,dataViewCtrlPtr->GetId());
1984
1985 dataViewEvent.SetEventObject(dataViewCtrlPtr);
1986 dataViewEvent.SetItem(reinterpret_cast<void*>(itemID)); // this is the item that receives the event
1987 // (can be an invalid item ID, this is especially useful if the dataview does not contain any items)
1988 dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
1989 dataViewEvent.SetDataObject(dataObjects);
1990 dataViewEvent.SetDataFormat(GetDnDDataFormat(dataObjects));
1991 if (dataViewEvent.GetDataFormat().GetType() != wxDF_INVALID)
1992 {
1993 dataViewEvent.SetDataSize(dataObjects->GetDataSize(dataViewEvent.GetDataFormat().GetType()));
1994 dataObjects->GetDataHere(dataViewEvent.GetDataFormat().GetType(),buffer.GetWriteBuf(dataViewEvent.GetDataSize()));
1995 buffer.UngetWriteBuf(dataViewEvent.GetDataSize());
1996 dataViewEvent.SetDataBuffer(buffer.GetData());
1997 }
1998
1999 // send event:
2000 receiveDrag = dataViewCtrlPtr->HandleWindowEvent(dataViewEvent) && dataViewEvent.IsAllowed();
2001 delete dataObjects;
2002 if (!receiveDrag)
2003 return false;
2004 }
2005 return true;
2006 }
2007
2008 //
2009 // drag & drop helper methods
2010 //
2011 wxDataFormat wxMacDataViewDataBrowserListViewControl::GetDnDDataFormat(wxDataObjectComposite* dataObjects)
2012 {
2013 wxDataFormat resultFormat;
2014
2015
2016 if (dataObjects != NULL)
2017 {
2018 bool compatible(true);
2019
2020 size_t const noOfFormats = dataObjects->GetFormatCount();
2021 size_t indexFormat;
2022
2023 wxDataFormat* formats;
2024
2025 // get all formats and check afterwards if the formats are compatible; if they are compatible the preferred format is returned otherwise
2026 // wxDF_INVALID is returned;
2027 // currently compatible types (ordered by priority are):
2028 // - wxDF_UNICODETEXT - wxDF_TEXT
2029 formats = new wxDataFormat[noOfFormats];
2030 dataObjects->GetAllFormats(formats);
2031 indexFormat = 0;
2032 while ((indexFormat < noOfFormats) && compatible)
2033 {
2034 switch (resultFormat.GetType())
2035 {
2036 case wxDF_INVALID:
2037 resultFormat.SetType(formats[indexFormat].GetType()); // first format (should only be reached if indexFormat == 0
2038 break;
2039 case wxDF_TEXT:
2040 if (formats[indexFormat].GetType() == wxDF_UNICODETEXT)
2041 resultFormat.SetType(wxDF_UNICODETEXT);
2042 else // incompatible
2043 {
2044 resultFormat.SetType(wxDF_INVALID);
2045 compatible = false;
2046 }
2047 break;
2048 case wxDF_UNICODETEXT:
2049 if (formats[indexFormat].GetType() != wxDF_TEXT)
2050 {
2051 resultFormat.SetType(wxDF_INVALID);
2052 compatible = false;
2053 }
2054 break;
2055 default:
2056 resultFormat.SetType(wxDF_INVALID); // not (yet) supported format
2057 compatible = false;
2058 }
2059 ++indexFormat;
2060 } /* while */
2061 // clean up:
2062 delete[] formats;
2063 }
2064 else
2065 resultFormat = wxDF_INVALID;
2066 return resultFormat;
2067 }
2068
2069 wxDataObjectComposite* wxMacDataViewDataBrowserListViewControl::GetDnDDataObjects(DragReference dragRef, ItemReference itemRef) const
2070 {
2071 UInt16 noOfFlavors;
2072
2073 wxDataObjectComposite* dataObject;
2074
2075
2076 ::CountDragItemFlavors(dragRef,itemRef,&noOfFlavors);
2077 if (noOfFlavors > 0)
2078 {
2079 // 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:
2080 wxTextDataObject* textDataObject(NULL);
2081
2082 dataObject = new wxDataObjectComposite();
2083 for (UInt16 indexFlavor=1; indexFlavor<=noOfFlavors; ++indexFlavor)
2084 {
2085 // variable definition:
2086 FlavorType flavorDataObject;
2087
2088 if (::GetFlavorType(dragRef,itemRef,indexFlavor,&flavorDataObject) == noErr) // GetFlavorType uses a 1 based index!
2089 switch (flavorDataObject)
2090 {
2091 case 'TEXT':
2092 if (textDataObject == NULL) // otherwise a 'utxt' flavor has already been found that gets priority compared to the 'TEXT' flavor
2093 {
2094 // variable definitions:
2095 Size nativeDataSize;
2096 wxMemoryBuffer nativeData;
2097
2098 if ((::GetFlavorDataSize(dragRef,itemRef,'TEXT',&nativeDataSize) == noErr) &&
2099 (::GetFlavorData(dragRef,itemRef,'TEXT',nativeData.GetWriteBuf(nativeDataSize),&nativeDataSize,0) == noErr))
2100 {
2101 nativeData.UngetWriteBuf(nativeDataSize);
2102 textDataObject = new wxTextDataObject();
2103 if (textDataObject->SetData(nativeData.GetDataLen(),nativeData.GetData()))
2104 dataObject->Add(textDataObject);
2105 else
2106 {
2107 wxDELETE(textDataObject);
2108 }
2109 }
2110 } /* block */
2111 break;
2112 case 'utxt':
2113 {
2114 // variable definition:
2115 Size nativeDataSize;
2116
2117 if (::GetFlavorDataSize(dragRef,itemRef,'utxt',&nativeDataSize) == noErr)
2118 {
2119 CFMutableDataRef draggedData;
2120
2121 draggedData = ::CFDataCreateMutable(kCFAllocatorDefault,nativeDataSize);
2122 ::CFDataSetLength(draggedData,nativeDataSize);
2123 if (::GetFlavorData(dragRef,itemRef,'utxt',::CFDataGetMutableBytePtr(draggedData),&nativeDataSize,0) == noErr)
2124 {
2125 // convert internally used UTF-16 representation to a UTF-8 representation:
2126 CFDataRef osxData;
2127 CFStringRef osxString;
2128
2129 osxString = ::CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,draggedData,kCFStringEncodingUTF16); // BOM character is handled by this function automatically
2130 osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,osxString,kCFStringEncodingUTF8,32);
2131 if (textDataObject == NULL)
2132 {
2133 textDataObject = new wxTextDataObject();
2134 if (textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData)))
2135 dataObject->Add(textDataObject);
2136 else
2137 {
2138 wxDELETE(textDataObject);
2139 }
2140 }
2141 else // overwrite data because the 'utxt' flavor has priority over the 'TEXT' flavor
2142 (void) textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData));
2143 // clean up:
2144 ::CFRelease(osxData);
2145 ::CFRelease(osxString);
2146 }
2147 // clean up:
2148 ::CFRelease(draggedData);
2149 }
2150 } /* block */
2151 break;
2152 }
2153 }
2154 }
2155 else
2156 dataObject = NULL;
2157 return dataObject;
2158 }
2159
2160 //
2161 // other methods
2162 //
2163 wxDataViewColumn* wxMacDataViewDataBrowserListViewControl::GetColumnPtr(DataBrowserPropertyID propertyID) const
2164 {
2165 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(GetWXPeer()));
2166
2167 if (dataViewCtrlPtr != NULL)
2168 {
2169 size_t const noOfColumns = dataViewCtrlPtr->GetColumnCount();
2170
2171 for (size_t i=0; i<noOfColumns; ++i)
2172 if (dataViewCtrlPtr->GetColumnPtr(i)->GetNativeData()->GetPropertyID() == propertyID)
2173 return dataViewCtrlPtr->GetColumnPtr(i);
2174 }
2175 return NULL;
2176 }
2177
2178 // ---------------------------------------------------------
2179 // wxDataViewRenderer
2180 // ---------------------------------------------------------
2181 wxDataViewRenderer::wxDataViewRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2182 :wxDataViewRendererBase(varianttype,mode,align), m_alignment(align), m_mode(mode), m_NativeDataPtr(NULL)
2183 {
2184 }
2185
2186 wxDataViewRenderer::~wxDataViewRenderer()
2187 {
2188 delete m_NativeDataPtr;
2189 }
2190
2191 void wxDataViewRenderer::SetAlignment(int align)
2192 {
2193 m_alignment = align;
2194 }
2195
2196 namespace
2197 {
2198
2199 // get the browser control or NULL if anything went wrong (it's not supposed to
2200 // so we assert if it did)
2201 wxMacDataViewDataBrowserListViewControl *
2202 GetBrowserFromCol(wxDataViewColumn *col)
2203 {
2204 wxCHECK_MSG( col, NULL, "should have a valid column" );
2205
2206 wxDataViewCtrl * const dvc = col->GetOwner();
2207 wxCHECK_MSG( dvc, NULL, "column must be associated with the control" );
2208
2209 return static_cast<wxMacDataViewDataBrowserListViewControl *>(dvc->GetPeer());
2210 }
2211
2212 } // anonymous namespace
2213
2214 void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
2215 {
2216 wxDataViewColumn * const col = GetOwner();
2217 wxMacDataViewDataBrowserListViewControl * const
2218 browser = GetBrowserFromCol(col);
2219 wxCHECK_RET( browser, "must be fully initialized" );
2220
2221 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2222
2223 DataBrowserPropertyFlags flags;
2224 verify_noerr( browser->GetPropertyFlags(colID, &flags) );
2225
2226 if ( (mode == wxDATAVIEW_CELL_EDITABLE) ||
2227 (mode == wxDATAVIEW_CELL_ACTIVATABLE) )
2228 flags |= kDataBrowserPropertyIsEditable;
2229 else
2230 flags &= ~kDataBrowserPropertyIsEditable;
2231
2232 verify_noerr( browser->SetPropertyFlags(colID, flags) );
2233 }
2234
2235 void wxDataViewRenderer::EnableEllipsize(wxEllipsizeMode mode)
2236 {
2237 wxDataViewColumn * const col = GetOwner();
2238
2239 wxMacDataViewDataBrowserListViewControl * const
2240 browser = GetBrowserFromCol(col);
2241 wxCHECK_RET( browser, "must be fully initialized" );
2242
2243 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2244
2245 DataBrowserPropertyFlags flags;
2246 browser->GetPropertyFlags(colID, &flags);
2247
2248 flags &= ~(kDataBrowserDoNotTruncateText |
2249 kDataBrowserTruncateTextAtStart |
2250 kDataBrowserTruncateTextMiddle |
2251 kDataBrowserTruncateTextAtEnd);
2252
2253 int flagToSet = 0;
2254 switch ( mode )
2255 {
2256 case wxELLIPSIZE_NONE:
2257 flagToSet = kDataBrowserDoNotTruncateText;
2258 break;
2259
2260 case wxELLIPSIZE_START:
2261 flagToSet = kDataBrowserTruncateTextAtStart;
2262 break;
2263
2264 case wxELLIPSIZE_MIDDLE:
2265 flagToSet = kDataBrowserTruncateTextMiddle;
2266 break;
2267
2268 case wxELLIPSIZE_END:
2269 flagToSet = kDataBrowserTruncateTextAtEnd;
2270 break;
2271 }
2272
2273 wxCHECK_RET( flagToSet, "unknown wxEllipsizeMode value" );
2274
2275 flags |= flagToSet;
2276 verify_noerr( browser->SetPropertyFlags(colID, flags) );
2277 }
2278
2279 wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
2280 {
2281 wxDataViewColumn * const col = GetOwner();
2282
2283 wxMacDataViewDataBrowserListViewControl * const
2284 browser = GetBrowserFromCol(col);
2285 wxCHECK_MSG( browser, wxELLIPSIZE_NONE, "must be fully initialized" );
2286
2287 const DataBrowserPropertyID colID = col->GetNativeData()->GetPropertyID();
2288
2289 DataBrowserPropertyFlags flags;
2290 browser->GetPropertyFlags(colID, &flags);
2291
2292 if ( flags & kDataBrowserDoNotTruncateText )
2293 return wxELLIPSIZE_NONE;
2294 if ( flags & kDataBrowserTruncateTextAtStart )
2295 return wxELLIPSIZE_START;
2296 if ( flags & kDataBrowserTruncateTextAtEnd )
2297 return wxELLIPSIZE_END;
2298
2299 // kDataBrowserTruncateTextMiddle == 0 so there is no need to test for it
2300 return wxELLIPSIZE_MIDDLE;
2301 }
2302
2303 void wxDataViewRenderer::SetNativeData(wxDataViewRendererNativeData* newNativeDataPtr)
2304 {
2305 delete m_NativeDataPtr;
2306 m_NativeDataPtr = newNativeDataPtr;
2307 }
2308
2309 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
2310
2311 // ---------------------------------------------------------
2312 // wxDataViewCustomRenderer
2313 // ---------------------------------------------------------
2314 wxDataViewCustomRenderer::wxDataViewCustomRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2315 :wxDataViewCustomRendererBase(varianttype,mode,align),
2316 m_editorCtrlPtr(NULL),
2317 m_DCPtr(NULL)
2318 {
2319 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserCustomType));
2320 }
2321
2322 bool wxDataViewCustomRenderer::MacRender()
2323 {
2324 return true;
2325 }
2326
2327 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
2328
2329 // ---------------------------------------------------------
2330 // wxDataViewTextRenderer
2331 // ---------------------------------------------------------
2332 wxDataViewTextRenderer::wxDataViewTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2333 :wxDataViewRenderer(varianttype,mode,align)
2334 {
2335 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserTextType));
2336 }
2337
2338 bool wxDataViewTextRenderer::MacRender()
2339 {
2340 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Text renderer cannot render value; value type: ")) << GetValue().GetType());
2341
2342 wxCFStringRef cfString(GetValue().GetString(),(GetView()->GetFont().Ok() ? GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2343 return (::SetDataBrowserItemDataText(GetNativeData()->GetItemDataRef(),cfString) == noErr);
2344 }
2345
2346 IMPLEMENT_CLASS(wxDataViewTextRenderer,wxDataViewRenderer)
2347
2348 // ---------------------------------------------------------
2349 // wxDataViewBitmapRenderer
2350 // ---------------------------------------------------------
2351 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2352 :wxDataViewRenderer(varianttype,mode,align)
2353 {
2354 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserIconType));
2355 }
2356
2357 bool wxDataViewBitmapRenderer::MacRender()
2358 // This method returns 'true' if
2359 // - the passed bitmap is valid and it could be assigned to the native data browser;
2360 // - the passed bitmap is invalid (or is not initialized); this case simulates a non-existing bitmap.
2361 // In all other cases the method returns 'false'.
2362 {
2363 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Bitmap renderer cannot render value; value type: ")) << GetValue().GetType());
2364
2365 wxBitmap bitmap;
2366
2367 bitmap << GetValue();
2368 return (!(bitmap.Ok()) || (::SetDataBrowserItemDataIcon(GetNativeData()->GetItemDataRef(),bitmap.GetIconRef()) == noErr));
2369 }
2370
2371 IMPLEMENT_CLASS(wxDataViewBitmapRenderer,wxDataViewRenderer)
2372
2373 // ---------------------------------------------------------
2374 // wxDataViewIconTextRenderer
2375 // ---------------------------------------------------------
2376 wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(
2377 const wxString& varianttype,
2378 wxDataViewCellMode mode,
2379 int WXUNUSED(align))
2380 :wxDataViewRenderer(varianttype,mode)
2381 {
2382 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserIconAndTextType));
2383 }
2384
2385 bool wxDataViewIconTextRenderer::MacRender()
2386 {
2387 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Icon & text renderer cannot render value; value type: ")) << GetValue().GetType());
2388
2389 wxDataViewIconText iconText;
2390
2391 iconText << GetValue();
2392
2393 wxCFStringRef cfString(iconText.GetText(),(GetView()->GetFont().Ok() ? GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2394
2395 if (iconText.GetIcon().IsOk())
2396 if (::SetDataBrowserItemDataIcon(GetNativeData()->GetItemDataRef(),MAC_WXHICON(iconText.GetIcon().GetHICON())) != noErr)
2397 return false;
2398 return (::SetDataBrowserItemDataText(GetNativeData()->GetItemDataRef(),cfString) == noErr);
2399 }
2400
2401 IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
2402
2403
2404 // ---------------------------------------------------------
2405 // wxDataViewToggleRenderer
2406 // ---------------------------------------------------------
2407 wxDataViewToggleRenderer::wxDataViewToggleRenderer(
2408 const wxString& varianttype,
2409 wxDataViewCellMode mode,
2410 int WXUNUSED(align))
2411 :wxDataViewRenderer(varianttype,mode)
2412 {
2413 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserCheckboxType));
2414 }
2415
2416 bool wxDataViewToggleRenderer::MacRender()
2417 {
2418 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Toggle renderer cannot render value; value type: ")) << GetValue().GetType());
2419 return (::SetDataBrowserItemDataButtonValue(GetNativeData()->GetItemDataRef(),GetValue().GetBool()) == noErr);
2420 }
2421
2422 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer,wxDataViewRenderer)
2423
2424 // ---------------------------------------------------------
2425 // wxDataViewProgressRenderer
2426 // ---------------------------------------------------------
2427 wxDataViewProgressRenderer::wxDataViewProgressRenderer(
2428 const wxString& WXUNUSED(label),
2429 wxString const& varianttype,
2430 wxDataViewCellMode mode,
2431 int align)
2432 :wxDataViewRenderer(varianttype,mode,align)
2433 {
2434 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserProgressBarType));
2435 }
2436
2437 bool wxDataViewProgressRenderer::MacRender()
2438 {
2439 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Progress renderer cannot render value type; value type: ")) << GetValue().GetType());
2440 return ((::SetDataBrowserItemDataMinimum(GetNativeData()->GetItemDataRef(), 0) == noErr) &&
2441 (::SetDataBrowserItemDataMaximum(GetNativeData()->GetItemDataRef(),100) == noErr) &&
2442 (::SetDataBrowserItemDataValue (GetNativeData()->GetItemDataRef(),GetValue().GetLong()) == noErr));
2443 }
2444
2445 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer,wxDataViewRenderer)
2446
2447 // ---------------------------------------------------------
2448 // wxDataViewDateRenderer
2449 // ---------------------------------------------------------
2450 wxDataViewDateRenderer::wxDataViewDateRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
2451 :wxDataViewRenderer(varianttype,mode,align)
2452 {
2453 SetNativeData(new wxDataViewRendererNativeData(kDataBrowserDateTimeType));
2454 }
2455
2456 bool wxDataViewDateRenderer::MacRender()
2457 {
2458 wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString(_("Date renderer cannot render value; value type: ")) << GetValue().GetType());
2459 return (::SetDataBrowserItemDataDateTime(GetNativeData()->GetItemDataRef(),GetValue().GetDateTime().Subtract(wxDateTime(1,wxDateTime::Jan,1904)).GetSeconds().GetLo()) == noErr);
2460 }
2461
2462 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer,wxDataViewRenderer)
2463
2464 // ---------------------------------------------------------
2465 // wxDataViewColumn
2466 // ---------------------------------------------------------
2467 wxDataViewColumn::wxDataViewColumn(const wxString& title, wxDataViewRenderer* renderer, unsigned int model_column, int width, wxAlignment align, int flags)
2468 :wxDataViewColumnBase(renderer, model_column), m_NativeDataPtr(new wxDataViewColumnNativeData()), m_title(title)
2469 {
2470 InitCommon(width, align, flags);
2471 if ((renderer != NULL) && (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
2472 renderer->SetAlignment(align);
2473 }
2474
2475 wxDataViewColumn::wxDataViewColumn(const wxBitmap& bitmap, wxDataViewRenderer* renderer, unsigned int model_column, int width, wxAlignment align, int flags)
2476 :wxDataViewColumnBase(bitmap, renderer, model_column), m_NativeDataPtr(new wxDataViewColumnNativeData())
2477 {
2478 InitCommon(width, align, flags);
2479 if ((renderer != NULL) && (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
2480 renderer->SetAlignment(align);
2481 }
2482
2483 wxDataViewColumn::~wxDataViewColumn()
2484 {
2485 delete m_NativeDataPtr;
2486 }
2487
2488 int wxDataViewColumn::GetWidth() const
2489 {
2490 // FIXME: This returns the last programatically set width and will not work if
2491 // the user changes the column's width by dragging it with the mouse.
2492 return m_width;
2493 }
2494
2495 bool wxDataViewColumn::IsSortKey() const
2496 {
2497 wxDataViewCtrl * const dataViewCtrlPtr(GetOwner());
2498 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(
2499 dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(
2500 dataViewCtrlPtr->GetPeer()));
2501
2502 DataBrowserPropertyID propertyID;
2503 return (macDataViewListCtrlPtr->GetSortProperty(&propertyID) == noErr) &&
2504 (propertyID == GetNativeData()->GetPropertyID());
2505 }
2506
2507 void wxDataViewColumn::SetAlignment(wxAlignment align)
2508 {
2509 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2510
2511
2512 m_alignment = align;
2513 if (dataViewCtrlPtr != NULL)
2514 {
2515 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2516
2517 if (macDataViewListCtrlPtr != NULL)
2518 {
2519 DataBrowserListViewHeaderDesc headerDescription;
2520
2521 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2522 switch (align)
2523 {
2524 case wxALIGN_CENTER:
2525 case wxALIGN_CENTER_HORIZONTAL:
2526 headerDescription.btnFontStyle.just = teCenter;
2527 break;
2528 case wxALIGN_LEFT:
2529 headerDescription.btnFontStyle.just = teFlushLeft;
2530 break;
2531 case wxALIGN_RIGHT:
2532 headerDescription.btnFontStyle.just = teFlushRight;
2533 break;
2534 default:
2535 headerDescription.btnFontStyle.just = teFlushDefault;
2536 }
2537 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set alignment."));
2538 }
2539 }
2540 }
2541
2542 void wxDataViewColumn::SetBitmap(wxBitmap const& bitmap)
2543 {
2544 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2545
2546
2547 wxDataViewColumnBase::SetBitmap(bitmap);
2548 if (dataViewCtrlPtr != NULL)
2549 {
2550 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2551
2552 if (macDataViewListCtrlPtr != NULL)
2553 {
2554 DataBrowserListViewHeaderDesc headerDescription;
2555
2556 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2557 if (GetBitmap().Ok())
2558 headerDescription.btnContentInfo.u.iconRef = GetBitmap().GetIconRef();
2559 else
2560 headerDescription.btnContentInfo.u.iconRef = NULL;
2561 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set icon."));
2562 }
2563 }
2564 }
2565
2566 void wxDataViewColumn::SetMaxWidth(int maxWidth)
2567 {
2568 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2569
2570
2571 m_maxWidth = maxWidth;
2572 if (dataViewCtrlPtr != NULL)
2573 {
2574 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2575
2576 if (macDataViewListCtrlPtr != NULL)
2577 {
2578 DataBrowserListViewHeaderDesc headerDescription;
2579
2580 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2581 headerDescription.maximumWidth = static_cast<UInt16>(maxWidth);
2582 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set maximum width."));
2583 }
2584 }
2585 }
2586
2587 void wxDataViewColumn::SetMinWidth(int minWidth)
2588 {
2589 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2590
2591
2592 m_minWidth = minWidth;
2593 if (dataViewCtrlPtr != NULL)
2594 {
2595 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2596
2597 if (macDataViewListCtrlPtr != NULL)
2598 {
2599 DataBrowserListViewHeaderDesc headerDescription;
2600
2601 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2602 headerDescription.minimumWidth = static_cast<UInt16>(minWidth);
2603 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set minimum width."));
2604 }
2605 }
2606 }
2607
2608 void wxDataViewColumn::SetReorderable(bool reorderable)
2609 {
2610 // first set the internal flag of the column:
2611 if (reorderable)
2612 m_flags |= wxDATAVIEW_COL_REORDERABLE;
2613 else
2614 m_flags &= ~wxDATAVIEW_COL_REORDERABLE;
2615 // if the column is associated with a control change also immediately the flags of the control:
2616 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2617
2618 if (dataViewCtrlPtr != NULL)
2619 {
2620 DataBrowserPropertyFlags flags;
2621 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2622
2623 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
2624 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(GetNativeData()->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
2625 if (reorderable)
2626 flags |= kDataBrowserListViewMovableColumn;
2627 else
2628 flags &= ~kDataBrowserListViewMovableColumn;
2629 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(GetNativeData()->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
2630 }
2631 }
2632
2633 void wxDataViewColumn::SetResizeable(bool resizeable)
2634 {
2635 // first set the internal flag of the column:
2636 if (resizeable)
2637 m_flags |= wxDATAVIEW_COL_RESIZABLE;
2638 else
2639 m_flags &= ~wxDATAVIEW_COL_RESIZABLE;
2640 // if the column is associated with a control change also immediately the flags of the control:
2641 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2642
2643 if (dataViewCtrlPtr != NULL)
2644 {
2645 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2646
2647 if (macDataViewListCtrlPtr != NULL)
2648 {
2649 DataBrowserListViewHeaderDesc headerDescription;
2650
2651 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2652 if (resizeable)
2653 {
2654 if (GetMinWidth() >= GetMaxWidth())
2655 {
2656 m_minWidth = 0;
2657 m_maxWidth = 30000;
2658 }
2659 headerDescription.minimumWidth = m_minWidth;
2660 headerDescription.maximumWidth = m_maxWidth;
2661 }
2662 else
2663 {
2664 headerDescription.minimumWidth = m_width;
2665 headerDescription.maximumWidth = m_width;
2666 }
2667 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2668 macDataViewListCtrlPtr->SetSortProperty(GetNativeData()->GetPropertyID());
2669 }
2670 }
2671 }
2672
2673 void wxDataViewColumn::SetSortable(bool sortable)
2674 {
2675 // first set the internal flag of the column:
2676 if (sortable)
2677 m_flags |= wxDATAVIEW_COL_SORTABLE;
2678 else
2679 m_flags &= ~wxDATAVIEW_COL_SORTABLE;
2680 // if the column is associated with a control change also immediately the flags of the control:
2681 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2682
2683 if (dataViewCtrlPtr != NULL)
2684 {
2685 DataBrowserPropertyFlags flags;
2686 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2687
2688 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
2689 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(GetNativeData()->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
2690 if (sortable)
2691 flags |= kDataBrowserListViewSortableColumn;
2692 else
2693 flags &= ~kDataBrowserListViewSortableColumn;
2694 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(GetNativeData()->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
2695 }
2696 }
2697
2698 void wxDataViewColumn::SetSortOrder(bool ascending)
2699 {
2700 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2701
2702
2703 m_ascending = ascending;
2704 if (dataViewCtrlPtr != NULL)
2705 {
2706 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2707
2708 if (macDataViewListCtrlPtr != NULL)
2709 {
2710 DataBrowserListViewHeaderDesc headerDescription;
2711
2712 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2713 if (ascending)
2714 headerDescription.initialOrder = kDataBrowserOrderIncreasing;
2715 else
2716 headerDescription.initialOrder = kDataBrowserOrderDecreasing;
2717 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription));
2718 macDataViewListCtrlPtr->SetSortProperty(GetNativeData()->GetPropertyID());
2719 }
2720 }
2721 }
2722
2723 void wxDataViewColumn::SetTitle(wxString const& title)
2724 {
2725 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2726
2727
2728 m_title = title;
2729 if (dataViewCtrlPtr != NULL)
2730 {
2731 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2732
2733 if (macDataViewListCtrlPtr != NULL)
2734 {
2735 DataBrowserListViewHeaderDesc headerDescription;
2736 wxCFStringRef cfTitle(title,(dataViewCtrlPtr->GetFont().Ok() ? dataViewCtrlPtr->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
2737
2738 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
2739 headerDescription.titleString = cfTitle;
2740 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(GetNativeData()->GetPropertyID(),&headerDescription) == noErr,_("Could not set header description."));
2741 }
2742 }
2743 }
2744
2745 void wxDataViewColumn::SetWidth(int width)
2746 {
2747 wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
2748
2749
2750 if ((width >= m_minWidth) && (width <= m_maxWidth))
2751 {
2752 m_width = width;
2753 if (dataViewCtrlPtr != NULL)
2754 {
2755 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
2756
2757 if (macDataViewListCtrlPtr != NULL)
2758 wxCHECK_RET(macDataViewListCtrlPtr->SetColumnWidth(GetNativeData()->GetPropertyID(),static_cast<UInt16>(width)) == noErr,_("Could not set column width."));
2759 }
2760 }
2761 }
2762
2763 void wxDataViewColumn::SetHidden(bool WXUNUSED(hidden))
2764 {
2765 // How to do that?
2766 }
2767
2768 bool wxDataViewColumn::IsHidden() const
2769 {
2770 return true;
2771 }
2772
2773
2774 void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
2775 {
2776 // see wxGTK native wxDataViewColumn implementation
2777 wxFAIL_MSG( "not implemented" );
2778 }
2779
2780 void wxDataViewColumn::SetNativeData(wxDataViewColumnNativeData* newNativeDataPtr)
2781 {
2782 delete m_NativeDataPtr;
2783 m_NativeDataPtr = newNativeDataPtr;
2784 }
2785
2786 #endif // wxUSE_DATAVIEWCTRL && !wxUSE_GENERICDATAVIEWCTRL