]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listctrl_mac.cpp
9b5bb81a400e93302f296d73bec4bc4fd7923351
[wxWidgets.git] / src / mac / carbon / listctrl_mac.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/listctrl_mac.cpp
3 // Purpose: wxListCtrl
4 // Author: Julian Smart
5 // Modified by: Agron Selimaj
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_LISTCTRL
28
29 #include "wx/listctrl.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #endif
34
35 #include "wx/mac/uma.h"
36
37 #include "wx/imaglist.h"
38 #include "wx/sysopt.h"
39
40 #define wxMAC_ALWAYS_USE_GENERIC_LISTCTRL wxT("mac.listctrl.always_use_generic")
41
42 #if wxUSE_EXTENDED_RTTI
43 WX_DEFINE_FLAGS( wxListCtrlStyle )
44
45 wxBEGIN_FLAGS( wxListCtrlStyle )
46 // new style border flags, we put them first to
47 // use them for streaming out
48 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
49 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
50 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
51 wxFLAGS_MEMBER(wxBORDER_RAISED)
52 wxFLAGS_MEMBER(wxBORDER_STATIC)
53 wxFLAGS_MEMBER(wxBORDER_NONE)
54
55 // old style border flags
56 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
57 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
58 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
59 wxFLAGS_MEMBER(wxRAISED_BORDER)
60 wxFLAGS_MEMBER(wxSTATIC_BORDER)
61 wxFLAGS_MEMBER(wxBORDER)
62
63 // standard window styles
64 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
65 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
66 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
67 wxFLAGS_MEMBER(wxWANTS_CHARS)
68 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
69 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
70 wxFLAGS_MEMBER(wxVSCROLL)
71 wxFLAGS_MEMBER(wxHSCROLL)
72
73 wxFLAGS_MEMBER(wxLC_LIST)
74 wxFLAGS_MEMBER(wxLC_REPORT)
75 wxFLAGS_MEMBER(wxLC_ICON)
76 wxFLAGS_MEMBER(wxLC_SMALL_ICON)
77 wxFLAGS_MEMBER(wxLC_ALIGN_TOP)
78 wxFLAGS_MEMBER(wxLC_ALIGN_LEFT)
79 wxFLAGS_MEMBER(wxLC_AUTOARRANGE)
80 wxFLAGS_MEMBER(wxLC_USER_TEXT)
81 wxFLAGS_MEMBER(wxLC_EDIT_LABELS)
82 wxFLAGS_MEMBER(wxLC_NO_HEADER)
83 wxFLAGS_MEMBER(wxLC_SINGLE_SEL)
84 wxFLAGS_MEMBER(wxLC_SORT_ASCENDING)
85 wxFLAGS_MEMBER(wxLC_SORT_DESCENDING)
86 wxFLAGS_MEMBER(wxLC_VIRTUAL)
87
88 wxEND_FLAGS( wxListCtrlStyle )
89
90 IMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxControl,"wx/listctrl.h")
91
92 wxBEGIN_PROPERTIES_TABLE(wxListCtrl)
93 wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
94
95 wxPROPERTY_FLAGS( WindowStyle , wxListCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
96 wxEND_PROPERTIES_TABLE()
97
98 wxBEGIN_HANDLERS_TABLE(wxListCtrl)
99 wxEND_HANDLERS_TABLE()
100
101 wxCONSTRUCTOR_5( wxListCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
102
103 /*
104 TODO : Expose more information of a list's layout etc. via appropriate objects (à la NotebookPageInfo)
105 */
106 #else
107 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
108 #endif
109
110 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
111 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
112
113 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
114
115 WX_DECLARE_EXPORTED_LIST(wxListItem, wxListItemList);
116 #include "wx/listimpl.cpp"
117 WX_DEFINE_LIST(wxListItemList)
118 WX_DEFINE_LIST(wxColumnList)
119
120 // so we can check for column clicks
121 static const EventTypeSpec eventList[] =
122 {
123 { kEventClassControl, kEventControlHit },
124 { kEventClassControl, kEventControlDraw }
125 };
126
127 static pascal OSStatus wxMacListCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
128 {
129 OSStatus result = eventNotHandledErr ;
130
131 wxMacCarbonEvent cEvent( event ) ;
132
133 ControlRef controlRef ;
134 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
135
136 wxListCtrl *window = (wxListCtrl*) data ;
137 wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, window->GetId() );
138 le.SetEventObject( window );
139
140 switch ( GetEventKind( event ) )
141 {
142 // check if the column was clicked on and fire an event if so
143 case kEventControlHit :
144 {
145 ControlPartCode result = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart, typeControlPartCode) ;
146 if (result == kControlButtonPart){
147 DataBrowserPropertyID col;
148 GetDataBrowserSortProperty(controlRef, &col);
149 int column = col - kMinColumnId;
150 le.m_col = column;
151 window->GetEventHandler()->ProcessEvent( le );
152 }
153 result = CallNextEventHandler(handler, event);
154 break;
155 }
156 case kEventControlDraw:
157 {
158 CGContextRef context = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, typeCGContextRef) ;
159 window->MacSetDrawingContext(context);
160 result = CallNextEventHandler(handler, event);
161 window->MacSetDrawingContext(NULL);
162 break;
163 }
164 default :
165 break ;
166 }
167
168
169 return result ;
170 }
171
172 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacListCtrlEventHandler )
173
174 class wxMacListCtrlItem : public wxMacListBoxItem
175 {
176 public:
177 wxMacListCtrlItem();
178
179 virtual void Notification(wxMacDataItemBrowserControl *owner ,
180 DataBrowserItemNotification message,
181 DataBrowserItemDataRef itemData ) const;
182
183 virtual void SetColumnInfo( unsigned int column, wxListItem* item );
184 virtual wxListItem* GetColumnInfo( unsigned int column );
185 virtual bool HasColumnInfo( unsigned int column );
186
187 virtual void SetColumnTextValue( unsigned int column, const wxString& text );
188 virtual const wxString& GetColumnTextValue( unsigned int column );
189
190 virtual int GetColumnImageValue( unsigned int column );
191 virtual void SetColumnImageValue( unsigned int column, int imageIndex );
192
193 virtual ~wxMacListCtrlItem();
194 protected:
195 wxListItemList m_rowItems;
196 };
197
198 DataBrowserDrawItemUPP gDataBrowserDrawItemUPP = NULL;
199 //DataBrowserEditItemUPP gDataBrowserEditItemUPP = NULL;
200 DataBrowserHitTestUPP gDataBrowserHitTestUPP = NULL;
201
202 // TODO: Make a better name!!
203 class wxMacDataBrowserListCtrlControl : public wxMacDataItemBrowserControl
204 {
205 public:
206 wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style );
207 virtual ~wxMacDataBrowserListCtrlControl();
208
209 // create a list item (can be a subclass of wxMacListBoxItem)
210
211 virtual wxMacDataItem* CreateItem();
212
213 virtual void MacInsertItem( unsigned int n, wxListItem* item );
214 virtual void MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item );
215 virtual void MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item );
216 virtual void UpdateState(wxMacDataItem* dataItem, wxListItem* item);
217
218 protected:
219 // we need to override to provide specialized handling for virtual wxListCtrls
220 virtual OSStatus GetSetItemData(DataBrowserItemID itemID,
221 DataBrowserPropertyID property,
222 DataBrowserItemDataRef itemData,
223 Boolean changeValue );
224
225 virtual void ItemNotification(
226 DataBrowserItemID itemID,
227 DataBrowserItemNotification message,
228 DataBrowserItemDataRef itemData);
229
230 virtual Boolean CompareItems(DataBrowserItemID itemOneID,
231 DataBrowserItemID itemTwoID,
232 DataBrowserPropertyID sortProperty);
233
234 static pascal void DataBrowserDrawItemProc(ControlRef browser,
235 DataBrowserItemID item,
236 DataBrowserPropertyID property,
237 DataBrowserItemState itemState,
238 const Rect *theRect,
239 SInt16 gdDepth,
240 Boolean colorDevice);
241
242 virtual void DrawItem(DataBrowserItemID itemID,
243 DataBrowserPropertyID property,
244 DataBrowserItemState itemState,
245 const Rect *itemRect,
246 SInt16 gdDepth,
247 Boolean colorDevice);
248
249 static pascal Boolean DataBrowserEditTextProc(ControlRef browser,
250 DataBrowserItemID item,
251 DataBrowserPropertyID property,
252 CFStringRef theString,
253 Rect *maxEditTextRect,
254 Boolean *shrinkToFit);
255
256 static pascal Boolean DataBrowserHitTestProc(ControlRef browser,
257 DataBrowserItemID itemID,
258 DataBrowserPropertyID property,
259 const Rect *theRect,
260 const Rect *mouseRect) { return true; }
261
262 virtual bool ConfirmEditText(DataBrowserItemID item,
263 DataBrowserPropertyID property,
264 CFStringRef theString,
265 Rect *maxEditTextRect,
266 Boolean *shrinkToFit);
267
268
269
270 wxClientDataType m_clientDataItemsType;
271 bool m_isVirtual;
272
273 };
274
275 class wxMacListCtrlEventDelegate : public wxEvtHandler
276 {
277 public:
278 wxMacListCtrlEventDelegate( wxListCtrl* list, int id );
279 virtual bool ProcessEvent( wxEvent& event );
280
281 private:
282 wxListCtrl* m_list;
283 int m_id;
284 };
285
286 wxMacListCtrlEventDelegate::wxMacListCtrlEventDelegate( wxListCtrl* list, int id )
287 {
288 m_list = list;
289 m_id = id;
290 }
291
292 bool wxMacListCtrlEventDelegate::ProcessEvent( wxEvent& event )
293 {
294 // even though we use a generic list ctrl underneath, make sure
295 // we present ourselves as wxListCtrl.
296 event.SetEventObject( m_list );
297 event.SetId( m_id );
298
299 if ( !event.IsKindOf( CLASSINFO( wxCommandEvent ) ) )
300 {
301 if (m_list->GetEventHandler()->ProcessEvent( event ))
302 return true;
303 }
304 return wxEvtHandler::ProcessEvent(event);
305 }
306
307 // ============================================================================
308 // implementation
309 // ============================================================================
310
311 wxMacListControl* wxListCtrl::GetPeer() const
312 {
313 return dynamic_cast<wxMacListControl*>(m_peer);
314 }
315
316 // ----------------------------------------------------------------------------
317 // wxListCtrl construction
318 // ----------------------------------------------------------------------------
319
320 void wxListCtrl::Init()
321 {
322 m_imageListNormal = NULL;
323 m_imageListSmall = NULL;
324 m_imageListState = NULL;
325
326 // keep track of if we created our own image lists, or if they were assigned
327 // to us.
328 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = false;
329 m_colCount = 0;
330 m_count = 0;
331 m_textCtrl = NULL;
332 m_genericImpl = NULL;
333 m_dbImpl = NULL;
334 m_compareFunc = NULL;
335 m_compareFuncData = 0;
336 m_colsInfo = wxColumnList();
337 m_textColor = wxNullColour;
338 m_bgColor = wxNullColour;
339 }
340
341 class wxGenericListCtrlHook : public wxGenericListCtrl
342 {
343 public:
344 wxGenericListCtrlHook(wxListCtrl* parent,
345 wxWindowID id,
346 const wxPoint& pos,
347 const wxSize& size,
348 long style,
349 const wxValidator& validator,
350 const wxString& name)
351 : wxGenericListCtrl(parent, id, pos, size, style, validator, name),
352 m_nativeListCtrl(parent)
353 {
354 }
355
356 protected:
357 virtual wxListItemAttr * OnGetItemAttr(long item) const
358 {
359 return m_nativeListCtrl->OnGetItemAttr(item);
360 }
361
362 virtual int OnGetItemImage(long item) const
363 {
364 return m_nativeListCtrl->OnGetItemImage(item);
365 }
366
367 virtual int OnGetItemColumnImage(long item, long column) const
368 {
369 return m_nativeListCtrl->OnGetItemColumnImage(item, column);
370 }
371
372 virtual wxString OnGetItemText(long item, long column) const
373 {
374 return m_nativeListCtrl->OnGetItemText(item, column);
375 }
376
377 wxListCtrl* m_nativeListCtrl;
378
379 };
380
381 bool wxListCtrl::Create(wxWindow *parent,
382 wxWindowID id,
383 const wxPoint& pos,
384 const wxSize& size,
385 long style,
386 const wxValidator& validator,
387 const wxString& name)
388 {
389
390 // for now, we'll always use the generic list control for ICON and LIST views,
391 // because they dynamically change the number of columns on resize.
392 // Also, allow the user to set it to use the list ctrl as well.
393 // Also, use generic list control in VIRTUAL mode.
394 if ( (wxSystemOptions::HasOption( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL )
395 && (wxSystemOptions::GetOptionInt( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL ) == 1)) ||
396 (style & wxLC_ICON) || (style & wxLC_SMALL_ICON) || (style & wxLC_LIST) || (style & wxLC_EDIT_LABELS) )
397 {
398 m_macIsUserPane = true;
399
400 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
401 return false;
402 m_genericImpl = new wxGenericListCtrlHook(this, id, pos, size, style, validator, name);
403 m_genericImpl->PushEventHandler( new wxMacListCtrlEventDelegate( this, GetId() ) );
404 return true;
405 }
406
407 else
408 {
409 m_macIsUserPane = false;
410
411 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
412 return false;
413 m_dbImpl = new wxMacDataBrowserListCtrlControl( this, pos, size, style );
414 m_peer = m_dbImpl;
415
416 MacPostControlCreate( pos, size );
417
418 InstallControlEventHandler( m_peer->GetControlRef() , GetwxMacListCtrlEventHandlerUPP(),
419 GetEventTypeCount(eventList), eventList, this,
420 (EventHandlerRef *)&m_macListCtrlEventHandler);
421 }
422
423 return true;
424 }
425
426 wxListCtrl::~wxListCtrl()
427 {
428 if (m_genericImpl)
429 {
430 m_genericImpl->PopEventHandler(/* deleteHandler = */ true);
431 }
432
433 if (m_ownsImageListNormal)
434 delete m_imageListNormal;
435 if (m_ownsImageListSmall)
436 delete m_imageListSmall;
437 if (m_ownsImageListState)
438 delete m_imageListState;
439 }
440
441 // ----------------------------------------------------------------------------
442 // set/get/change style
443 // ----------------------------------------------------------------------------
444
445 // Add or remove a single window style
446 void wxListCtrl::SetSingleStyle(long style, bool add)
447 {
448 long flag = GetWindowStyleFlag();
449
450 // Get rid of conflicting styles
451 if ( add )
452 {
453 if ( style & wxLC_MASK_TYPE)
454 flag = flag & ~wxLC_MASK_TYPE;
455 if ( style & wxLC_MASK_ALIGN )
456 flag = flag & ~wxLC_MASK_ALIGN;
457 if ( style & wxLC_MASK_SORT )
458 flag = flag & ~wxLC_MASK_SORT;
459 }
460
461 if ( add )
462 flag |= style;
463 else
464 flag &= ~style;
465
466 SetWindowStyleFlag(flag);
467 }
468
469 // Set the whole window style
470 void wxListCtrl::SetWindowStyleFlag(long flag)
471 {
472 if ( flag != m_windowStyle )
473 {
474 m_windowStyle = flag;
475
476 if (m_genericImpl)
477 {
478 m_genericImpl->SetWindowStyleFlag(flag);
479 }
480
481 Refresh();
482 }
483 }
484
485 void wxListCtrl::DoSetSize( int x, int y, int width, int height, int sizeFlags )
486 {
487 wxControl::DoSetSize(x, y, width, height, sizeFlags);
488
489 if (m_genericImpl)
490 m_genericImpl->SetSize(x, y, width, height, sizeFlags);
491 }
492
493 bool wxListCtrl::SetFont(const wxFont& font)
494 {
495 bool rv = true;
496 rv = wxControl::SetFont(font);
497 if (m_genericImpl)
498 rv = m_genericImpl->SetFont(font);
499 return rv;
500 }
501
502 bool wxListCtrl::SetForegroundColour(const wxColour& colour)
503 {
504 bool rv = true;
505 if (m_genericImpl)
506 rv = m_genericImpl->SetForegroundColour(colour);
507 if (m_dbImpl)
508 SetTextColour(colour);
509 return rv;
510 }
511
512 bool wxListCtrl::SetBackgroundColour(const wxColour& colour)
513 {
514 bool rv = true;
515 if (m_genericImpl)
516 rv = m_genericImpl->SetBackgroundColour(colour);
517 if (m_dbImpl)
518 m_bgColor = colour;
519 return rv;
520 }
521
522 wxColour wxListCtrl::GetBackgroundColour()
523 {
524 if (m_genericImpl)
525 return m_genericImpl->GetBackgroundColour();
526 if (m_dbImpl)
527 return m_bgColor;
528
529 return wxNullColour;
530 }
531
532 // ----------------------------------------------------------------------------
533 // accessors
534 // ----------------------------------------------------------------------------
535
536 // Gets information about this column
537 bool wxListCtrl::GetColumn(int col, wxListItem& item) const
538 {
539 if (m_genericImpl)
540 return m_genericImpl->GetColumn(col, item);
541
542 bool success = true;
543
544 if (m_dbImpl)
545 {
546
547 wxColumnList::compatibility_iterator node = m_colsInfo.Item( col );
548 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
549 wxListItem* column = node->GetData();
550
551 long mask = column->GetMask();
552 if (mask & wxLIST_MASK_TEXT)
553 item.SetText(column->GetText());
554 if (mask & wxLIST_MASK_DATA)
555 item.SetData(column->GetData());
556 if (mask & wxLIST_MASK_IMAGE)
557 item.SetImage(column->GetImage());
558 if (mask & wxLIST_MASK_STATE)
559 item.SetState(column->GetState());
560 if (mask & wxLIST_MASK_FORMAT)
561 item.SetAlign(column->GetAlign());
562 if (mask & wxLIST_MASK_WIDTH)
563 item.SetWidth(column->GetWidth());
564 }
565
566 return success;
567 }
568
569 // Sets information about this column
570 bool wxListCtrl::SetColumn(int col, wxListItem& item)
571 {
572 if (m_genericImpl)
573 return m_genericImpl->SetColumn(col, item);
574
575 if (m_dbImpl)
576 {
577 if ( col >= (int)m_colsInfo.GetCount() )
578 {
579 wxListItem* listItem = new wxListItem(item);
580 m_colsInfo.Append( listItem );
581 }
582 else
583 {
584 wxListItem listItem;
585 GetColumn( col, listItem );
586 long mask = item.GetMask();
587 if (mask & wxLIST_MASK_TEXT)
588 listItem.SetText(item.GetText());
589 if (mask & wxLIST_MASK_DATA)
590 listItem.SetData(item.GetData());
591 if (mask & wxLIST_MASK_IMAGE)
592 listItem.SetImage(item.GetImage());
593 if (mask & wxLIST_MASK_STATE)
594 listItem.SetState(item.GetState());
595 if (mask & wxLIST_MASK_FORMAT)
596 listItem.SetAlign(item.GetAlign());
597 if (mask & wxLIST_MASK_WIDTH)
598 listItem.SetWidth(item.GetWidth());
599 }
600
601 // change the appearance in the databrowser.
602 DataBrowserListViewHeaderDesc columnDesc;
603 columnDesc.version=kDataBrowserListViewLatestHeaderDesc;
604 verify_noerr( m_dbImpl->GetHeaderDesc( kMinColumnId + col, &columnDesc ) );
605
606 /*
607 if (item.GetMask() & wxLIST_MASK_TEXT)
608 {
609 wxFontEncoding enc;
610 if ( m_font.Ok() )
611 enc = m_font.GetEncoding();
612 else
613 enc = wxLocale::GetSystemEncoding();
614 wxMacCFStringHolder cfTitle;
615 cfTitle.Assign( item.GetText() , enc );
616 if(columnDesc.titleString)
617 CFRelease(columnDesc.titleString);
618 columnDesc.titleString = cfTitle;
619 }
620 */
621
622 if (item.GetMask() & wxLIST_MASK_IMAGE && item.GetImage() != -1 )
623 {
624 columnDesc.btnContentInfo.contentType = kControlContentIconRef;
625 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
626 if (imageList && imageList->GetImageCount() > 0 )
627 {
628 wxBitmap bmp = imageList->GetBitmap( item.GetImage() );
629 IconRef icon = bmp.GetBitmapData()->GetIconRef();
630 columnDesc.btnContentInfo.u.iconRef = icon;
631 }
632 }
633
634 verify_noerr( m_dbImpl->SetHeaderDesc( kMinColumnId + col, &columnDesc ) );
635
636 }
637 return true;
638 }
639
640 int wxListCtrl::GetColumnCount() const
641 {
642 if (m_genericImpl)
643 return m_genericImpl->GetColumnCount();
644
645 if (m_dbImpl)
646 {
647 UInt32 count;
648 m_dbImpl->GetColumnCount(&count);
649 return count;
650 }
651
652 return m_colCount;
653 }
654
655 // Gets the column width
656 int wxListCtrl::GetColumnWidth(int col) const
657 {
658 if (m_genericImpl)
659 return m_genericImpl->GetColumnWidth(col);
660
661 if (m_dbImpl)
662 {
663 return m_dbImpl->GetColumnWidth(col);
664 }
665
666 return 0;
667 }
668
669 // Sets the column width
670 bool wxListCtrl::SetColumnWidth(int col, int width)
671 {
672 if (m_genericImpl)
673 return m_genericImpl->SetColumnWidth(col, width);
674
675 if (m_dbImpl)
676 {
677 int mywidth = width;
678 if (width == wxLIST_AUTOSIZE || width == wxLIST_AUTOSIZE_USEHEADER)
679 mywidth = 150;
680
681 if (col == -1)
682 {
683 for (int column = 0; column < GetColumnCount(); column++)
684 {
685 m_dbImpl->SetColumnWidth(col, mywidth);
686 }
687 }
688 else{
689 m_dbImpl->SetColumnWidth(col, mywidth);
690 }
691 return true;
692 }
693
694 return false;
695 }
696
697 // Gets the number of items that can fit vertically in the
698 // visible area of the list control (list or report view)
699 // or the total number of items in the list control (icon
700 // or small icon view)
701 int wxListCtrl::GetCountPerPage() const
702 {
703 if (m_genericImpl)
704 return m_genericImpl->GetCountPerPage();
705
706 if (m_dbImpl)
707 {
708 }
709
710 return 1;
711 }
712
713 // Gets the edit control for editing labels.
714 wxTextCtrl* wxListCtrl::GetEditControl() const
715 {
716 if (m_genericImpl)
717 return m_genericImpl->GetEditControl();
718
719 return NULL;
720 }
721
722 // Gets information about the item
723 bool wxListCtrl::GetItem(wxListItem& info) const
724 {
725 if (m_genericImpl)
726 return m_genericImpl->GetItem(info);
727
728 if (m_dbImpl)
729 {
730 if (!IsVirtual())
731 m_dbImpl->MacGetColumnInfo(info.m_itemId, info.m_col, info);
732 else
733 {
734 info.SetText( OnGetItemText(info.m_itemId, info.m_col) );
735 info.SetImage( OnGetItemColumnImage(info.m_itemId, info.m_col) );
736 wxListItemAttr* attrs = OnGetItemAttr( info.m_itemId );
737 if (attrs)
738 {
739 info.SetFont( attrs->GetFont() );
740 info.SetBackgroundColour( attrs->GetBackgroundColour() );
741 info.SetTextColour( attrs->GetTextColour() );
742 }
743 }
744 }
745 bool success = true;
746 return success;
747 }
748
749 // Sets information about the item
750 bool wxListCtrl::SetItem(wxListItem& info)
751 {
752 if (m_genericImpl)
753 return m_genericImpl->SetItem(info);
754
755 if (m_dbImpl)
756 m_dbImpl->MacSetColumnInfo( info.m_itemId, info.m_col, &info );
757
758 return true;
759 }
760
761 long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
762 {
763 if (m_genericImpl)
764 return m_genericImpl->SetItem(index, col, label, imageId);
765
766 wxListItem info;
767 info.m_text = label;
768 info.m_mask = wxLIST_MASK_TEXT;
769 info.m_itemId = index;
770 info.m_col = col;
771 if ( imageId > -1 )
772 {
773 info.m_image = imageId;
774 info.m_mask |= wxLIST_MASK_IMAGE;
775 }
776 return SetItem(info);
777 }
778
779
780 // Gets the item state
781 int wxListCtrl::GetItemState(long item, long stateMask) const
782 {
783 if (m_genericImpl)
784 return m_genericImpl->GetItemState(item, stateMask);
785
786 wxListItem info;
787
788 info.m_mask = wxLIST_MASK_STATE;
789 info.m_stateMask = stateMask;
790 info.m_itemId = item;
791
792 if (!GetItem(info))
793 return 0;
794
795 return info.m_state;
796 }
797
798 // Sets the item state
799 bool wxListCtrl::SetItemState(long item, long state, long stateMask)
800 {
801 if (m_genericImpl)
802 return m_genericImpl->SetItemState(item, state, stateMask);
803
804 wxListItem info;
805 info.m_mask = wxLIST_MASK_STATE;
806 info.m_stateMask = stateMask;
807 info.m_state = state;
808 info.m_itemId = item;
809 return SetItem(info);
810 }
811
812 // Sets the item image
813 bool wxListCtrl::SetItemImage(long item, int image, int WXUNUSED(selImage))
814 {
815 return SetItemColumnImage(item, 0, image);
816 }
817
818 // Sets the item image
819 bool wxListCtrl::SetItemColumnImage(long item, long column, int image)
820 {
821 if (m_genericImpl)
822 return m_genericImpl->SetItemColumnImage(item, column, image);
823
824 wxListItem info;
825
826 info.m_mask = wxLIST_MASK_IMAGE;
827 info.m_image = image;
828 info.m_itemId = item;
829 info.m_col = column;
830
831 return SetItem(info);
832 }
833
834 // Gets the item text
835 wxString wxListCtrl::GetItemText(long item) const
836 {
837 if (m_genericImpl)
838 return m_genericImpl->GetItemText(item);
839
840 wxListItem info;
841
842 info.m_mask = wxLIST_MASK_TEXT;
843 info.m_itemId = item;
844
845 if (!GetItem(info))
846 return wxEmptyString;
847 return info.m_text;
848 }
849
850 // Sets the item text
851 void wxListCtrl::SetItemText(long item, const wxString& str)
852 {
853 if (m_genericImpl)
854 return m_genericImpl->SetItemText(item, str);
855
856 wxListItem info;
857
858 info.m_mask = wxLIST_MASK_TEXT;
859 info.m_itemId = item;
860 info.m_text = str;
861
862 SetItem(info);
863 }
864
865 // Gets the item data
866 long wxListCtrl::GetItemData(long item) const
867 {
868 if (m_genericImpl)
869 return m_genericImpl->GetItemData(item);
870
871 wxListItem info;
872
873 info.m_mask = wxLIST_MASK_DATA;
874 info.m_itemId = item;
875
876 if (!GetItem(info))
877 return 0;
878 return info.m_data;
879 }
880
881 // Sets the item data
882 bool wxListCtrl::SetItemData(long item, long data)
883 {
884 if (m_genericImpl)
885 return m_genericImpl->SetItemData(item, data);
886
887 wxListItem info;
888
889 info.m_mask = wxLIST_MASK_DATA;
890 info.m_itemId = item;
891 info.m_data = data;
892
893 return SetItem(info);
894 }
895
896 wxRect wxListCtrl::GetViewRect() const
897 {
898 wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
899 _T("wxListCtrl::GetViewRect() only works in icon mode") );
900
901 if (m_genericImpl)
902 return m_genericImpl->GetViewRect();
903
904 wxRect rect;
905 return rect;
906 }
907
908 // Gets the item rectangle
909 bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
910 {
911 if (m_genericImpl)
912 return m_genericImpl->GetItemRect(item, rect, code);
913
914 return true;
915 }
916
917 // Gets the item position
918 bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
919 {
920 if (m_genericImpl)
921 return m_genericImpl->GetItemPosition(item, pos);
922
923 bool success = false;
924
925 return success;
926 }
927
928 // Sets the item position.
929 bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
930 {
931 if (m_genericImpl)
932 return m_genericImpl->SetItemPosition(item, pos);
933
934 return false;
935 }
936
937 // Gets the number of items in the list control
938 int wxListCtrl::GetItemCount() const
939 {
940 if (m_genericImpl)
941 return m_genericImpl->GetItemCount();
942
943 if (m_dbImpl)
944 return m_dbImpl->MacGetCount();
945
946 return m_count;
947 }
948
949 void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
950 {
951 if (m_genericImpl)
952 m_genericImpl->SetItemSpacing(spacing, isSmall);
953 }
954
955 wxSize wxListCtrl::GetItemSpacing() const
956 {
957 if (m_genericImpl)
958 return m_genericImpl->GetItemSpacing();
959
960 return wxSize(0, 0);
961 }
962
963 void wxListCtrl::SetItemTextColour( long item, const wxColour &col )
964 {
965 if (m_genericImpl)
966 {
967 m_genericImpl->SetItemTextColour(item, col);
968 return;
969 }
970
971 wxListItem info;
972 info.m_itemId = item;
973 info.SetTextColour( col );
974 SetItem( info );
975 }
976
977 wxColour wxListCtrl::GetItemTextColour( long item ) const
978 {
979 if (m_genericImpl)
980 return m_genericImpl->GetItemTextColour(item);
981
982 if (m_dbImpl)
983 {
984 wxListItem info;
985 if (GetItem(info))
986 return info.GetTextColour();
987 }
988 return wxNullColour;
989 }
990
991 void wxListCtrl::SetItemBackgroundColour( long item, const wxColour &col )
992 {
993 if (m_genericImpl)
994 {
995 m_genericImpl->SetItemBackgroundColour(item, col);
996 return;
997 }
998
999 wxListItem info;
1000 info.m_itemId = item;
1001 info.SetBackgroundColour( col );
1002 SetItem( info );
1003 }
1004
1005 wxColour wxListCtrl::GetItemBackgroundColour( long item ) const
1006 {
1007 if (m_genericImpl)
1008 return m_genericImpl->GetItemBackgroundColour(item);
1009
1010 if (m_dbImpl)
1011 {
1012 wxListItem info;
1013 if (GetItem(info))
1014 return info.GetBackgroundColour();
1015 }
1016 return wxNullColour;
1017 }
1018
1019 void wxListCtrl::SetItemFont( long item, const wxFont &f )
1020 {
1021 if (m_genericImpl)
1022 {
1023 m_genericImpl->SetItemFont(item, f);
1024 return;
1025 }
1026
1027 wxListItem info;
1028 info.m_itemId = item;
1029 info.SetFont( f );
1030 SetItem( info );
1031 }
1032
1033 wxFont wxListCtrl::GetItemFont( long item ) const
1034 {
1035 if (m_genericImpl)
1036 return m_genericImpl->GetItemFont(item);
1037
1038 if (m_dbImpl)
1039 {
1040 wxListItem info;
1041 if (GetItem(info))
1042 return info.GetFont();
1043 }
1044
1045 return wxNullFont;
1046 }
1047
1048 // Gets the number of selected items in the list control
1049 int wxListCtrl::GetSelectedItemCount() const
1050 {
1051 if (m_genericImpl)
1052 return m_genericImpl->GetSelectedItemCount();
1053
1054 if (m_dbImpl)
1055 return m_dbImpl->GetSelectedItemCount(NULL, true);
1056
1057 return 0;
1058 }
1059
1060 // Gets the text colour of the listview
1061 wxColour wxListCtrl::GetTextColour() const
1062 {
1063 if (m_genericImpl)
1064 return m_genericImpl->GetTextColour();
1065
1066 // TODO: we need owner drawn list items to customize text color.
1067 if (m_dbImpl)
1068 return m_textColor;
1069
1070 return wxNullColour;
1071 }
1072
1073 // Sets the text colour of the listview
1074 void wxListCtrl::SetTextColour(const wxColour& col)
1075 {
1076 if (m_genericImpl)
1077 {
1078 m_genericImpl->SetTextColour(col);
1079 return;
1080 }
1081
1082 if (m_dbImpl)
1083 m_textColor = col;
1084 }
1085
1086 // Gets the index of the topmost visible item when in
1087 // list or report view
1088 long wxListCtrl::GetTopItem() const
1089 {
1090 if (m_genericImpl)
1091 return m_genericImpl->GetTopItem();
1092
1093 return 0;
1094 }
1095
1096 // Searches for an item, starting from 'item'.
1097 // 'geometry' is one of
1098 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1099 // 'state' is a state bit flag, one or more of
1100 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1101 // item can be -1 to find the first item that matches the
1102 // specified flags.
1103 // Returns the item or -1 if unsuccessful.
1104 long wxListCtrl::GetNextItem(long item, int geom, int state) const
1105 {
1106 if (m_genericImpl)
1107 return m_genericImpl->GetNextItem(item, geom, state);
1108
1109 if (m_dbImpl && geom == wxLIST_NEXT_ALL && state == wxLIST_STATE_SELECTED )
1110 {
1111 long count = m_dbImpl->MacGetCount() ;
1112 for ( long line = item + 1 ; line < count; line++ )
1113 {
1114 wxMacDataItem* id = m_dbImpl->GetItemFromLine(line);
1115 if ( m_dbImpl->IsItemSelected(id ) )
1116 return line;
1117 }
1118 return -1;
1119 }
1120
1121 return 0;
1122 }
1123
1124
1125 wxImageList *wxListCtrl::GetImageList(int which) const
1126 {
1127 if (m_genericImpl)
1128 return m_genericImpl->GetImageList(which);
1129
1130 if ( which == wxIMAGE_LIST_NORMAL )
1131 {
1132 return m_imageListNormal;
1133 }
1134 else if ( which == wxIMAGE_LIST_SMALL )
1135 {
1136 return m_imageListSmall;
1137 }
1138 else if ( which == wxIMAGE_LIST_STATE )
1139 {
1140 return m_imageListState;
1141 }
1142 return NULL;
1143 }
1144
1145 void wxListCtrl::SetImageList(wxImageList *imageList, int which)
1146 {
1147 if (m_genericImpl)
1148 {
1149 m_genericImpl->SetImageList(imageList, which);
1150 return;
1151 }
1152
1153 if ( which == wxIMAGE_LIST_NORMAL )
1154 {
1155 if (m_ownsImageListNormal) delete m_imageListNormal;
1156 m_imageListNormal = imageList;
1157 m_ownsImageListNormal = false;
1158 }
1159 else if ( which == wxIMAGE_LIST_SMALL )
1160 {
1161 if (m_ownsImageListSmall) delete m_imageListSmall;
1162 m_imageListSmall = imageList;
1163 m_ownsImageListSmall = false;
1164 }
1165 else if ( which == wxIMAGE_LIST_STATE )
1166 {
1167 if (m_ownsImageListState) delete m_imageListState;
1168 m_imageListState = imageList;
1169 m_ownsImageListState = false;
1170 }
1171 }
1172
1173 void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
1174 {
1175 if (m_genericImpl)
1176 {
1177 m_genericImpl->AssignImageList(imageList, which);
1178 return;
1179 }
1180
1181 SetImageList(imageList, which);
1182 if ( which == wxIMAGE_LIST_NORMAL )
1183 m_ownsImageListNormal = true;
1184 else if ( which == wxIMAGE_LIST_SMALL )
1185 m_ownsImageListSmall = true;
1186 else if ( which == wxIMAGE_LIST_STATE )
1187 m_ownsImageListState = true;
1188 }
1189
1190 // ----------------------------------------------------------------------------
1191 // Operations
1192 // ----------------------------------------------------------------------------
1193
1194 // Arranges the items
1195 bool wxListCtrl::Arrange(int flag)
1196 {
1197 if (m_genericImpl)
1198 return m_genericImpl->Arrange(flag);
1199 return false;
1200 }
1201
1202 // Deletes an item
1203 bool wxListCtrl::DeleteItem(long item)
1204 {
1205 if (m_genericImpl)
1206 return m_genericImpl->DeleteItem(item);
1207
1208 if (m_dbImpl)
1209 {
1210 m_dbImpl->MacDelete(item);
1211 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ITEM, GetId() );
1212 event.SetEventObject( this );
1213 event.m_itemIndex = item;
1214 GetEventHandler()->ProcessEvent( event );
1215
1216 }
1217 return true;
1218 }
1219
1220 // Deletes all items
1221 bool wxListCtrl::DeleteAllItems()
1222 {
1223 if (m_genericImpl)
1224 return m_genericImpl->DeleteAllItems();
1225
1226 if (m_dbImpl)
1227 {
1228 m_dbImpl->MacClear();
1229 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetId() );
1230 event.SetEventObject( this );
1231 GetEventHandler()->ProcessEvent( event );
1232 }
1233 return true;
1234 }
1235
1236 // Deletes all items
1237 bool wxListCtrl::DeleteAllColumns()
1238 {
1239 if (m_genericImpl)
1240 return m_genericImpl->DeleteAllColumns();
1241
1242 if (m_dbImpl)
1243 {
1244 UInt32 cols;
1245 m_dbImpl->GetColumnCount(&cols);
1246 for (UInt32 col = 0; col < cols; col++)
1247 {
1248 DeleteColumn(col);
1249 }
1250 }
1251
1252 return true;
1253 }
1254
1255 // Deletes a column
1256 bool wxListCtrl::DeleteColumn(int col)
1257 {
1258 if (m_genericImpl)
1259 return m_genericImpl->DeleteColumn(col);
1260
1261 if (m_dbImpl)
1262 {
1263 OSStatus err = m_dbImpl->RemoveColumn(col);
1264 return err == noErr;
1265 }
1266
1267 return true;
1268 }
1269
1270 // Clears items, and columns if there are any.
1271 void wxListCtrl::ClearAll()
1272 {
1273 if (m_genericImpl)
1274 {
1275 m_genericImpl->ClearAll();
1276 return;
1277 }
1278
1279 if (m_dbImpl)
1280 {
1281 DeleteAllItems();
1282 DeleteAllColumns();
1283 }
1284 }
1285
1286 wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
1287 {
1288 if (m_genericImpl)
1289 return m_genericImpl->EditLabel(item, textControlClass);
1290
1291 if (m_dbImpl)
1292 {
1293 wxMacDataItem* id = m_dbImpl->GetItemFromLine(item);
1294 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), (DataBrowserItemID)id, kMinColumnId) );
1295 }
1296 return NULL;
1297 }
1298
1299 // End label editing, optionally cancelling the edit
1300 bool wxListCtrl::EndEditLabel(bool cancel)
1301 {
1302 // TODO: generic impl. doesn't have this method - is it needed for us?
1303 if (m_genericImpl)
1304 return true; // m_genericImpl->EndEditLabel(cancel);
1305
1306 if (m_dbImpl)
1307 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), kDataBrowserNoItem, kMinColumnId) );
1308 return true;
1309 }
1310
1311 // Ensures this item is visible
1312 bool wxListCtrl::EnsureVisible(long item)
1313 {
1314 if (m_genericImpl)
1315 return m_genericImpl->EnsureVisible(item);
1316
1317 if (m_dbImpl)
1318 {
1319 wxMacDataItem* dataItem = m_dbImpl->GetItemFromLine(item);
1320 m_dbImpl->RevealItem(dataItem, kDataBrowserRevealWithoutSelecting);
1321 }
1322
1323 return true;
1324 }
1325
1326 // Find an item whose label matches this string, starting from the item after 'start'
1327 // or the beginning if 'start' is -1.
1328 long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
1329 {
1330 if (m_genericImpl)
1331 return m_genericImpl->FindItem(start, str, partial);
1332
1333 return -1;
1334 }
1335
1336 // Find an item whose data matches this data, starting from the item after 'start'
1337 // or the beginning if 'start' is -1.
1338 long wxListCtrl::FindItem(long start, long data)
1339 {
1340 if (m_genericImpl)
1341 return m_genericImpl->FindItem(start, data);
1342
1343 long idx = start + 1;
1344 long count = GetItemCount();
1345
1346 while (idx < count)
1347 {
1348 if (GetItemData(idx) == data)
1349 return idx;
1350 idx++;
1351 };
1352
1353 return -1;
1354 }
1355
1356 // Find an item nearest this position in the specified direction, starting from
1357 // the item after 'start' or the beginning if 'start' is -1.
1358 long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
1359 {
1360 if (m_genericImpl)
1361 return m_genericImpl->FindItem(start, pt, direction);
1362 return -1;
1363 }
1364
1365 // Determines which item (if any) is at the specified point,
1366 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
1367 long
1368 wxListCtrl::HitTest(const wxPoint& point, int& flags, long *ptrSubItem) const
1369 {
1370 if (m_genericImpl)
1371 return m_genericImpl->HitTest(point, flags, ptrSubItem);
1372
1373 return -1;
1374 }
1375
1376
1377 // Inserts an item, returning the index of the new item if successful,
1378 // -1 otherwise.
1379 long wxListCtrl::InsertItem(wxListItem& info)
1380 {
1381 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
1382
1383 if (m_genericImpl)
1384 return m_genericImpl->InsertItem(info);
1385
1386 if (m_dbImpl)
1387 {
1388 int count = GetItemCount();
1389
1390 if (info.m_itemId > count)
1391 info.m_itemId = count;
1392
1393 m_dbImpl->MacInsertItem(info.m_itemId, &info );
1394 wxListEvent event( wxEVT_COMMAND_LIST_INSERT_ITEM, GetId() );
1395 event.SetEventObject( this );
1396 event.m_itemIndex = info.m_itemId;
1397 GetEventHandler()->ProcessEvent( event );
1398 }
1399
1400 return info.m_itemId;
1401 }
1402
1403 long wxListCtrl::InsertItem(long index, const wxString& label)
1404 {
1405 if (m_genericImpl)
1406 return m_genericImpl->InsertItem(index, label);
1407
1408 wxListItem info;
1409 info.m_text = label;
1410 info.m_mask = wxLIST_MASK_TEXT;
1411 info.m_itemId = index;
1412 return InsertItem(info);
1413 }
1414
1415 // Inserts an image item
1416 long wxListCtrl::InsertItem(long index, int imageIndex)
1417 {
1418 if (m_genericImpl)
1419 return m_genericImpl->InsertItem(index, imageIndex);
1420
1421 wxListItem info;
1422 info.m_image = imageIndex;
1423 info.m_mask = wxLIST_MASK_IMAGE;
1424 info.m_itemId = index;
1425 return InsertItem(info);
1426 }
1427
1428 // Inserts an image/string item
1429 long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
1430 {
1431 if (m_genericImpl)
1432 return m_genericImpl->InsertItem(index, label, imageIndex);
1433
1434 wxListItem info;
1435 info.m_image = imageIndex;
1436 info.m_text = label;
1437 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
1438 info.m_itemId = index;
1439 return InsertItem(info);
1440 }
1441
1442 // For list view mode (only), inserts a column.
1443 long wxListCtrl::InsertColumn(long col, wxListItem& item)
1444 {
1445 if (m_genericImpl)
1446 return m_genericImpl->InsertColumn(col, item);
1447
1448 if (m_dbImpl)
1449 {
1450 int width = item.GetWidth();
1451 if ( !(item.GetMask() & wxLIST_MASK_WIDTH) )
1452 width = 150;
1453
1454 DataBrowserPropertyType type = kDataBrowserCustomType; //kDataBrowserTextType;
1455 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
1456 if (imageList && imageList->GetImageCount() > 0)
1457 {
1458 wxBitmap bmp = imageList->GetBitmap(0);
1459 //if (bmp.Ok())
1460 // type = kDataBrowserIconAndTextType;
1461 }
1462
1463 SInt16 just = teFlushDefault;
1464 if (item.GetMask() & wxLIST_MASK_FORMAT)
1465 {
1466 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
1467 just = teFlushLeft;
1468 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
1469 just = teCenter;
1470 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
1471 just = teFlushRight;
1472 }
1473 m_dbImpl->InsertColumn(col, type, item.GetText(), just, width);
1474 SetColumn(col, item);
1475
1476 // set/remove options based on the wxListCtrl type.
1477 DataBrowserTableViewColumnID id;
1478 m_dbImpl->GetColumnIDFromIndex(col, &id);
1479 DataBrowserPropertyFlags flags;
1480 verify_noerr(m_dbImpl->GetPropertyFlags(id, &flags));
1481 if (GetWindowStyleFlag() & wxLC_EDIT_LABELS)
1482 flags |= kDataBrowserPropertyIsEditable;
1483
1484 if (GetWindowStyleFlag() & wxLC_VIRTUAL){
1485 flags &= ~kDataBrowserListViewSortableColumn;
1486 }
1487 verify_noerr(m_dbImpl->SetPropertyFlags(id, flags));
1488 }
1489
1490 return col;
1491 }
1492
1493 long wxListCtrl::InsertColumn(long col,
1494 const wxString& heading,
1495 int format,
1496 int width)
1497 {
1498 if (m_genericImpl)
1499 return m_genericImpl->InsertColumn(col, heading, format, width);
1500
1501 wxListItem item;
1502 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1503 item.m_text = heading;
1504 if ( width > -1 )
1505 {
1506 item.m_mask |= wxLIST_MASK_WIDTH;
1507 item.m_width = width;
1508 }
1509 item.m_format = format;
1510
1511 return InsertColumn(col, item);
1512 }
1513
1514 // scroll the control by the given number of pixels (exception: in list view,
1515 // dx is interpreted as number of columns)
1516 bool wxListCtrl::ScrollList(int dx, int dy)
1517 {
1518 if (m_genericImpl)
1519 return m_genericImpl->ScrollList(dx, dy);
1520
1521 if (m_dbImpl)
1522 {
1523 m_dbImpl->SetScrollPosition(dx, dy);
1524 }
1525 return true;
1526 }
1527
1528
1529 bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1530 {
1531 if (m_genericImpl)
1532 return m_genericImpl->SortItems(fn, data);
1533
1534 if (m_dbImpl)
1535 {
1536 m_compareFunc = fn;
1537 m_compareFuncData = data;
1538 }
1539
1540 return true;
1541 }
1542
1543 // ----------------------------------------------------------------------------
1544 // virtual list controls
1545 // ----------------------------------------------------------------------------
1546
1547 wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
1548 {
1549 // this is a pure virtual function, in fact - which is not really pure
1550 // because the controls which are not virtual don't need to implement it
1551 wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") );
1552
1553 return wxEmptyString;
1554 }
1555
1556 int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
1557 {
1558 wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
1559 -1,
1560 wxT("List control has an image list, OnGetItemImage or OnGetItemColumnImage should be overridden."));
1561 return -1;
1562 }
1563
1564 int wxListCtrl::OnGetItemColumnImage(long item, long column) const
1565 {
1566 if (!column)
1567 return OnGetItemImage(item);
1568
1569 return -1;
1570 }
1571
1572 wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
1573 {
1574 wxASSERT_MSG( item >= 0 && item < GetItemCount(),
1575 _T("invalid item index in OnGetItemAttr()") );
1576
1577 // no attributes by default
1578 return NULL;
1579 }
1580
1581 void wxListCtrl::SetItemCount(long count)
1582 {
1583 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
1584
1585 if (m_genericImpl)
1586 {
1587 m_genericImpl->SetItemCount(count);
1588 return;
1589 }
1590
1591 if (m_dbImpl)
1592 {
1593 // we need to temporarily disable the new item creation notification
1594 // procedure to speed things up
1595 // FIXME: Even this doesn't seem to help much...
1596 DataBrowserCallbacks callbacks;
1597 DataBrowserItemNotificationUPP itemUPP;
1598 GetDataBrowserCallbacks(m_dbImpl->GetControlRef(), &callbacks);
1599 itemUPP = callbacks.u.v1.itemNotificationCallback;
1600 callbacks.u.v1.itemNotificationCallback = 0;
1601 m_dbImpl->SetCallbacks(&callbacks);
1602 ::AddDataBrowserItems(m_dbImpl->GetControlRef(), kDataBrowserNoItem,
1603 count, NULL, kDataBrowserItemNoProperty);
1604 callbacks.u.v1.itemNotificationCallback = itemUPP;
1605 m_dbImpl->SetCallbacks(&callbacks);
1606 }
1607 m_count = count;
1608 }
1609
1610 void wxListCtrl::RefreshItem(long item)
1611 {
1612 if (m_genericImpl)
1613 {
1614 m_genericImpl->RefreshItem(item);
1615 return;
1616 }
1617
1618 wxRect rect;
1619 GetItemRect(item, rect);
1620 RefreshRect(rect);
1621 }
1622
1623 void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
1624 {
1625 if (m_genericImpl)
1626 {
1627 m_genericImpl->RefreshItems(itemFrom, itemTo);
1628 return;
1629 }
1630
1631 wxRect rect1, rect2;
1632 GetItemRect(itemFrom, rect1);
1633 GetItemRect(itemTo, rect2);
1634
1635 wxRect rect = rect1;
1636 rect.height = rect2.GetBottom() - rect1.GetTop();
1637
1638 RefreshRect(rect);
1639 }
1640
1641
1642 // wxMac internal data structures
1643
1644 wxMacListCtrlItem::~wxMacListCtrlItem()
1645 {
1646 }
1647
1648 void wxMacListCtrlItem::Notification(wxMacDataItemBrowserControl *owner ,
1649 DataBrowserItemNotification message,
1650 DataBrowserItemDataRef itemData ) const
1651 {
1652
1653 wxMacDataBrowserListCtrlControl *lb = dynamic_cast<wxMacDataBrowserListCtrlControl*>(owner);
1654
1655 // we want to depend on as little as possible to make sure tear-down of controls is safe
1656 if ( message == kDataBrowserItemRemoved)
1657 {
1658 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
1659 {
1660 delete (wxClientData*) (m_data);
1661 }
1662
1663 delete this;
1664 return;
1665 }
1666 else if ( message == kDataBrowserItemAdded )
1667 {
1668 // we don't issue events on adding, the item is not really stored in the list yet, so we
1669 // avoid asserts by gettting out now
1670 return ;
1671 }
1672
1673 wxListCtrl *list = wxDynamicCast( owner->GetPeer() , wxListCtrl );
1674 if ( list )
1675 {
1676 bool trigger = false;
1677
1678 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1679 bool isSingle = (list->GetWindowStyle() & wxLC_SINGLE_SEL) != 0;
1680
1681 event.SetEventObject( list );
1682 event.m_itemIndex = owner->GetLineFromItem( this ) ;
1683 if ( !list->IsVirtual() )
1684 {
1685 lb->MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1686 }
1687
1688 switch (message)
1689 {
1690 case kDataBrowserItemDeselected:
1691 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1692 if ( !isSingle )
1693 trigger = !lb->IsSelectionSuppressed();
1694 break;
1695
1696 case kDataBrowserItemSelected:
1697 trigger = !lb->IsSelectionSuppressed();
1698 break;
1699
1700 case kDataBrowserItemDoubleClicked:
1701 event.SetEventType( wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
1702 trigger = true;
1703 break;
1704
1705 case kDataBrowserEditStarted :
1706 // TODO : how to veto ?
1707 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1708 trigger = true ;
1709 break ;
1710
1711 case kDataBrowserEditStopped :
1712 // TODO probably trigger only upon the value store callback, because
1713 // here IIRC we cannot veto
1714 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1715 trigger = true ;
1716 break ;
1717
1718 default:
1719 break;
1720 }
1721
1722 if ( trigger )
1723 {
1724 // direct notification is not always having the listbox GetSelection() having in synch with event
1725 wxPostEvent( list->GetEventHandler(), event );
1726 }
1727 }
1728
1729 }
1730
1731 wxMacDataBrowserListCtrlControl::wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
1732 : wxMacDataItemBrowserControl( peer, pos, size, style )
1733 {
1734 OSStatus err = noErr;
1735 m_clientDataItemsType = wxClientData_None;
1736 m_isVirtual = false;
1737
1738 if ( style & wxLC_VIRTUAL )
1739 m_isVirtual = true;
1740
1741 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
1742 if ( style & wxLC_SINGLE_SEL )
1743 {
1744 options |= kDataBrowserSelectOnlyOne;
1745 }
1746 else
1747 {
1748 options |= kDataBrowserCmdTogglesSelection;
1749 }
1750
1751 err = SetSelectionFlags( options );
1752 verify_noerr( err );
1753
1754 DataBrowserCustomCallbacks callbacks;
1755 InitializeDataBrowserCustomCallbacks( &callbacks, kDataBrowserLatestCustomCallbacks );
1756
1757 if ( gDataBrowserDrawItemUPP == NULL )
1758 gDataBrowserDrawItemUPP = NewDataBrowserDrawItemUPP(DataBrowserDrawItemProc);
1759
1760 // if ( gDataBrowserEditItemUPP == NULL )
1761 // gDataBrowserEditItemUPP = NewDataBrowserEditItemUPP(DataBrowserEditTextProc);
1762
1763 if ( gDataBrowserHitTestUPP == NULL )
1764 gDataBrowserHitTestUPP = NewDataBrowserHitTestUPP(DataBrowserHitTestProc);
1765
1766 callbacks.u.v1.drawItemCallback = gDataBrowserDrawItemUPP;
1767 // callbacks.u.v1.editTextCallback = gDataBrowserEditItemUPP;
1768 callbacks.u.v1.hitTestCallback = gDataBrowserHitTestUPP;
1769
1770 SetDataBrowserCustomCallbacks( GetControlRef(), &callbacks );
1771
1772 if ( style & wxLC_LIST )
1773 {
1774 InsertColumn(0, kDataBrowserIconAndTextType, wxEmptyString, -1, -1);
1775 verify_noerr( AutoSizeColumns() );
1776 }
1777
1778 if ( style & wxLC_LIST || style & wxLC_NO_HEADER )
1779 verify_noerr( SetHeaderButtonHeight( 0 ) );
1780
1781 if ( m_isVirtual )
1782 SetSortProperty( kMinColumnId - 1 );
1783 else
1784 SetSortProperty( kMinColumnId );
1785 if ( style & wxLC_SORT_ASCENDING )
1786 {
1787 m_sortOrder = SortOrder_Text_Ascending;
1788 SetSortOrder( kDataBrowserOrderIncreasing );
1789 }
1790 else if ( style & wxLC_SORT_DESCENDING )
1791 {
1792 m_sortOrder = SortOrder_Text_Descending;
1793 SetSortOrder( kDataBrowserOrderDecreasing );
1794 }
1795 else
1796 {
1797 m_sortOrder = SortOrder_None;
1798 }
1799
1800 if ( style & wxLC_VRULES )
1801 {
1802 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1803 verify_noerr( DataBrowserChangeAttributes(m_controlRef, kDataBrowserAttributeListViewDrawColumnDividers, kDataBrowserAttributeNone) );
1804 #endif
1805 }
1806
1807 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
1808 err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
1809 }
1810
1811 pascal Boolean wxMacDataBrowserListCtrlControl::DataBrowserEditTextProc(
1812 ControlRef browser,
1813 DataBrowserItemID itemID,
1814 DataBrowserPropertyID property,
1815 CFStringRef theString,
1816 Rect *maxEditTextRect,
1817 Boolean *shrinkToFit)
1818 {
1819 Boolean result = false;
1820 wxMacDataBrowserListCtrlControl* ctl = dynamic_cast<wxMacDataBrowserListCtrlControl*>( wxMacControl::GetReferenceFromNativeControl( browser ) );
1821 if ( ctl != 0 )
1822 {
1823 result = ctl->ConfirmEditText(itemID, property, theString, maxEditTextRect, shrinkToFit);
1824 theString = CFSTR("Hello!");
1825 }
1826 return result;
1827 }
1828
1829 bool wxMacDataBrowserListCtrlControl::ConfirmEditText(
1830 DataBrowserItemID itemID,
1831 DataBrowserPropertyID property,
1832 CFStringRef theString,
1833 Rect *maxEditTextRect,
1834 Boolean *shrinkToFit)
1835 {
1836 //wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1837 return false;
1838 }
1839
1840 pascal void wxMacDataBrowserListCtrlControl::DataBrowserDrawItemProc(
1841 ControlRef browser,
1842 DataBrowserItemID itemID,
1843 DataBrowserPropertyID property,
1844 DataBrowserItemState itemState,
1845 const Rect *itemRect,
1846 SInt16 gdDepth,
1847 Boolean colorDevice)
1848 {
1849 wxMacDataBrowserListCtrlControl* ctl = dynamic_cast<wxMacDataBrowserListCtrlControl*>( wxMacControl::GetReferenceFromNativeControl( browser ) );
1850 if ( ctl != 0 )
1851 {
1852 ctl->DrawItem(itemID, property, itemState, itemRect, gdDepth, colorDevice);
1853 }
1854 }
1855
1856 // routines needed for DrawItem
1857 enum
1858 {
1859 kIconWidth = 16,
1860 kIconHeight = 16,
1861 kTextBoxHeight = 14,
1862 kIconTextSpacingV = 2,
1863 kItemPadding = 4,
1864 kContentHeight = kIconHeight + kTextBoxHeight + kIconTextSpacingV
1865 };
1866
1867 static void calculateCGDrawingBounds(CGRect inItemRect, CGRect *outIconRect, CGRect *outTextRect, bool hasIcon = false)
1868 {
1869 float textBottom;
1870 float iconH, iconW = 0;
1871 float padding = kItemPadding;
1872 if (hasIcon)
1873 {
1874 iconH = kIconHeight;
1875 iconW = kIconWidth;
1876 padding = padding*2;
1877 }
1878
1879 textBottom = inItemRect.origin.y;
1880
1881 *outIconRect = CGRectMake(inItemRect.origin.x + kItemPadding,
1882 textBottom + kIconTextSpacingV, kIconWidth,
1883 kIconHeight);
1884
1885 *outTextRect = CGRectMake(inItemRect.origin.x + padding + iconW,
1886 textBottom + kIconTextSpacingV, inItemRect.size.width - padding - iconW,
1887 inItemRect.size.height - kIconTextSpacingV);
1888 }
1889
1890 void wxMacDataBrowserListCtrlControl::DrawItem(
1891 DataBrowserItemID itemID,
1892 DataBrowserPropertyID property,
1893 DataBrowserItemState itemState,
1894 const Rect *itemRect,
1895 SInt16 gdDepth,
1896 Boolean colorDevice)
1897 {
1898 wxString text;
1899 wxFont font = wxNullFont;
1900 int imgIndex = -1;
1901 short listColumn = property - kMinColumnId;
1902
1903 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1904 wxMacListCtrlItem* lcItem;
1905 wxColour color = *wxBLACK;
1906 wxColour bgColor = wxNullColour;
1907
1908 if (listColumn >= 0)
1909 {
1910 if (!m_isVirtual)
1911 {
1912 lcItem = (wxMacListCtrlItem*) itemID;
1913 if (lcItem->HasColumnInfo(listColumn)){
1914 wxListItem* item = lcItem->GetColumnInfo(listColumn);
1915
1916 // we always use the 0 column to get font and text/background colors.
1917 if (lcItem->HasColumnInfo(0))
1918 {
1919 wxListItem* firstItem = lcItem->GetColumnInfo(0);
1920 color = firstItem->GetTextColour();
1921 bgColor = firstItem->GetBackgroundColour();
1922 font = firstItem->GetFont();
1923 }
1924
1925 if (item->GetMask() & wxLIST_MASK_TEXT)
1926 text = item->GetText();
1927 if (item->GetMask() & wxLIST_MASK_IMAGE)
1928 imgIndex = item->GetImage();
1929 }
1930
1931 }
1932 else
1933 {
1934 text = list->OnGetItemText( (long)itemID-1, listColumn );
1935 imgIndex = list->OnGetItemColumnImage( (long)itemID-1, listColumn );
1936 wxListItemAttr* attrs = list->OnGetItemAttr( (long)itemID-1 );
1937 if (attrs)
1938 {
1939 if (attrs->HasBackgroundColour())
1940 bgColor = attrs->GetBackgroundColour();
1941 if (attrs->HasTextColour())
1942 color = attrs->GetTextColour();
1943 if (attrs->HasFont())
1944 font = attrs->GetFont();
1945 }
1946 }
1947 }
1948
1949 wxColour listBgColor = list->GetBackgroundColour();
1950 if (bgColor == wxNullColour)
1951 bgColor = listBgColor;
1952
1953 wxFont listFont = list->GetFont();
1954 if (font == wxNullFont)
1955 font = listFont;
1956
1957 wxMacCFStringHolder cfString;
1958 cfString.Assign( text, wxLocale::GetSystemEncoding() );
1959
1960 Rect enclosingRect;
1961 CGRect enclosingCGRect, iconCGRect, textCGRect;
1962 Boolean active;
1963 ThemeDrawingState savedState = NULL;
1964 CGContextRef context = (CGContextRef)list->MacGetDrawingContext();
1965 RGBColor labelColor;
1966
1967 GetDataBrowserItemPartBounds(GetControlRef(), itemID, property, kDataBrowserPropertyEnclosingPart,
1968 &enclosingRect);
1969
1970 enclosingCGRect = CGRectMake(enclosingRect.left,
1971 enclosingRect.top,
1972 enclosingRect.right - enclosingRect.left,
1973 enclosingRect.bottom - enclosingRect.top);
1974
1975 active = IsControlActive(GetControlRef());
1976
1977 if (itemState == kDataBrowserItemIsSelected)
1978 {
1979 RGBColor foregroundColor;
1980
1981 GetThemeDrawingState(&savedState);
1982
1983 GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, 32, true, &foregroundColor);
1984 GetThemeTextColor(kThemeTextColorWhite, gdDepth, colorDevice, &labelColor);
1985
1986 CGContextSaveGState(context);
1987
1988 CGContextSetRGBFillColor(context, (float)foregroundColor.red / (float)USHRT_MAX,
1989 (float)foregroundColor.green / (float)USHRT_MAX,
1990 (float)foregroundColor.blue / (float)USHRT_MAX, 1.0);
1991 CGContextFillRect(context, enclosingCGRect);
1992
1993 CGContextRestoreGState(context);
1994 }
1995 else
1996 {
1997
1998 if (color.Ok())
1999 labelColor = MAC_WXCOLORREF( color.GetPixel() );
2000 else if (list->GetTextColour().Ok())
2001 labelColor = MAC_WXCOLORREF( list->GetTextColour().GetPixel() );
2002 else
2003 {
2004 labelColor.red = 0;
2005 labelColor.green = 0;
2006 labelColor.blue = 0;
2007 }
2008
2009 if (bgColor.Ok())
2010 {
2011 RGBColor foregroundColor = MAC_WXCOLORREF( bgColor.GetPixel() );
2012 CGContextSaveGState(context);
2013
2014 CGContextSetRGBFillColor(context, (float)foregroundColor.red / (float)USHRT_MAX,
2015 (float)foregroundColor.green / (float)USHRT_MAX,
2016 (float)foregroundColor.blue / (float)USHRT_MAX, 1.0);
2017 CGContextFillRect(context, enclosingCGRect);
2018
2019 CGContextRestoreGState(context);
2020 }
2021 }
2022
2023 calculateCGDrawingBounds(enclosingCGRect, &iconCGRect, &textCGRect, (imgIndex != -1) );
2024
2025 if (imgIndex != -1)
2026 {
2027 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
2028 if (imageList && imageList->GetImageCount() > 0){
2029 wxBitmap bmp = imageList->GetBitmap(imgIndex);
2030 IconRef icon = bmp.GetBitmapData()->GetIconRef();
2031
2032 RGBColor iconLabel;
2033 iconLabel.red = 0;
2034 iconLabel.green = 0;
2035 iconLabel.blue = 0;
2036
2037 PlotIconRefInContext(context, &iconCGRect, kAlignNone,
2038 active ? kTransformNone : kTransformDisabled, &iconLabel,
2039 kPlotIconRefNormalFlags, icon);
2040 }
2041 }
2042
2043 HIThemeTextHorizontalFlush hFlush = kHIThemeTextHorizontalFlushLeft;
2044 UInt16 fontID = kThemeViewsFont;
2045
2046 if (font.Ok())
2047 {
2048 if (font.GetFamily() != wxFONTFAMILY_DEFAULT)
2049 fontID = font.MacGetThemeFontID();
2050
2051 // FIXME: replace these with CG or ATSUI calls so we can remove this #ifndef.
2052 #ifndef __LP64__
2053 ::TextSize( (short)(font.MacGetFontSize()) ) ;
2054 ::TextFace( font.MacGetFontStyle() ) ;
2055 #endif
2056 }
2057
2058 wxListItem item;
2059 list->GetColumn(listColumn, item);
2060 if (item.GetMask() & wxLIST_MASK_FORMAT)
2061 {
2062 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
2063 hFlush = kHIThemeTextHorizontalFlushLeft;
2064 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
2065 hFlush = kHIThemeTextHorizontalFlushCenter;
2066 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
2067 {
2068 hFlush = kHIThemeTextHorizontalFlushRight;
2069 textCGRect.origin.x -= kItemPadding; // give a little extra paddding
2070 }
2071 }
2072
2073 HIThemeTextInfo info;
2074 info.version = kHIThemeTextInfoVersionZero;
2075 info.state = active ? kThemeStateActive : kThemeStateInactive;
2076 info.fontID = fontID;
2077 info.horizontalFlushness = hFlush;
2078 info.verticalFlushness = kHIThemeTextVerticalFlushCenter;
2079 info.options = kHIThemeTextBoxOptionNone;
2080 info.truncationPosition = kHIThemeTextTruncationEnd;
2081 info.truncationMaxLines = 1;
2082
2083 CGContextSaveGState(context);
2084 CGContextSetRGBFillColor (context, (float)labelColor.red / (float)USHRT_MAX,
2085 (float)labelColor.green / (float)USHRT_MAX,
2086 (float)labelColor.blue / (float)USHRT_MAX, 1.0);
2087
2088 HIThemeDrawTextBox(cfString, &textCGRect, &info, context, kHIThemeOrientationNormal);
2089
2090 CGContextRestoreGState(context);
2091
2092 if (savedState != NULL)
2093 SetThemeDrawingState(savedState, true);
2094 }
2095
2096 OSStatus wxMacDataBrowserListCtrlControl::GetSetItemData(DataBrowserItemID itemID,
2097 DataBrowserPropertyID property,
2098 DataBrowserItemDataRef itemData,
2099 Boolean changeValue )
2100 {
2101 wxString text;
2102 int imgIndex = -1;
2103 short listColumn = property - kMinColumnId;
2104
2105 OSStatus err = errDataBrowserPropertyNotSupported;
2106 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
2107 wxMacListCtrlItem* lcItem;
2108
2109 if (listColumn >= 0)
2110 {
2111 if (!m_isVirtual)
2112 {
2113 lcItem = (wxMacListCtrlItem*) itemID;
2114 if (lcItem->HasColumnInfo(listColumn)){
2115 wxListItem* item = lcItem->GetColumnInfo(listColumn);
2116 if (item->GetMask() & wxLIST_MASK_TEXT)
2117 text = item->GetText();
2118 if (item->GetMask() & wxLIST_MASK_IMAGE)
2119 imgIndex = item->GetImage();
2120 }
2121 }
2122 else
2123 {
2124 text = list->OnGetItemText( (long)itemID-1, listColumn );
2125 imgIndex = list->OnGetItemColumnImage( (long)itemID-1, listColumn );
2126 }
2127 }
2128
2129 if ( !changeValue )
2130 {
2131 switch (property)
2132 {
2133 case kDataBrowserItemIsEditableProperty :
2134 if ( list && list->HasFlag( wxLC_EDIT_LABELS ) )
2135 {
2136 verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
2137 err = noErr ;
2138 }
2139 break ;
2140 default :
2141 if ( property >= kMinColumnId )
2142 {
2143 wxMacCFStringHolder cfStr;
2144
2145 if (text){
2146 cfStr.Assign( text, wxLocale::GetSystemEncoding() );
2147 err = ::SetDataBrowserItemDataText( itemData, cfStr );
2148 err = noErr;
2149 }
2150
2151
2152
2153 if ( imgIndex != -1 )
2154 {
2155 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
2156 if (imageList && imageList->GetImageCount() > 0){
2157 wxBitmap bmp = imageList->GetBitmap(imgIndex);
2158 IconRef icon = bmp.GetBitmapData()->GetIconRef();
2159 ::SetDataBrowserItemDataIcon(itemData, icon);
2160 }
2161 }
2162
2163 }
2164 break ;
2165 }
2166
2167 }
2168 else
2169 {
2170 switch (property)
2171 {
2172 default:
2173 if ( property >= kMinColumnId )
2174 {
2175 short listColumn = property - kMinColumnId;
2176
2177 // TODO probably send the 'end edit' from here, as we
2178 // can then deal with the veto
2179 CFStringRef sr ;
2180 verify_noerr( GetDataBrowserItemDataText( itemData , &sr ) ) ;
2181 wxMacCFStringHolder cfStr(sr) ;;
2182 if (m_isVirtual)
2183 list->SetItem( (long)itemData-1 , listColumn, cfStr.AsString() ) ;
2184 else
2185 {
2186 if (lcItem)
2187 lcItem->SetColumnTextValue( listColumn, cfStr.AsString() );
2188 }
2189 err = noErr ;
2190 }
2191 break;
2192 }
2193 }
2194 return err;
2195 }
2196
2197 void wxMacDataBrowserListCtrlControl::ItemNotification(DataBrowserItemID itemID,
2198 DataBrowserItemNotification message,
2199 DataBrowserItemDataRef itemData )
2200 {
2201 // we want to depend on as little as possible to make sure tear-down of controls is safe
2202 if ( message == kDataBrowserItemRemoved)
2203 {
2204 // make sure MacDelete does the proper teardown.
2205 return;
2206 }
2207 else if ( message == kDataBrowserItemAdded )
2208 {
2209 // we don't issue events on adding, the item is not really stored in the list yet, so we
2210 // avoid asserts by getting out now
2211 return ;
2212 }
2213
2214 wxListCtrl *list = wxDynamicCast( GetPeer() , wxListCtrl );
2215 if ( list )
2216 {
2217 bool trigger = false;
2218
2219 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
2220 bool isSingle = (list->GetWindowStyle() & wxLC_SINGLE_SEL) != 0;
2221
2222 event.SetEventObject( list );
2223 if ( !list->IsVirtual() )
2224 {
2225 DataBrowserTableViewRowIndex result = 0;
2226 verify_noerr( GetItemRow( itemID, &result ) ) ;
2227 event.m_itemIndex = result;
2228
2229 if (event.m_itemIndex >= 0)
2230 MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
2231 }
2232 else
2233 {
2234 event.m_itemIndex = (long)itemID;
2235 }
2236
2237 switch (message)
2238 {
2239 case kDataBrowserItemDeselected:
2240 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
2241 if ( !isSingle )
2242 trigger = !IsSelectionSuppressed();
2243 break;
2244
2245 case kDataBrowserItemSelected:
2246 trigger = !IsSelectionSuppressed();
2247
2248 break;
2249
2250 case kDataBrowserItemDoubleClicked:
2251 event.SetEventType( wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
2252 trigger = true;
2253 break;
2254
2255 case kDataBrowserEditStarted :
2256 // TODO : how to veto ?
2257 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
2258 trigger = true ;
2259 break ;
2260
2261 case kDataBrowserEditStopped :
2262 // TODO probably trigger only upon the value store callback, because
2263 // here IIRC we cannot veto
2264 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
2265 trigger = true ;
2266 break ;
2267
2268 default:
2269 break;
2270 }
2271
2272 if ( trigger )
2273 {
2274 // direct notification is not always having the listbox GetSelection() having in synch with event
2275 wxPostEvent( list->GetEventHandler(), event );
2276 }
2277 }
2278 }
2279
2280 Boolean wxMacDataBrowserListCtrlControl::CompareItems(DataBrowserItemID itemOneID,
2281 DataBrowserItemID itemTwoID,
2282 DataBrowserPropertyID sortProperty)
2283 {
2284
2285 bool retval = false;
2286 wxString itemText;
2287 wxString otherItemText;
2288 int colId = sortProperty - kMinColumnId;
2289 long itemNum = 0;
2290 long otherItemNum = 0;
2291
2292 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
2293
2294 // means we need to
2295 if (colId >= 0)
2296 {
2297 if (!m_isVirtual)
2298 {
2299 wxMacListCtrlItem* item = (wxMacListCtrlItem*)itemOneID;
2300 wxMacListCtrlItem* otherItem = (wxMacListCtrlItem*)itemTwoID;
2301 wxListCtrlCompare func = list->GetCompareFunc();
2302 if (func != NULL && item->HasColumnInfo(colId) && otherItem->HasColumnInfo(colId))
2303 return func(item->GetColumnInfo(colId)->GetData(), otherItem->GetColumnInfo(colId)->GetData(), list->GetCompareFuncData()) >= 0;
2304
2305 itemNum = item->GetOrder();
2306 otherItemNum = otherItem->GetOrder();
2307 if (item->HasColumnInfo(colId))
2308 itemText = item->GetColumnInfo(colId)->GetText();
2309 if (otherItem->HasColumnInfo(colId))
2310 otherItemText = otherItem->GetColumnInfo(colId)->GetText();
2311 }
2312 else
2313 {
2314 itemNum = (long)itemOneID;
2315 otherItemNum = (long)itemTwoID;
2316 itemText = list->OnGetItemText( itemNum-1, colId );
2317 otherItemText = list->OnGetItemText( otherItemNum-1, colId );
2318
2319 }
2320
2321 DataBrowserSortOrder sort;
2322 verify_noerr(GetSortOrder(&sort));
2323
2324 if ( sort == kDataBrowserOrderIncreasing )
2325 {
2326 retval = itemText.CmpNoCase( otherItemText ) > 0;
2327 }
2328 else if ( sort == kDataBrowserOrderDecreasing )
2329 {
2330 retval = itemText.CmpNoCase( otherItemText ) < 0;
2331 }
2332 }
2333 else{
2334 // fallback for undefined cases
2335 retval = itemOneID < itemTwoID;
2336 }
2337
2338 return retval;
2339 }
2340
2341 wxMacDataBrowserListCtrlControl::~wxMacDataBrowserListCtrlControl()
2342 {
2343 }
2344
2345 void wxMacDataBrowserListCtrlControl::MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item )
2346 {
2347 wxMacDataItem* dataItem = GetItemFromLine(row);
2348 if (item)
2349 {
2350 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
2351 listItem->SetColumnInfo( column, item );
2352 UpdateState(dataItem, item);
2353 }
2354 }
2355
2356 // apply changes that need to happen immediately, rather than when the
2357 // databrowser control fires a callback.
2358 void wxMacDataBrowserListCtrlControl::UpdateState(wxMacDataItem* dataItem, wxListItem* listItem)
2359 {
2360 bool isSelected = IsItemSelected( dataItem );
2361 bool isSelectedState = (listItem->GetState() == wxLIST_STATE_SELECTED);
2362
2363 // toggle the selection state if wxListInfo state and actual state don't match.
2364 if ( isSelected != isSelectedState )
2365 {
2366 DataBrowserSetOption options = kDataBrowserItemsAdd;
2367 if (!isSelectedState)
2368 options = kDataBrowserItemsRemove;
2369 SetSelectedItem(dataItem, options);
2370 }
2371 // TODO: Set column width if item width > than current column width
2372 }
2373
2374 void wxMacDataBrowserListCtrlControl::MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item )
2375 {
2376 wxMacDataItem* dataItem = GetItemFromLine(row);
2377 // CS should this guard against dataItem = 0 ? , as item is not a pointer if (item) is not appropriate
2378 //if (item)
2379 {
2380 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
2381 wxListItem* oldItem = listItem->GetColumnInfo( column );
2382
2383 long mask = item.GetMask();
2384 if ( !mask )
2385 // by default, get everything for backwards compatibility
2386 mask = -1;
2387
2388 if ( mask & wxLIST_MASK_TEXT )
2389 item.SetText(oldItem->GetText());
2390 if ( mask & wxLIST_MASK_IMAGE )
2391 item.SetImage(oldItem->GetImage());
2392 if ( mask & wxLIST_MASK_DATA )
2393 item.SetData(oldItem->GetData());
2394 if ( mask & wxLIST_MASK_STATE )
2395 item.SetState(oldItem->GetState());
2396 if ( mask & wxLIST_MASK_WIDTH )
2397 item.SetWidth(oldItem->GetWidth());
2398 if ( mask & wxLIST_MASK_FORMAT )
2399 item.SetAlign(oldItem->GetAlign());
2400
2401 item.SetTextColour(oldItem->GetTextColour());
2402 item.SetBackgroundColour(oldItem->GetBackgroundColour());
2403 item.SetFont(oldItem->GetFont());
2404 }
2405 }
2406
2407 void wxMacDataBrowserListCtrlControl::MacInsertItem( unsigned int n, wxListItem* item )
2408 {
2409 wxMacDataItemBrowserControl::MacInsert(n, item->GetText());
2410 MacSetColumnInfo(n, 0, item);
2411 }
2412
2413 wxMacDataItem* wxMacDataBrowserListCtrlControl::CreateItem()
2414 {
2415 return new wxMacListCtrlItem();
2416 }
2417
2418 wxMacListCtrlItem::wxMacListCtrlItem()
2419 {
2420 m_rowItems = wxListItemList();
2421 }
2422
2423 int wxMacListCtrlItem::GetColumnImageValue( unsigned int column )
2424 {
2425 return GetColumnInfo(column)->GetImage();
2426 }
2427
2428 void wxMacListCtrlItem::SetColumnImageValue( unsigned int column, int imageIndex )
2429 {
2430 GetColumnInfo(column)->SetImage(imageIndex);
2431 }
2432
2433 const wxString& wxMacListCtrlItem::GetColumnTextValue( unsigned int column )
2434 {
2435 if ( column == 0 )
2436 return GetLabel();
2437
2438 return GetColumnInfo(column)->GetText();
2439 }
2440
2441 void wxMacListCtrlItem::SetColumnTextValue( unsigned int column, const wxString& text )
2442 {
2443 GetColumnInfo(column)->SetText(text);
2444
2445 // for compatibility with superclass APIs
2446 if ( column == 0 )
2447 SetLabel(text);
2448 }
2449
2450 wxListItem* wxMacListCtrlItem::GetColumnInfo( unsigned int column )
2451 {
2452 wxListItemList::compatibility_iterator node = m_rowItems.Item( column );
2453 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
2454
2455 return node->GetData();
2456 }
2457
2458 bool wxMacListCtrlItem::HasColumnInfo( unsigned int column )
2459 {
2460 return m_rowItems.GetCount() > column;
2461 }
2462
2463 void wxMacListCtrlItem::SetColumnInfo( unsigned int column, wxListItem* item )
2464 {
2465
2466 if ( column >= m_rowItems.GetCount() )
2467 {
2468 wxListItem* listItem = new wxListItem(*item);
2469 m_rowItems.Append( listItem );
2470 }
2471 else
2472 {
2473 wxListItem* listItem = GetColumnInfo( column );
2474 long mask = item->GetMask();
2475 if (mask & wxLIST_MASK_TEXT)
2476 listItem->SetText(item->GetText());
2477 if (mask & wxLIST_MASK_DATA)
2478 listItem->SetData(item->GetData());
2479 if (mask & wxLIST_MASK_IMAGE)
2480 listItem->SetImage(item->GetImage());
2481 if (mask & wxLIST_MASK_STATE)
2482 listItem->SetState(item->GetState());
2483 if (mask & wxLIST_MASK_FORMAT)
2484 listItem->SetAlign(item->GetAlign());
2485 if (mask & wxLIST_MASK_WIDTH)
2486 listItem->SetWidth(item->GetWidth());
2487
2488 listItem->SetTextColour(item->GetTextColour());
2489 listItem->SetBackgroundColour(item->GetBackgroundColour());
2490 listItem->SetFont(item->GetFont());
2491 }
2492 }
2493
2494 #endif // wxUSE_LISTCTRL