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