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