]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/dataview.cpp
8a35b22c5617f566bab11e236fd6e002cb16a8e1
[wxWidgets.git] / src / osx / carbon / dataview.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/datavgen.cpp
3 // Purpose: wxDataViewCtrl native mac implementation
4 // Author:
5 // Id: $Id$
6 // Copyright: (c) 2007
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
14
15 #include "wx/dataview.h"
16
17 #if !defined(wxUSE_GENERICDATAVIEWCTRL) || (wxUSE_GENERICDATAVIEWCTRL == 0)
18
19 #include <limits>
20
21 #include "wx/osx/carbon/databrow.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/timer.h"
25 #include "wx/settings.h"
26 #include "wx/dcclient.h"
27 #include "wx/icon.h"
28 #endif
29
30 #include "wx/renderer.h"
31
32 //-----------------------------------------------------------------------------
33 // local constants
34 //-----------------------------------------------------------------------------
35
36 // a list of all catchable events:
37 static EventTypeSpec const eventList[] =
38 {
39 {kEventClassControl, kEventControlDraw},
40 {kEventClassControl, kEventControlHit}
41 };
42
43 //-----------------------------------------------------------------------------
44 // local functions
45 //-----------------------------------------------------------------------------
46
47 static pascal OSStatus wxMacDataViewCtrlEventHandler(EventHandlerCallRef handler, EventRef EventReference, void* Data)
48 {
49 wxDataViewCtrl* DataViewCtrlPtr((wxDataViewCtrl*) Data); // the 'Data' variable always contains a pointer to the data view control that installed the handler
50
51 wxMacCarbonEvent CarbonEvent(EventReference) ;
52
53
54 switch (GetEventKind(EventReference))
55 {
56 case kEventControlDraw:
57 {
58 OSStatus status;
59
60 DataViewCtrlPtr->MacSetDrawingContext(CarbonEvent.GetParameter<CGContextRef>(kEventParamCGContextRef,typeCGContextRef));
61 status = ::CallNextEventHandler(handler,EventReference);
62 DataViewCtrlPtr->MacSetDrawingContext(NULL);
63 return status;
64 }
65 case kEventControlHit :
66 if (CarbonEvent.GetParameter<ControlPartCode>(kEventParamControlPart,typeControlPartCode) == kControlButtonPart) // we only care about the header
67 {
68 ControlRef controlReference;
69 DataBrowserPropertyID columnPropertyID;
70 unsigned long columnIndex;
71 OSStatus status;
72 wxDataViewEvent DataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK,DataViewCtrlPtr->GetId());
73
74 CarbonEvent.GetParameter(kEventParamDirectObject,&controlReference);
75 // determine the column that triggered the event (this is the column that is responsible for sorting the data view):
76 status = ::GetDataBrowserSortProperty(controlReference,&columnPropertyID);
77 wxCHECK(status == noErr,status);
78 status = ::GetDataBrowserTableViewColumnPosition(controlReference,columnPropertyID,&columnIndex);
79 if (status == errDataBrowserPropertyNotFound) // user clicked into part of the header that does not have a property
80 return ::CallNextEventHandler(handler,EventReference);
81 wxCHECK(status == noErr,status);
82 // initialize wxWidget event handler:
83 DataViewEvent.SetEventObject(DataViewCtrlPtr);
84 DataViewEvent.SetColumn(columnIndex);
85 DataViewEvent.SetDataViewColumn(DataViewCtrlPtr->GetColumn(columnIndex));
86 // finally sent the equivalent wxWidget event:
87 DataViewCtrlPtr->HandleWindowEvent(DataViewEvent);
88 return ::CallNextEventHandler(handler,EventReference);
89 }
90 else
91 return eventNotHandledErr;
92 }
93
94 return eventNotHandledErr;
95 }
96
97 static DataBrowserItemID* CreateDataBrowserItemIDArray(size_t& noOfEntries, wxDataViewItemArray const& items) // returns a newly allocated pointer to valid data browser item IDs
98 {
99 size_t const noOfItems = items.GetCount();
100
101 DataBrowserItemID* itemIDs(new DataBrowserItemID[noOfItems]);
102
103
104 // convert all valid data view items to data browser items
105 noOfEntries = 0;
106 for (size_t i=0; i<noOfItems; ++i)
107 if (items[i].IsOk())
108 {
109 itemIDs[noOfEntries] = reinterpret_cast<DataBrowserItemID>(items[i].GetID());
110 ++noOfEntries;
111 }
112 // done:
113 return itemIDs;
114 }
115
116 static bool InitializeColumnDescription(DataBrowserListViewColumnDesc& columnDescription, wxDataViewColumn const* columnPtr, DataBrowserPropertyID columnPropertyID, wxCFStringRef const& title)
117 {
118 // set properties for the column:
119 columnDescription.propertyDesc.propertyID = columnPropertyID;
120 columnDescription.propertyDesc.propertyType = columnPtr->GetRenderer()->GetPropertyType();
121 columnDescription.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn; // make the column selectable
122 if (columnPtr->IsReorderable())
123 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewMovableColumn;
124 if (columnPtr->IsResizeable())
125 {
126 columnDescription.headerBtnDesc.minimumWidth = 0;
127 columnDescription.headerBtnDesc.maximumWidth = 30000; // 32767 is the theoretical maximum though but 30000 looks nicer
128 }
129 else
130 {
131 columnDescription.headerBtnDesc.minimumWidth = columnPtr->GetWidth();
132 columnDescription.headerBtnDesc.maximumWidth = columnPtr->GetWidth();
133 }
134 if (columnPtr->IsSortable())
135 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewSortableColumn;
136 if (columnPtr->GetRenderer()->GetMode() == wxDATAVIEW_CELL_EDITABLE)
137 columnDescription.propertyDesc.propertyFlags |= kDataBrowserPropertyIsEditable;
138 if ((columnDescription.propertyDesc.propertyType == kDataBrowserCustomType) ||
139 (columnDescription.propertyDesc.propertyType == kDataBrowserDateTimeType) ||
140 (columnDescription.propertyDesc.propertyType == kDataBrowserIconAndTextType) ||
141 (columnDescription.propertyDesc.propertyType == kDataBrowserTextType))
142 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn; // enables generally the possibility to have user input for the mentioned types
143 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
144 columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewNoGapForIconInHeaderButton;
145 #endif
146 // set header's properties:
147 columnDescription.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
148 columnDescription.headerBtnDesc.titleOffset = 0;
149 columnDescription.headerBtnDesc.titleString = ::CFStringCreateCopy(kCFAllocatorDefault,title);
150 columnDescription.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing; // choose one of the orders as "undefined" is not supported anyway (s. ControlDefs.h in the HIToolbox framework)
151 columnDescription.headerBtnDesc.btnFontStyle.flags = kControlUseFontMask | kControlUseJustMask;
152 switch (columnPtr->GetAlignment())
153 {
154 case wxALIGN_CENTER:
155 case wxALIGN_CENTER_HORIZONTAL:
156 columnDescription.headerBtnDesc.btnFontStyle.just = teCenter;
157 break;
158 case wxALIGN_LEFT:
159 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushLeft;
160 break;
161 case wxALIGN_RIGHT:
162 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushRight;
163 break;
164 default:
165 columnDescription.headerBtnDesc.btnFontStyle.just = teFlushDefault;
166 }
167 columnDescription.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
168 columnDescription.headerBtnDesc.btnFontStyle.style = normal;
169 if (columnPtr->GetBitmap().IsOk())
170 {
171 columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
172 columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = columnPtr->GetBitmap().GetIconRef();
173 }
174 else
175 {
176 // not text only as we otherwise could not add a bitmap later
177 // columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
178 columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
179 columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = NULL;
180 }
181
182 // done:
183 return true;
184 }
185
186 //-----------------------------------------------------------------------------
187 // local function pointers
188 //-----------------------------------------------------------------------------
189
190 DEFINE_ONE_SHOT_HANDLER_GETTER(wxMacDataViewCtrlEventHandler)
191
192 // ---------------------------------------------------------
193 // wxMacDataViewModelNotifier
194 // ---------------------------------------------------------
195 class wxMacDataViewModelNotifier : public wxDataViewModelNotifier
196 {
197 public:
198 wxMacDataViewModelNotifier(wxMacDataViewDataBrowserListViewControl* initDataViewControlPtr) : m_dataViewControlPtr(initDataViewControlPtr)
199 {
200 }
201
202 virtual bool ItemAdded(const wxDataViewItem &parent, const wxDataViewItem &item)
203 {
204 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
205
206 wxCHECK_MSG(item.IsOk(),false,_("Added item is invalid."));
207 bool noFailureFlag = (!(parent.IsOk()) && (m_dataViewControlPtr->AddItem(kDataBrowserNoItem,&itemID) == noErr) ||
208 parent.IsOk() && (m_dataViewControlPtr->AddItem(reinterpret_cast<DataBrowserItemID>(parent.GetID()),&itemID) == noErr));
209
210 wxDataViewCtrl *dvc = (wxDataViewCtrl*) m_dataViewControlPtr->GetWXPeer();
211 if (dvc->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
212 {
213 wxDataViewModel *model = GetOwner();
214
215 int height = 20; // TODO find out standard height
216 unsigned int num = dvc->GetColumnCount();
217 unsigned int col;
218 for (col = 0; col < num; col++)
219 {
220 wxDataViewColumn *column = dvc->GetColumn( col );
221 if (column->IsHidden())
222 continue;
223
224 wxDataViewCustomRenderer *renderer = wxDynamicCast( column->GetRenderer(), wxDataViewCustomRenderer );
225 if (renderer)
226 {
227 wxVariant value;
228 model->GetValue( value, item, column->GetModelColumn() );
229 renderer->SetValue( value );
230 height = wxMax( height, renderer->GetSize().y );
231 }
232
233 }
234
235 if (height > 20)
236 m_dataViewControlPtr->SetRowHeight( itemID, height );
237 }
238
239 return noFailureFlag;
240 }
241
242 virtual bool ItemsAdded(wxDataViewItem const& parent, wxDataViewItemArray const& items)
243 {
244 bool noFailureFlag;
245
246 DataBrowserItemID* itemIDs;
247
248 size_t noOfEntries;
249
250
251 // convert all valid data view items to data browser items:
252 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
253 // insert all valid items into control:
254 noFailureFlag = ((noOfEntries == 0) ||
255 !(parent.IsOk()) && (m_dataViewControlPtr->AddItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
256 parent.IsOk() && (m_dataViewControlPtr->AddItems(reinterpret_cast<DataBrowserItemID>(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
257 // give allocated array space free again:
258 delete[] itemIDs;
259
260 wxDataViewCtrl *dvc = (wxDataViewCtrl*) m_dataViewControlPtr->GetWXPeer();
261 if (dvc->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
262 {
263 wxDataViewModel *model = GetOwner();
264 unsigned int colnum = dvc->GetColumnCount();
265
266 size_t i;
267 size_t count = items.GetCount();
268 for (i = 0; i < count; i++)
269 {
270 wxDataViewItem item = items[i];
271 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
272
273 int height = 20; // TODO find out standard height
274 unsigned int col;
275 for (col = 0; col < colnum; col++)
276 {
277 wxDataViewColumn *column = dvc->GetColumn( col );
278 if (column->IsHidden())
279 continue; // skip it!
280
281 if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
282 continue; // skip it!
283
284 wxDataViewCustomRenderer *renderer = wxDynamicCast( column->GetRenderer(), wxDataViewCustomRenderer );
285 if (renderer)
286 {
287 wxVariant value;
288 model->GetValue( value, item, column->GetModelColumn() );
289 renderer->SetValue( value );
290 height = wxMax( height, renderer->GetSize().y );
291 }
292 }
293
294 if (height > 20)
295 m_dataViewControlPtr->SetRowHeight( itemID, height );
296 }
297 }
298
299 // done:
300 return noFailureFlag;
301 }
302
303 virtual bool ItemChanged(wxDataViewItem const& item)
304 {
305 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
306
307
308 wxCHECK_MSG(item.IsOk(),false,_("Changed item is invalid."));
309 if (m_dataViewControlPtr->UpdateItems(&itemID) == noErr)
310 {
311 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(m_dataViewControlPtr->GetWXPeer()));
312
313 // sent the equivalent wxWidget event:
314 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId());
315
316 dataViewEvent.SetEventObject(dataViewCtrlPtr);
317 dataViewEvent.SetItem(item);
318 // sent the equivalent wxWidget event:
319 dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
320 // done
321 return true;
322 }
323 else
324 return false;
325 }
326
327 virtual bool ItemsChanged(wxDataViewItemArray const& items)
328 {
329 bool noFailureFlag;
330
331 DataBrowserItemID* itemIDs;
332
333 size_t noOfEntries;
334
335
336 // convert all valid data view items to data browser items:
337 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
338 // change items (ATTENTION: ONLY ITEMS OF THE ROOT ARE CHANGED BECAUSE THE PARENT PARAMETER IS MISSING):
339 noFailureFlag = (m_dataViewControlPtr->UpdateItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty,kDataBrowserItemNoProperty) == noErr);
340 if (noFailureFlag)
341 {
342 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(m_dataViewControlPtr->GetWXPeer()));
343
344 // send for all changed items a wxWidget event:
345 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId());
346
347 dataViewEvent.SetEventObject(dataViewCtrlPtr);
348 for (size_t i=0; i<noOfEntries; ++i)
349 {
350 dataViewEvent.SetItem(reinterpret_cast<void*>(itemIDs[i]));
351 dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
352 }
353 }
354 // release allocated array space:
355 delete[] itemIDs;
356 // done:
357 return noFailureFlag;
358 }
359
360 virtual bool ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
361 {
362 if (item.IsOk())
363 {
364 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
365 OSStatus errorStatus;
366 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(m_dataViewControlPtr->GetWXPeer()));
367
368 // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
369 // not to be identical because the being edited item might be below the passed item in the hierarchy);
370 // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
371 // has been started and that variables can currently not be updated even when requested by the system:
372 dataViewCtrlPtr->SetDeleting(true);
373 errorStatus = m_dataViewControlPtr->RemoveItem(reinterpret_cast<DataBrowserItemID>(parent.GetID()),&itemID);
374 // enable automatic updating again:
375 dataViewCtrlPtr->SetDeleting(false);
376 return (errorStatus == noErr);
377 }
378 else
379 return false;
380 }
381
382 virtual bool ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& items)
383 {
384 bool noFailureFlag;
385
386 DataBrowserItemID* itemIDs;
387
388 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(m_dataViewControlPtr->GetWXPeer()));
389
390 size_t noOfEntries;
391
392
393 wxCHECK_MSG(dataViewCtrlPtr != NULL,false,_("Data view control is not correctly initialized"));
394 // convert all valid data view items to data browser items:
395 itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
396 // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
397 // not to be identical because the being edited item might be below the passed item in the hierarchy);
398 // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
399 // has been started and that variables can currently not be updated even when requested by the system:
400 dataViewCtrlPtr->SetDeleting(true);
401 // insert all valid items into control:
402 noFailureFlag = ((noOfEntries == 0) ||
403 !(parent.IsOk()) && (m_dataViewControlPtr->RemoveItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
404 parent.IsOk() && (m_dataViewControlPtr->RemoveItems(reinterpret_cast<DataBrowserItemID>(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
405 // enable automatic updating again:
406 dataViewCtrlPtr->SetDeleting(false);
407 // give allocated array space free again:
408 delete[] itemIDs;
409 // done:
410 return noFailureFlag;
411 }
412
413 virtual bool ValueChanged(wxDataViewItem const& item, unsigned int col)
414 {
415 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
416 DataBrowserItemID parentID;
417
418 DataBrowserPropertyID propertyID;
419
420 wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast<wxDataViewCtrl*>(m_dataViewControlPtr->GetWXPeer()));
421
422
423 wxCHECK_MSG(item.IsOk(), false,_("Passed item is invalid."));
424 wxCHECK_MSG(this->GetOwner() != NULL,false,_("Owner not initialized."));
425 wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Control is wrongly initialized."));
426 parentID = reinterpret_cast<DataBrowserItemID>(this->GetOwner()->GetParent(item).GetID());
427 if ((m_dataViewControlPtr->GetPropertyID(col,&propertyID) == noErr) &&
428 (m_dataViewControlPtr->UpdateItems(parentID,1,&itemID,dataViewCtrlPtr->GetColumn(col)->GetPropertyID(),propertyID) == noErr))
429 {
430 wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId());
431
432 dataViewEvent.SetEventObject(dataViewCtrlPtr);
433 dataViewEvent.SetColumn(col);
434 dataViewEvent.SetItem(item);
435 // send the equivalent wxWidget event:
436 dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
437 // done
438 return true;
439 }
440 else
441 return false;
442 }
443
444 virtual bool Cleared()
445 {
446 bool noFailureFlag = (m_dataViewControlPtr->RemoveItems() == noErr);
447 wxDataViewItem item;
448 wxDataViewItemArray array;
449 GetOwner()->GetChildren( item, array );
450 ItemsAdded( item, array );
451 m_dataViewControlPtr->SetScrollPosition(0, 0);
452 return noFailureFlag;
453 }
454
455 virtual void Resort()
456 {
457 m_dataViewControlPtr->Resort();
458 }
459
460 private:
461 wxMacDataViewDataBrowserListViewControl* m_dataViewControlPtr;
462 };
463
464 // ---------------------------------------------------------
465 // wxDataViewRenderer
466 // ---------------------------------------------------------
467 wxDataViewRenderer::wxDataViewRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
468 :wxDataViewRendererBase(varianttype,mode,align), m_alignment(align), m_mode(mode)
469 {
470 }
471
472 void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
473 {
474 wxDataViewColumn* dataViewColumnPtr;
475
476
477 m_mode = mode;
478 dataViewColumnPtr = this->GetOwner();
479 if (dataViewColumnPtr != NULL)
480 {
481 wxDataViewCtrl* dataViewCtrlPtr(dataViewColumnPtr->GetOwner());
482
483 if (dataViewCtrlPtr != NULL)
484 {
485 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
486
487 if (macDataViewListCtrlPtr != NULL)
488 {
489 DataBrowserPropertyFlags flags;
490
491 verify_noerr(macDataViewListCtrlPtr->GetPropertyFlags(dataViewColumnPtr->GetPropertyID(),&flags));
492 if (mode == wxDATAVIEW_CELL_EDITABLE)
493 flags |= kDataBrowserPropertyIsEditable;
494 else
495 flags &= ~kDataBrowserPropertyIsEditable;
496 verify_noerr(macDataViewListCtrlPtr->SetPropertyFlags(dataViewColumnPtr->GetPropertyID(),flags));
497 }
498 }
499 }
500 }
501
502 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
503
504 // ---------------------------------------------------------
505 // wxDataViewCustomRenderer
506 // ---------------------------------------------------------
507 wxDataViewCustomRenderer::wxDataViewCustomRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
508 :wxDataViewRenderer(varianttype,mode,align), m_editorCtrlPtr(NULL), m_DCPtr(NULL)
509 {
510 }
511
512 wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
513 {
514 delete m_DCPtr;
515 }
516
517 void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, wxRect cell, wxDC *dc, int state )
518 {
519 wxDataViewCtrl *view = GetOwner()->GetOwner();
520 // wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : view->GetForegroundColour();
521 wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? *wxWHITE : view->GetForegroundColour();
522 dc->SetTextForeground(col);
523 dc->DrawText( text, cell.x + xoffset, cell.y + ((cell.height - dc->GetCharHeight()) / 2));
524 }
525
526 wxDC* wxDataViewCustomRenderer::GetDC()
527 {
528 if (m_DCPtr == NULL)
529 {
530 if ((GetOwner() == NULL) || (GetOwner()->GetOwner() == NULL))
531 return NULL;
532 m_DCPtr = new wxWindowDC(this->GetOwner()->GetOwner());
533 }
534 return m_DCPtr;
535 }
536
537 bool wxDataViewCustomRenderer::Render()
538 {
539 return true;
540 }
541
542 void wxDataViewCustomRenderer::SetDC(wxDC* newDCPtr)
543 {
544 delete m_DCPtr;
545 m_DCPtr = newDCPtr;
546 }
547
548 WXDataBrowserPropertyType wxDataViewCustomRenderer::GetPropertyType() const
549 {
550 return kDataBrowserCustomType;
551 }
552
553 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
554
555 // ---------------------------------------------------------
556 // wxDataViewTextRenderer
557 // ---------------------------------------------------------
558 wxDataViewTextRenderer::wxDataViewTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
559 :wxDataViewRenderer(varianttype,mode,align)
560 {
561 }
562
563 bool wxDataViewTextRenderer::Render()
564 {
565 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Text renderer cannot render value; value type: ")) << this->GetValue().GetType());
566
567 wxCFStringRef cfString(this->GetValue().GetString(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
568 return (::SetDataBrowserItemDataText(this->GetDataReference(),cfString) == noErr);
569 }
570
571 WXDataBrowserPropertyType wxDataViewTextRenderer::GetPropertyType() const
572 {
573 return kDataBrowserTextType;
574 }
575
576 IMPLEMENT_CLASS(wxDataViewTextRenderer,wxDataViewRenderer)
577
578 // ---------------------------------------------------------
579 // wxDataViewTextRendererAttr
580 // ---------------------------------------------------------
581 wxDataViewTextRendererAttr::wxDataViewTextRendererAttr(wxString const& varianttype, wxDataViewCellMode mode, int align)
582 :wxDataViewTextRenderer(varianttype,mode,align)
583 {
584 }
585
586 IMPLEMENT_CLASS(wxDataViewTextRendererAttr,wxDataViewTextRenderer)
587
588 // ---------------------------------------------------------
589 // wxDataViewBitmapRenderer
590 // ---------------------------------------------------------
591 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
592 :wxDataViewRenderer(varianttype,mode,align)
593 {
594 }
595
596 bool wxDataViewBitmapRenderer::Render()
597 // This method returns 'true' if
598 // - the passed bitmap is valid and it could be assigned to the native data browser;
599 // - the passed bitmap is invalid (or is not initialized); this case simulates a non-existing bitmap.
600 // In all other cases the method returns 'false'.
601 {
602 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Bitmap renderer cannot render value; value type: ")) << this->GetValue().GetType());
603
604 wxBitmap bitmap;
605
606 bitmap << this->GetValue();
607 if (bitmap.Ok())
608 return (::SetDataBrowserItemDataIcon(this->GetDataReference(),bitmap.GetIconRef()) == noErr);
609 else
610 return true;
611 }
612
613 WXDataBrowserPropertyType wxDataViewBitmapRenderer::GetPropertyType() const
614 {
615 return kDataBrowserIconType;
616 }
617
618 IMPLEMENT_CLASS(wxDataViewBitmapRenderer,wxDataViewRenderer)
619
620 // ---------------------------------------------------------
621 // wxDataViewIconTextRenderer
622 // ---------------------------------------------------------
623 wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
624 :wxDataViewRenderer(varianttype,mode)
625 {
626 }
627
628 bool wxDataViewIconTextRenderer::Render()
629 {
630 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Icon & text renderer cannot render value; value type: ")) << this->GetValue().GetType());
631
632 wxDataViewIconText iconText;
633
634 iconText << this->GetValue();
635
636 wxCFStringRef cfString(iconText.GetText(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
637
638 if (iconText.GetIcon().IsOk())
639 if (::SetDataBrowserItemDataIcon(this->GetDataReference(),MAC_WXHICON(iconText.GetIcon().GetHICON())) != noErr)
640 return false;
641 return (::SetDataBrowserItemDataText(this->GetDataReference(),cfString) == noErr);
642 }
643
644 WXDataBrowserPropertyType wxDataViewIconTextRenderer::GetPropertyType() const
645 {
646 return kDataBrowserIconAndTextType;
647 }
648
649 IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
650
651
652 // ---------------------------------------------------------
653 // wxDataViewToggleRenderer
654 // ---------------------------------------------------------
655 wxDataViewToggleRenderer::wxDataViewToggleRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
656 :wxDataViewRenderer(varianttype,mode)
657 {
658 }
659
660 bool wxDataViewToggleRenderer::Render()
661 {
662 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Toggle renderer cannot render value; value type: ")) << this->GetValue().GetType());
663 return (::SetDataBrowserItemDataButtonValue(this->GetDataReference(),this->GetValue().GetBool()) == noErr);
664 }
665
666 WXDataBrowserPropertyType wxDataViewToggleRenderer::GetPropertyType() const
667 {
668 return kDataBrowserCheckboxType;
669 }
670
671 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer,wxDataViewRenderer)
672
673 // ---------------------------------------------------------
674 // wxDataViewProgressRenderer
675 // ---------------------------------------------------------
676 wxDataViewProgressRenderer::wxDataViewProgressRenderer(wxString const& label, wxString const& varianttype, wxDataViewCellMode mode, int align)
677 :wxDataViewRenderer(varianttype,mode,align)
678 {
679 }
680
681 bool wxDataViewProgressRenderer::Render()
682 {
683 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Progress renderer cannot render value type; value type: ")) << this->GetValue().GetType());
684 return ((::SetDataBrowserItemDataMinimum(this->GetDataReference(), 0) == noErr) &&
685 (::SetDataBrowserItemDataMaximum(this->GetDataReference(),100) == noErr) &&
686 (::SetDataBrowserItemDataValue (this->GetDataReference(),this->GetValue().GetLong()) == noErr));
687 }
688
689 WXDataBrowserPropertyType wxDataViewProgressRenderer::GetPropertyType() const
690 {
691 return kDataBrowserProgressBarType;
692 }
693
694 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer,wxDataViewRenderer)
695
696 // ---------------------------------------------------------
697 // wxDataViewDateRenderer
698 // ---------------------------------------------------------
699 wxDataViewDateRenderer::wxDataViewDateRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
700 :wxDataViewRenderer(varianttype,mode,align)
701 {
702 }
703
704 bool wxDataViewDateRenderer::Render()
705 {
706 wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Date renderer cannot render value; value type: ")) << this->GetValue().GetType());
707 return (::SetDataBrowserItemDataDateTime(this->GetDataReference(),this->GetValue().GetDateTime().Subtract(wxDateTime(1,wxDateTime::Jan,1904)).GetSeconds().GetLo()) == noErr);
708 }
709
710 WXDataBrowserPropertyType wxDataViewDateRenderer::GetPropertyType() const
711 {
712 return kDataBrowserDateTimeType;
713 }
714
715 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer,wxDataViewRenderer)
716
717 // ---------------------------------------------------------
718 // wxDataViewColumn
719 // ---------------------------------------------------------
720
721 void wxDataViewColumn::SetAlignment(wxAlignment align)
722 {
723 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
724
725
726 m_alignment = align;
727 if (dataViewCtrlPtr != NULL)
728 {
729 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
730
731 if (macDataViewListCtrlPtr != NULL)
732 {
733 DataBrowserListViewHeaderDesc headerDescription;
734
735 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
736 switch (align)
737 {
738 case wxALIGN_CENTER:
739 case wxALIGN_CENTER_HORIZONTAL:
740 headerDescription.btnFontStyle.just = teCenter;
741 break;
742 case wxALIGN_LEFT:
743 headerDescription.btnFontStyle.just = teFlushLeft;
744 break;
745 case wxALIGN_RIGHT:
746 headerDescription.btnFontStyle.just = teFlushRight;
747 break;
748 default:
749 headerDescription.btnFontStyle.just = teFlushDefault;
750 }
751 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set alignment."));
752 }
753 }
754 }
755
756 void wxDataViewColumn::SetBitmap(wxBitmap const& bitmap)
757 {
758 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
759
760
761 wxDataViewColumnBase::SetBitmap(bitmap);
762 if (dataViewCtrlPtr != NULL)
763 {
764 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
765
766 if (macDataViewListCtrlPtr != NULL)
767 {
768 DataBrowserListViewHeaderDesc headerDescription;
769
770 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
771 if (this->GetBitmap().Ok())
772 headerDescription.btnContentInfo.u.iconRef = this->GetBitmap().GetIconRef();
773 else
774 headerDescription.btnContentInfo.u.iconRef = NULL;
775 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set icon."));
776 }
777 }
778 }
779
780 void wxDataViewColumn::SetMaxWidth(int maxWidth)
781 {
782 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
783
784
785 m_maxWidth = maxWidth;
786 if (dataViewCtrlPtr != NULL)
787 {
788 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
789
790 if (macDataViewListCtrlPtr != NULL)
791 {
792 DataBrowserListViewHeaderDesc headerDescription;
793
794 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
795 headerDescription.maximumWidth = static_cast<UInt16>(maxWidth);
796 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set maximum width."));
797 }
798 }
799 }
800
801 void wxDataViewColumn::SetMinWidth(int minWidth)
802 {
803 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
804
805
806 m_minWidth = minWidth;
807 if (dataViewCtrlPtr != NULL)
808 {
809 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
810
811 if (macDataViewListCtrlPtr != NULL)
812 {
813 DataBrowserListViewHeaderDesc headerDescription;
814
815 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
816 headerDescription.minimumWidth = static_cast<UInt16>(minWidth);
817 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set minimum width."));
818 }
819 }
820 }
821
822 void wxDataViewColumn::SetReorderable(bool reorderable)
823 {
824 // first set the internal flag of the column:
825 if (reorderable)
826 m_flags |= wxDATAVIEW_COL_REORDERABLE;
827 else
828 m_flags &= ~wxDATAVIEW_COL_REORDERABLE;
829 // if the column is associated with a control change also immediately the flags of the control:
830 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
831
832 if (dataViewCtrlPtr != NULL)
833 {
834 DataBrowserPropertyFlags flags;
835 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
836
837 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
838 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(this->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
839 if (reorderable)
840 flags |= kDataBrowserListViewMovableColumn;
841 else
842 flags &= ~kDataBrowserListViewMovableColumn;
843 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(this->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
844 }
845 }
846
847 void wxDataViewColumn::SetResizeable(bool resizeable)
848 {
849 // first set the internal flag of the column:
850 if (resizeable)
851 m_flags |= wxDATAVIEW_COL_RESIZABLE;
852 else
853 m_flags &= ~wxDATAVIEW_COL_RESIZABLE;
854 // if the column is associated with a control change also immediately the flags of the control:
855 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
856
857 if (dataViewCtrlPtr != NULL)
858 {
859 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
860
861 if (macDataViewListCtrlPtr != NULL)
862 {
863 DataBrowserListViewHeaderDesc headerDescription;
864
865 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription));
866 if (resizeable) {
867 headerDescription.minimumWidth = 0;
868 headerDescription.maximumWidth = 30000;
869 }
870 else {
871 headerDescription.minimumWidth = m_width;
872 headerDescription.maximumWidth = m_width;
873 }
874 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription));
875 macDataViewListCtrlPtr->SetSortProperty(this->GetPropertyID());
876 }
877 }
878 }
879
880 void wxDataViewColumn::SetSortable(bool sortable)
881 {
882 // first set the internal flag of the column:
883 if (sortable)
884 m_flags |= wxDATAVIEW_COL_SORTABLE;
885 else
886 m_flags &= ~wxDATAVIEW_COL_SORTABLE;
887 // if the column is associated with a control change also immediately the flags of the control:
888 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
889
890 if (dataViewCtrlPtr != NULL)
891 {
892 DataBrowserPropertyFlags flags;
893 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
894
895 wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
896 wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(this->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
897 if (sortable)
898 flags |= kDataBrowserListViewSortableColumn;
899 else
900 flags &= ~kDataBrowserListViewSortableColumn;
901 wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(this->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
902 }
903 }
904
905 void wxDataViewColumn::SetSortOrder(bool ascending)
906 {
907 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
908
909
910 m_ascending = ascending;
911 if (dataViewCtrlPtr != NULL)
912 {
913 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
914
915 if (macDataViewListCtrlPtr != NULL)
916 {
917 DataBrowserListViewHeaderDesc headerDescription;
918
919 verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription));
920 if (ascending)
921 headerDescription.initialOrder = kDataBrowserOrderIncreasing;
922 else
923 headerDescription.initialOrder = kDataBrowserOrderDecreasing;
924 verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription));
925 macDataViewListCtrlPtr->SetSortProperty(this->GetPropertyID());
926 }
927 }
928 }
929
930 void wxDataViewColumn::SetTitle(wxString const& title)
931 {
932 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
933
934
935 m_title = title;
936 if (dataViewCtrlPtr != NULL)
937 {
938 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
939
940 if (macDataViewListCtrlPtr != NULL)
941 {
942 DataBrowserListViewHeaderDesc headerDescription;
943 wxCFStringRef cfTitle(title,(dataViewCtrlPtr->GetFont().Ok() ? dataViewCtrlPtr->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
944
945 wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
946 headerDescription.titleString = cfTitle;
947 wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set header description."));
948 }
949 }
950 }
951
952 void wxDataViewColumn::SetWidth(int width)
953 {
954 wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
955
956
957 if ((width >= m_minWidth) && (width <= m_maxWidth))
958 {
959 m_width = width;
960 if (dataViewCtrlPtr != NULL)
961 {
962 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(dataViewCtrlPtr->GetPeer()));
963
964 if (macDataViewListCtrlPtr != NULL)
965 wxCHECK_RET(macDataViewListCtrlPtr->SetColumnWidth(this->GetPropertyID(),static_cast<UInt16>(width)) == noErr,_("Could not set column width."));
966 }
967 }
968 }
969
970 void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
971 {
972 // see wxGTK native wxDataViewColumn implementation
973 wxFAIL_MSG( "not implemented" );
974 }
975
976 bool wxDataViewColumn::IsSortKey() const
977 {
978 wxDataViewCtrl * const dataViewCtrlPtr(GetOwner());
979 wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(
980 dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(
981 dataViewCtrlPtr->GetPeer()));
982
983 DataBrowserPropertyID propertyID;
984 return macDataViewListCtrlPtr->GetSortProperty(&propertyID) == noErr &&
985 propertyID == m_propertyID;
986 }
987
988 //-----------------------------------------------------------------------------
989 // wxDataViewCtrl
990 //-----------------------------------------------------------------------------
991
992
993 wxDataViewCtrl::~wxDataViewCtrl()
994 {
995 ClearColumns();
996 }
997
998 void wxDataViewCtrl::Init()
999 {
1000 m_CustomRendererPtr = NULL;
1001 m_Deleting = false;
1002 m_macIsUserPane = false;
1003 m_cgContext = NULL;
1004 }
1005
1006 bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator )
1007 {
1008 if (!(this->wxControl::Create(parent,id,pos,size,style & ~(wxHSCROLL | wxVSCROLL),validator)))
1009 return false;
1010
1011 #ifdef __WXMAC__
1012 MacSetClipChildren(true) ;
1013 #endif
1014
1015 m_peer = new wxMacDataViewDataBrowserListViewControl(this,pos,size,style);
1016
1017 if ( style & wxBORDER_NONE )
1018 m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean) false ) ;
1019
1020 this->MacPostControlCreate(pos,size);
1021 ::SetAutomaticControlDragTrackingEnabledForWindow(::GetControlOwner(m_peer->GetControlRef()),true);
1022
1023 InstallControlEventHandler(m_peer->GetControlRef(),GetwxMacDataViewCtrlEventHandlerUPP(),GetEventTypeCount(eventList),eventList,this,NULL);
1024
1025 ::SetDataBrowserTableViewHiliteStyle( m_peer->GetControlRef(), kDataBrowserTableViewFillHilite );
1026
1027 return true;
1028 }
1029
1030 wxSize wxDataViewCtrl::DoGetBestSize() const
1031 {
1032 wxSize best = wxControl::DoGetBestSize();
1033 best.y = 80;
1034
1035 return best;
1036 }
1037
1038 /*static*/
1039 wxVisualAttributes wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
1040 {
1041 wxVisualAttributes attr;
1042
1043 attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
1044 attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
1045 //attr.font.MacCreateFromThemeFont(kThemeViewsFont);
1046
1047 return attr;
1048 }
1049
1050 bool wxDataViewCtrl::AssociateModel(wxDataViewModel* model)
1051 {
1052 if (!wxDataViewCtrlBase::AssociateModel(model))
1053 return false;
1054
1055 model->AddNotifier(new wxMacDataViewModelNotifier(dynamic_cast<wxMacDataViewDataBrowserListViewControl*>(m_peer)));
1056
1057 return true;
1058 }
1059
1060 bool wxDataViewCtrl::AppendColumn(wxDataViewColumn* columnPtr)
1061 {
1062 return wxDataViewCtrl::InsertColumn( GetColumnCount(), columnPtr );
1063 }
1064
1065 bool wxDataViewCtrl::PrependColumn(wxDataViewColumn* columnPtr)
1066 {
1067 return wxDataViewCtrl::InsertColumn( 0, columnPtr );
1068 }
1069
1070 bool wxDataViewCtrl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
1071 {
1072 DataBrowserListViewColumnDesc columnDescription;
1073
1074 DataBrowserPropertyID NewPropertyID;
1075
1076 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1077
1078 wxCFStringRef title(columnPtr->GetTitle(),m_font.Ok() ? this->GetFont().GetEncoding() : wxLocale::GetSystemEncoding());
1079
1080
1081 // first, some error checking:
1082 wxCHECK_MSG(MacDataViewListCtrlPtr != NULL, false,_("m_peer is not or incorrectly initialized"));
1083 wxCHECK_MSG(columnPtr != NULL, false,_("Column pointer must not be NULL."));
1084 wxCHECK_MSG(columnPtr->GetRenderer() != NULL, false,_("Column does not have a renderer."));
1085 wxCHECK_MSG(this->GetModel() != NULL, false,_("No model associated with control."));
1086 wxCHECK_MSG((columnPtr->GetModelColumn() >= 0) &&
1087 (columnPtr->GetModelColumn() < this->GetModel()->GetColumnCount()),false,_("Column's model column has no equivalent in the associated model."));
1088
1089 // try to get new ID for the column:
1090 wxCHECK_MSG(MacDataViewListCtrlPtr->GetFreePropertyID(&NewPropertyID) == noErr,false,_("Cannot create new column's ID. Probably max. number of columns reached."));
1091 // full column variable initialization:
1092 columnPtr->SetPropertyID(NewPropertyID);
1093 // add column to wxWidget's internal structure:
1094 wxCHECK_MSG(this->wxDataViewCtrlBase::InsertColumn(pos,columnPtr) &&
1095 m_ColumnPointers.insert(ColumnPointerHashMapType::value_type(NewPropertyID,columnPtr)).second,false,_("Could not add column to internal structures."));
1096 // create a column description and add column to the native control:
1097 wxCHECK_MSG(::InitializeColumnDescription(columnDescription,columnPtr,NewPropertyID,title), false,_("Column description could not be initialized."));
1098 wxCHECK_MSG(MacDataViewListCtrlPtr->AddColumn(&columnDescription,pos) == noErr,false,_("Column could not be added."));
1099
1100 // final adjustments for the layout:
1101 wxCHECK_MSG(MacDataViewListCtrlPtr->SetColumnWidth(NewPropertyID,columnPtr->GetWidth()) == noErr,false,_("Column width could not be set."));
1102
1103 // make sure that the data is up-to-date...
1104 // if the newly appended column is the first column add the initial data to the control and mark the column as an expander column,
1105 // otherwise ask the control to 'update' the data in the newly appended column:
1106 if (this->GetColumnCount() == 1)
1107 {
1108 this->SetExpanderColumn(columnPtr);
1109 this->AddChildrenLevel(wxDataViewItem());
1110 }
1111 else
1112 MacDataViewListCtrlPtr->UpdateItems(kDataBrowserNoItem,0,NULL,kDataBrowserItemNoProperty,NewPropertyID);
1113 // done:
1114 return true;
1115 }
1116
1117 bool wxDataViewCtrl::ClearColumns()
1118 {
1119 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1120
1121
1122 while (m_ColumnPointers.begin() != m_ColumnPointers.end())
1123 {
1124 wxCHECK_MSG(MacDataViewListCtrlPtr->RemoveColumnByProperty(m_ColumnPointers.begin()->first) == noErr,false,_("Could not remove column."));
1125 delete m_ColumnPointers.begin()->second;
1126 m_ColumnPointers.erase(m_ColumnPointers.begin());
1127 }
1128 return true;
1129 }
1130
1131 bool wxDataViewCtrl::DeleteColumn(wxDataViewColumn* columnPtr)
1132 {
1133 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1134
1135
1136 if ((MacDataViewListCtrlPtr->RemoveColumnByProperty(columnPtr->GetPropertyID()) == noErr) && (m_ColumnPointers.erase(columnPtr->GetPropertyID()) > 0))
1137 {
1138 delete columnPtr;
1139 return true;
1140 }
1141 else
1142 return false;
1143 }
1144
1145 wxDataViewColumn* wxDataViewCtrl::GetColumn(unsigned int pos) const
1146 {
1147 DataBrowserPropertyID propertyID;
1148
1149 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1150
1151
1152 if (MacDataViewListCtrlPtr->GetPropertyID(pos,&propertyID) == noErr)
1153 {
1154 ColumnPointerHashMapType::const_iterator Result(m_ColumnPointers.find(propertyID));
1155
1156 if (Result != m_ColumnPointers.end())
1157 return Result->second;
1158 else
1159 return NULL;
1160 }
1161 else
1162 return NULL;
1163 }
1164
1165 unsigned int wxDataViewCtrl::GetColumnCount() const
1166 {
1167 return m_ColumnPointers.size();
1168 }
1169
1170 int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
1171 {
1172 if (columnPtr != NULL)
1173 {
1174 DataBrowserTableViewColumnIndex Position;
1175 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1176
1177 wxCHECK_MSG(MacDataViewListCtrlPtr->GetColumnIndex(columnPtr->GetPropertyID(),&Position) == noErr,-1,_("Could not determine column's position"));
1178 return static_cast<int>(Position);
1179 }
1180 else
1181 return wxNOT_FOUND;
1182 }
1183
1184 void wxDataViewCtrl::Collapse(wxDataViewItem const& item)
1185 {
1186 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1187
1188
1189 MacDataViewListCtrlPtr->CloseContainer(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1190 }
1191
1192 void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
1193 {
1194 ExpandAncestors(item);
1195
1196 if (item.IsOk())
1197 {
1198 DataBrowserPropertyID propertyID;
1199 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1200
1201 if (columnPtr != NULL)
1202 propertyID = columnPtr->GetPropertyID();
1203 else
1204 propertyID = kDataBrowserNoItem;
1205 MacDataViewListCtrlPtr->RevealItem(reinterpret_cast<DataBrowserItemID>(item.GetID()),propertyID,kDataBrowserRevealOnly);
1206 }
1207 }
1208
1209 void wxDataViewCtrl::Expand(wxDataViewItem const& item)
1210 {
1211 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1212
1213
1214 MacDataViewListCtrlPtr->OpenContainer(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1215 }
1216
1217 bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
1218 {
1219 if (item.IsOk())
1220 {
1221 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1222
1223 DataBrowserItemState state = 0;
1224 OSStatus err = ::GetDataBrowserItemState(
1225 MacDataViewListCtrlPtr->GetControlRef(),
1226 reinterpret_cast<DataBrowserItemID>(item.GetID()),
1227 &state );
1228 if ((err == 0) && (state & kDataBrowserContainerIsOpen))
1229 return true;
1230 }
1231 return false;
1232 }
1233
1234 wxDataViewColumn* wxDataViewCtrl::GetSortingColumn() const
1235 {
1236 DataBrowserPropertyID propertyID;
1237
1238 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1239
1240
1241 if (MacDataViewListCtrlPtr->GetSortProperty(&propertyID) == noErr)
1242 return this->GetColumnPtr(propertyID);
1243 else
1244 return NULL;
1245 }
1246
1247 unsigned int wxDataViewCtrl::GetCount() const
1248 {
1249 ItemCount noOfItems;
1250
1251
1252 wxCHECK_MSG(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer)->GetItemCount(&noOfItems) == noErr,0,_("Could not determine number of items"));
1253 return noOfItems;
1254 }
1255
1256 wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
1257 {
1258 if (item.IsOk() && (columnPtr != NULL))
1259 {
1260 Rect MacRectangle;
1261 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1262
1263 if (MacDataViewListCtrlPtr->GetPartBounds(reinterpret_cast<DataBrowserItemID>(item.GetID()),columnPtr->GetPropertyID(),kDataBrowserPropertyContentPart,&MacRectangle) == noErr)
1264 {
1265 wxRect rectangle;
1266
1267 ::wxMacNativeToRect(&MacRectangle,&rectangle);
1268 return rectangle;
1269 }
1270 else
1271 return wxRect();
1272 }
1273 else
1274 return wxRect();
1275 }
1276
1277 wxDataViewItem wxDataViewCtrl::GetSelection() const
1278 {
1279 wxArrayDataBrowserItemID itemIDs;
1280
1281 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1282
1283
1284 if (MacDataViewListCtrlPtr->GetSelectedItemIDs(itemIDs) > 0)
1285 return wxDataViewItem(reinterpret_cast<void*>(itemIDs[0]));
1286 else
1287 return wxDataViewItem();
1288 }
1289
1290 int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const
1291 {
1292 size_t NoOfSelectedItems;
1293
1294 wxArrayDataBrowserItemID itemIDs;
1295
1296 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1297
1298
1299 NoOfSelectedItems = MacDataViewListCtrlPtr->GetSelectedItemIDs(itemIDs);
1300 sel.Empty();
1301 sel.SetCount(NoOfSelectedItems);
1302 for (size_t i=0; i<NoOfSelectedItems; ++i)
1303 sel[i] = wxDataViewItem(reinterpret_cast<void*>(itemIDs[i]));
1304 return static_cast<int>(NoOfSelectedItems);
1305 }
1306
1307 void wxDataViewCtrl::HitTest(wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const
1308 {
1309 item = wxDataViewItem();
1310 columnPtr = NULL;
1311 }
1312
1313 bool wxDataViewCtrl::IsSelected(wxDataViewItem const& item) const
1314 {
1315 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1316
1317
1318 return MacDataViewListCtrlPtr->IsItemSelected(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1319 }
1320
1321 void wxDataViewCtrl::SelectAll()
1322 {
1323 DataBrowserItemID* itemIDPtr;
1324
1325 Handle handle(::NewHandle(0));
1326
1327 size_t NoOfItems;
1328
1329 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1330
1331
1332 wxCHECK_RET(MacDataViewListCtrlPtr->GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1333 NoOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1334 HLock(handle);
1335 itemIDPtr = (DataBrowserItemID*) (*handle);
1336 MacDataViewListCtrlPtr->SetSelectedItems(NoOfItems,itemIDPtr,kDataBrowserItemsAssign);
1337 HUnlock(handle);
1338 DisposeHandle(handle);
1339 }
1340
1341 void wxDataViewCtrl::Select(wxDataViewItem const& item)
1342 {
1343 if (item.IsOk())
1344 {
1345 ExpandAncestors(item);
1346
1347 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1348 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1349
1350 MacDataViewListCtrlPtr->SetSelectedItems(1,&itemID,kDataBrowserItemsAdd);
1351 }
1352 }
1353
1354 void wxDataViewCtrl::SetSelections(wxDataViewItemArray const& sel)
1355 {
1356 size_t const NoOfSelections = sel.GetCount();
1357
1358 wxDataViewItem last_parent;
1359
1360 size_t i;
1361 for (i = 0; i < NoOfSelections; i++)
1362 {
1363 wxDataViewItem item = sel[i];
1364 wxDataViewItem parent = GetModel()->GetParent( item );
1365 if (parent)
1366 {
1367 if (parent != last_parent)
1368 ExpandAncestors(item);
1369 }
1370 last_parent = parent;
1371 }
1372
1373 DataBrowserItemID* itemIDs;
1374 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1375
1376 itemIDs = new DataBrowserItemID[NoOfSelections];
1377 for (i=0; i<NoOfSelections; ++i)
1378 itemIDs[i] = reinterpret_cast<DataBrowserItemID>(sel[i].GetID());
1379 MacDataViewListCtrlPtr->SetSelectedItems(NoOfSelections,itemIDs,kDataBrowserItemsAssign);
1380 delete[] itemIDs;
1381 }
1382
1383 void wxDataViewCtrl::Unselect(wxDataViewItem const& item)
1384 {
1385 if (item.IsOk())
1386 {
1387 DataBrowserItemID itemID(reinterpret_cast<DataBrowserItemID>(item.GetID()));
1388 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1389
1390 MacDataViewListCtrlPtr->SetSelectedItems(1,&itemID,kDataBrowserItemsRemove);
1391 }
1392 }
1393
1394 void wxDataViewCtrl::UnselectAll()
1395 {
1396 DataBrowserItemID* itemIDPtr;
1397
1398 Handle handle(::NewHandle(0));
1399
1400 size_t NoOfItems;
1401
1402 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1403
1404
1405 wxCHECK_RET(MacDataViewListCtrlPtr->GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
1406 NoOfItems = static_cast<size_t>(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
1407 HLock(handle);
1408 itemIDPtr = (DataBrowserItemID*) (*handle);
1409 MacDataViewListCtrlPtr->SetSelectedItems(NoOfItems,itemIDPtr,kDataBrowserItemsRemove);
1410 HUnlock(handle);
1411 DisposeHandle(handle);
1412 }
1413
1414 // data handling:
1415 void wxDataViewCtrl::AddChildrenLevel(wxDataViewItem const& parentItem)
1416 {
1417 int NoOfChildren;
1418
1419 wxDataViewItemArray items;
1420
1421
1422 wxCHECK_RET(this->GetModel() != NULL,_("Model pointer not initialized."));
1423 NoOfChildren = this->GetModel()->GetChildren(parentItem,items);
1424 #if 0
1425 for (int i=0; i<NoOfChildren; ++i)
1426 (void) this->GetModel()->ItemAdded(parentItem,items[i]);
1427 #else
1428 (void) this->GetModel()->ItemsAdded(parentItem,items);
1429 #endif
1430 }
1431
1432 void wxDataViewCtrl::FinishCustomItemEditing()
1433 {
1434 if (this->GetCustomRendererItem().IsOk())
1435 {
1436 this->GetCustomRendererPtr()->FinishEditing();
1437 this->SetCustomRendererItem(wxDataViewItem());
1438 this->SetCustomRendererPtr (NULL);
1439 }
1440 }
1441
1442 wxDataViewColumn* wxDataViewCtrl::GetColumnPtr(WXDataBrowserPropertyID propertyID) const
1443 {
1444 ColumnPointerHashMapType::const_iterator Result(m_ColumnPointers.find(propertyID));
1445
1446 if (Result != m_ColumnPointers.end())
1447 return Result->second;
1448 else
1449 return NULL;
1450 }
1451
1452 // inherited methods from wxDataViewCtrlBase
1453 void wxDataViewCtrl::DoSetExpanderColumn()
1454 {
1455 if (this->GetExpanderColumn() != NULL)
1456 {
1457 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1458
1459 (void) MacDataViewListCtrlPtr->SetDisclosureColumn(this->GetExpanderColumn()->GetPropertyID(),false); // second parameter explicitely passed to ensure that arrow is centered
1460 }
1461 }
1462
1463 void wxDataViewCtrl::DoSetIndent()
1464 {
1465 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1466
1467 (void) MacDataViewListCtrlPtr->SetIndent(static_cast<float>(this->GetIndent()));
1468 }
1469
1470 // event handling:
1471 void wxDataViewCtrl::OnMouse(wxMouseEvent& event)
1472 {
1473 event.Skip();
1474
1475 if (GetModel() == NULL)
1476 return;
1477
1478 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1479
1480 int NoOfChildren;
1481 wxDataViewItemArray items;
1482 NoOfChildren = GetModel()->GetChildren( wxDataViewItem(), items);
1483 if (NoOfChildren == 0)
1484 return;
1485 wxDataViewItem firstChild = items[0];
1486
1487 UInt16 headerHeight = 0;
1488 MacDataViewListCtrlPtr->GetHeaderButtonHeight(&headerHeight);
1489
1490
1491 if (event.GetY() < headerHeight)
1492 {
1493 unsigned int col_count = GetColumnCount();
1494 unsigned int col;
1495 for (col = 0; col < col_count; col++)
1496 {
1497 wxDataViewColumn *column = GetColumn( col );
1498 if (column->IsHidden())
1499 continue;
1500
1501 Rect itemrect;
1502 ::GetDataBrowserItemPartBounds( MacDataViewListCtrlPtr->GetControlRef(),
1503 reinterpret_cast<DataBrowserItemID>(firstChild.GetID()), column->GetPropertyID(),
1504 kDataBrowserPropertyEnclosingPart, &itemrect );
1505
1506 if (abs( event.GetX() - itemrect.right) < 3)
1507 {
1508 if (column->GetFlags() & wxDATAVIEW_COL_RESIZABLE)
1509 SetCursor( wxCursor( wxCURSOR_SIZEWE ) );
1510 else
1511 SetCursor( *wxSTANDARD_CURSOR );
1512 return;
1513 }
1514 }
1515
1516 }
1517
1518 SetCursor( *wxSTANDARD_CURSOR );
1519 }
1520
1521 void wxDataViewCtrl::OnSize(wxSizeEvent& event)
1522 {
1523 unsigned int const NoOfColumns = this->GetColumnCount();
1524
1525
1526 for (unsigned int i=0; i<NoOfColumns; ++i)
1527 {
1528 wxDataViewColumn* dataViewColumnPtr(this->GetColumn(i));
1529
1530 if (dataViewColumnPtr != NULL)
1531 {
1532 wxDataViewCustomRenderer* dataViewCustomRendererPtr(dynamic_cast<wxDataViewCustomRenderer*>(dataViewColumnPtr->GetRenderer()));
1533
1534 if (dataViewCustomRendererPtr != NULL)
1535 dataViewCustomRendererPtr->SetDC(NULL); // reset DC because DC has changed
1536 }
1537 }
1538
1539 wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast<wxMacDataViewDataBrowserListViewControlPointer>(m_peer));
1540 ControlRef ref = MacDataViewListCtrlPtr->GetControlRef();
1541 if (NoOfColumns == 1)
1542 {
1543 ::SetDataBrowserHasScrollBars( ref, false, true );
1544 ::AutoSizeDataBrowserListViewColumns( ref );
1545 }
1546 if (NoOfColumns > 1)
1547 {
1548 ::SetDataBrowserHasScrollBars( ref, true, true );
1549 }
1550
1551 event.Skip();
1552 }
1553
1554 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase)
1555
1556 BEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase)
1557 EVT_SIZE(wxDataViewCtrl::OnSize)
1558 EVT_MOTION(wxDataViewCtrl::OnMouse)
1559 END_EVENT_TABLE()
1560
1561 #endif // !wxUSE_GENERICDATAVIEWCTRL
1562
1563 #endif // wxUSE_DATAVIEWCTRL
1564