]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listctrl_mac.cpp
PCH support.
[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
119 // so we can check for column clicks
120 static const EventTypeSpec eventList[] =
121 {
122 { kEventClassControl, kEventControlHit },
123 };
124
125 static pascal OSStatus wxMacListCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
126 {
127 OSStatus result = eventNotHandledErr ;
128
129 wxMacCarbonEvent cEvent( event ) ;
130
131 ControlRef controlRef ;
132 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
133
134 wxListCtrl *window = (wxListCtrl*) data ;
135 wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, window->GetId() );
136 le.SetEventObject( window );
137
138 switch ( GetEventKind( event ) )
139 {
140 // check if the column was clicked on and fire an event if so
141 case kEventControlHit :
142 {
143 ControlPartCode result = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart, typeControlPartCode) ;
144 if (result == kControlButtonPart){
145 DataBrowserPropertyID col;
146 GetDataBrowserSortProperty(controlRef, &col);
147 int column = col - kMinColumnId;
148 le.m_col = column;
149 window->GetEventHandler()->ProcessEvent( le );
150 }
151 result = CallNextEventHandler(handler, event);
152 break;
153 }
154 default :
155 break ;
156 }
157
158
159 return result ;
160 }
161
162 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacListCtrlEventHandler )
163
164 class wxMacListCtrlItem : public wxMacListBoxItem
165 {
166 public:
167 wxMacListCtrlItem();
168
169 virtual void Notification(wxMacDataItemBrowserControl *owner ,
170 DataBrowserItemNotification message,
171 DataBrowserItemDataRef itemData ) const;
172
173 virtual void SetColumnInfo( unsigned int column, wxListItem* item );
174 virtual wxListItem* GetColumnInfo( unsigned int column );
175 virtual bool HasColumnInfo( unsigned int column );
176
177 virtual void SetColumnTextValue( unsigned int column, const wxString& text );
178 virtual const wxString& GetColumnTextValue( unsigned int column );
179
180 virtual int GetColumnImageValue( unsigned int column );
181 virtual void SetColumnImageValue( unsigned int column, int imageIndex );
182
183 virtual ~wxMacListCtrlItem();
184 protected:
185 wxListItemList m_rowItems;
186 };
187
188 // TODO: Make a better name!!
189 class wxMacDataBrowserListCtrlControl : public wxMacDataItemBrowserControl
190 {
191 public:
192 wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style );
193 virtual ~wxMacDataBrowserListCtrlControl();
194
195 // create a list item (can be a subclass of wxMacListBoxItem)
196
197 virtual wxMacDataItem* CreateItem();
198
199 virtual void MacInsertItem( unsigned int n, wxListItem* item );
200 virtual void MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item );
201 virtual void MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item );
202 virtual void UpdateState(wxMacDataItem* dataItem, wxListItem* item);
203
204 protected:
205 // we need to override to provide specialized handling for virtual wxListCtrls
206 virtual OSStatus GetSetItemData(DataBrowserItemID itemID,
207 DataBrowserPropertyID property,
208 DataBrowserItemDataRef itemData,
209 Boolean changeValue );
210
211 virtual void ItemNotification(
212 DataBrowserItemID itemID,
213 DataBrowserItemNotification message,
214 DataBrowserItemDataRef itemData);
215
216 virtual Boolean CompareItems(DataBrowserItemID itemOneID,
217 DataBrowserItemID itemTwoID,
218 DataBrowserPropertyID sortProperty);
219
220 wxClientDataType m_clientDataItemsType;
221 bool m_isVirtual;
222
223 };
224
225 // TODO: This gives errors, find out why.
226 //BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
227 // EVT_PAINT(wxListCtrl::OnPaint)
228 //END_EVENT_TABLE()
229
230 // ============================================================================
231 // implementation
232 // ============================================================================
233
234 wxMacListControl* wxListCtrl::GetPeer() const
235 {
236 return dynamic_cast<wxMacListControl*>(m_peer);
237 }
238
239 // ----------------------------------------------------------------------------
240 // wxListCtrl construction
241 // ----------------------------------------------------------------------------
242
243 void wxListCtrl::Init()
244 {
245 m_imageListNormal = NULL;
246 m_imageListSmall = NULL;
247 m_imageListState = NULL;
248
249 // keep track of if we created our own image lists, or if they were assigned
250 // to us.
251 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = false;
252 m_colCount = 0;
253 m_count = 0;
254 m_textCtrl = NULL;
255 m_genericImpl = NULL;
256 m_dbImpl = NULL;
257 m_compareFunc = NULL;
258 m_compareFuncData = 0;
259 }
260
261 class wxGenericListCtrlHook : public wxGenericListCtrl
262 {
263 public:
264 wxGenericListCtrlHook(wxListCtrl* parent,
265 wxWindowID id,
266 const wxPoint& pos,
267 const wxSize& size,
268 long style,
269 const wxValidator& validator,
270 const wxString& name)
271 : wxGenericListCtrl(parent, id, pos, size, style, validator, name),
272 m_nativeListCtrl(parent)
273 {
274 }
275
276 protected:
277 virtual wxListItemAttr * OnGetItemAttr(long item) const
278 {
279 return m_nativeListCtrl->OnGetItemAttr(item);
280 }
281
282 virtual int OnGetItemImage(long item) const
283 {
284 return m_nativeListCtrl->OnGetItemImage(item);
285 }
286
287 virtual int OnGetItemColumnImage(long item, long column) const
288 {
289 return m_nativeListCtrl->OnGetItemColumnImage(item, column);
290 }
291
292 virtual wxString OnGetItemText(long item, long column) const
293 {
294 return m_nativeListCtrl->OnGetItemText(item, column);
295 }
296
297 wxListCtrl* m_nativeListCtrl;
298
299 };
300
301 bool wxListCtrl::Create(wxWindow *parent,
302 wxWindowID id,
303 const wxPoint& pos,
304 const wxSize& size,
305 long style,
306 const wxValidator& validator,
307 const wxString& name)
308 {
309
310 // for now, we'll always use the generic list control for ICON and LIST views,
311 // because they dynamically change the number of columns on resize.
312 // Also, allow the user to set it to use the list ctrl as well.
313 // Also, use generic list control in VIRTUAL mode.
314 if ( (wxSystemOptions::HasOption( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL )
315 && (wxSystemOptions::GetOptionInt( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL ) == 1)) ||
316 (style & wxLC_ICON) || (style & wxLC_SMALL_ICON) || (style & wxLC_LIST) /* || (style & wxLC_VIRTUAL) */ )
317 {
318 m_macIsUserPane = true;
319
320 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
321 return false;
322 m_genericImpl = new wxGenericListCtrlHook(this, id, pos, size, style, validator, name);
323 return true;
324 }
325
326 else
327 {
328 m_macIsUserPane = false;
329
330 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
331 return false;
332 m_dbImpl = new wxMacDataBrowserListCtrlControl( this, pos, size, style );
333 m_peer = m_dbImpl;
334
335 MacPostControlCreate( pos, size );
336
337 InstallControlEventHandler( m_peer->GetControlRef() , GetwxMacListCtrlEventHandlerUPP(),
338 GetEventTypeCount(eventList), eventList, this,
339 (EventHandlerRef *)&m_macListCtrlEventHandler);
340 }
341
342 return true;
343 }
344
345 wxListCtrl::~wxListCtrl()
346 {
347 if (m_ownsImageListNormal)
348 delete m_imageListNormal;
349 if (m_ownsImageListSmall)
350 delete m_imageListSmall;
351 if (m_ownsImageListState)
352 delete m_imageListState;
353 }
354
355 // ----------------------------------------------------------------------------
356 // set/get/change style
357 // ----------------------------------------------------------------------------
358
359 // Add or remove a single window style
360 void wxListCtrl::SetSingleStyle(long style, bool add)
361 {
362 long flag = GetWindowStyleFlag();
363
364 // Get rid of conflicting styles
365 if ( add )
366 {
367 if ( style & wxLC_MASK_TYPE)
368 flag = flag & ~wxLC_MASK_TYPE;
369 if ( style & wxLC_MASK_ALIGN )
370 flag = flag & ~wxLC_MASK_ALIGN;
371 if ( style & wxLC_MASK_SORT )
372 flag = flag & ~wxLC_MASK_SORT;
373 }
374
375 if ( add )
376 flag |= style;
377 else
378 flag &= ~style;
379
380 SetWindowStyleFlag(flag);
381 }
382
383 // Set the whole window style
384 void wxListCtrl::SetWindowStyleFlag(long flag)
385 {
386 if ( flag != m_windowStyle )
387 {
388 m_windowStyle = flag;
389
390 if (m_genericImpl)
391 {
392 m_genericImpl->SetWindowStyleFlag(flag);
393 }
394
395 Refresh();
396 }
397 }
398
399 void wxListCtrl::DoSetSize( int x, int y, int width, int height, int sizeFlags )
400 {
401 wxControl::DoSetSize(x, y, width, height, sizeFlags);
402
403 if (m_genericImpl)
404 m_genericImpl->SetSize(x, y, width, height, sizeFlags);
405 }
406
407 bool wxListCtrl::SetFont(const wxFont& font)
408 {
409 bool rv;
410 rv = wxControl::SetFont(font);
411 if (m_genericImpl)
412 rv = m_genericImpl->SetFont(font);
413 return rv;
414 }
415
416 bool wxListCtrl::SetForegroundColour(const wxColour& colour)
417 {
418 bool rv;
419 rv = wxControl::SetForegroundColour(colour);
420 if (m_genericImpl)
421 rv = m_genericImpl->SetForegroundColour(colour);
422 return rv;
423 }
424
425 bool wxListCtrl::SetBackgroundColour(const wxColour& colour)
426 {
427 bool rv;
428 rv = wxControl::SetBackgroundColour(colour);
429 if (m_genericImpl)
430 rv = m_genericImpl->SetBackgroundColour(colour);
431 return rv;
432 }
433
434 // ----------------------------------------------------------------------------
435 // accessors
436 // ----------------------------------------------------------------------------
437
438 // Gets information about this column
439 bool wxListCtrl::GetColumn(int col, wxListItem& item) const
440 {
441 if (m_genericImpl)
442 return m_genericImpl->GetColumn(col, item);
443
444 bool success = true;
445
446 if ( item.m_mask & wxLIST_MASK_TEXT )
447 {
448 }
449
450 if ( item.m_mask & wxLIST_MASK_FORMAT )
451 {
452 }
453
454 if ( item.m_mask & wxLIST_MASK_IMAGE )
455 {
456 }
457
458 if ( (item.m_mask & wxLIST_MASK_TEXT) )
459 {
460 }
461
462
463 return success;
464 }
465
466 // Sets information about this column
467 bool wxListCtrl::SetColumn(int col, wxListItem& item)
468 {
469 if (m_genericImpl)
470 return m_genericImpl->SetColumn(col, item);
471
472 return false;
473 }
474
475 int wxListCtrl::GetColumnCount() const
476 {
477 if (m_genericImpl)
478 return m_genericImpl->GetColumnCount();
479
480 if (m_dbImpl)
481 {
482 UInt32 count;
483 m_dbImpl->GetColumnCount(&count);
484 return count;
485 }
486
487 return m_colCount;
488 }
489
490 // Gets the column width
491 int wxListCtrl::GetColumnWidth(int col) const
492 {
493 if (m_genericImpl)
494 return m_genericImpl->GetColumnWidth(col);
495
496 if (m_dbImpl)
497 {
498 return m_dbImpl->GetColumnWidth(col);
499 }
500
501 return 0;
502 }
503
504 // Sets the column width
505 bool wxListCtrl::SetColumnWidth(int col, int width)
506 {
507 if (m_genericImpl)
508 return m_genericImpl->SetColumnWidth(col, width);
509
510 // TODO: This is setting the width of the first column
511 // to the entire window width; investigate why
512 // this is.
513
514 if (m_dbImpl)
515 {
516 int mywidth = width;
517 if (width == wxLIST_AUTOSIZE || width == wxLIST_AUTOSIZE_USEHEADER)
518 mywidth = 150;
519
520 if (col == -1)
521 {
522 for (int column = 0; column < GetColumnCount(); column++)
523 {
524 m_dbImpl->SetColumnWidth(col, mywidth);
525 }
526 }
527 else{
528 m_dbImpl->SetColumnWidth(col, mywidth);
529 }
530 return true;
531 }
532
533 return false;
534 }
535
536 // Gets the number of items that can fit vertically in the
537 // visible area of the list control (list or report view)
538 // or the total number of items in the list control (icon
539 // or small icon view)
540 int wxListCtrl::GetCountPerPage() const
541 {
542 if (m_genericImpl)
543 return m_genericImpl->GetCountPerPage();
544
545 if (m_dbImpl)
546 {
547 }
548
549 return 1;
550 }
551
552 // Gets the edit control for editing labels.
553 wxTextCtrl* wxListCtrl::GetEditControl() const
554 {
555 if (m_genericImpl)
556 return m_genericImpl->GetEditControl();
557
558 return NULL;
559 }
560
561 // Gets information about the item
562 bool wxListCtrl::GetItem(wxListItem& info) const
563 {
564 if (m_genericImpl)
565 return m_genericImpl->GetItem(info);
566
567 if (m_dbImpl)
568 m_dbImpl->MacGetColumnInfo(info.m_itemId, info.m_col, info);
569 bool success = true;
570 return success;
571 }
572
573 // Sets information about the item
574 bool wxListCtrl::SetItem(wxListItem& info)
575 {
576 if (m_genericImpl)
577 return m_genericImpl->SetItem(info);
578
579 if (m_dbImpl)
580 m_dbImpl->MacSetColumnInfo( info.m_itemId, info.m_col, &info );
581
582 return true;
583 }
584
585 long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
586 {
587 if (m_genericImpl)
588 return m_genericImpl->SetItem(index, col, label, imageId);
589
590 wxListItem info;
591 info.m_text = label;
592 info.m_mask = wxLIST_MASK_TEXT;
593 info.m_itemId = index;
594 info.m_col = col;
595 if ( imageId > -1 )
596 {
597 info.m_image = imageId;
598 info.m_mask |= wxLIST_MASK_IMAGE;
599 }
600 return SetItem(info);
601 }
602
603
604 // Gets the item state
605 int wxListCtrl::GetItemState(long item, long stateMask) const
606 {
607 if (m_genericImpl)
608 return m_genericImpl->GetItemState(item, stateMask);
609
610 wxListItem info;
611
612 info.m_mask = wxLIST_MASK_STATE;
613 info.m_stateMask = stateMask;
614 info.m_itemId = item;
615
616 if (!GetItem(info))
617 return 0;
618
619 return info.m_state;
620 }
621
622 // Sets the item state
623 bool wxListCtrl::SetItemState(long item, long state, long stateMask)
624 {
625 if (m_genericImpl)
626 return m_genericImpl->SetItemState(item, state, stateMask);
627
628 wxListItem info;
629 info.m_mask = wxLIST_MASK_STATE;
630 info.m_stateMask = stateMask;
631 info.m_state = state;
632 info.m_itemId = item;
633 return SetItem(info);
634 }
635
636 // Sets the item image
637 bool wxListCtrl::SetItemImage(long item, int image, int WXUNUSED(selImage))
638 {
639 return SetItemColumnImage(item, 0, image);
640 }
641
642 // Sets the item image
643 bool wxListCtrl::SetItemColumnImage(long item, long column, int image)
644 {
645 if (m_genericImpl)
646 return m_genericImpl->SetItemColumnImage(item, column, image);
647
648 wxListItem info;
649
650 info.m_mask = wxLIST_MASK_IMAGE;
651 info.m_image = image;
652 info.m_itemId = item;
653 info.m_col = column;
654
655 return SetItem(info);
656 }
657
658 // Gets the item text
659 wxString wxListCtrl::GetItemText(long item) const
660 {
661 if (m_genericImpl)
662 return m_genericImpl->GetItemText(item);
663
664 wxListItem info;
665
666 info.m_mask = wxLIST_MASK_TEXT;
667 info.m_itemId = item;
668
669 if (!GetItem(info))
670 return wxEmptyString;
671 return info.m_text;
672 }
673
674 // Sets the item text
675 void wxListCtrl::SetItemText(long item, const wxString& str)
676 {
677 if (m_genericImpl)
678 return m_genericImpl->SetItemText(item, str);
679
680 wxListItem info;
681
682 info.m_mask = wxLIST_MASK_TEXT;
683 info.m_itemId = item;
684 info.m_text = str;
685
686 SetItem(info);
687 }
688
689 // Gets the item data
690 long wxListCtrl::GetItemData(long item) const
691 {
692 if (m_genericImpl)
693 return m_genericImpl->GetItemData(item);
694
695 wxListItem info;
696
697 info.m_mask = wxLIST_MASK_DATA;
698 info.m_itemId = item;
699
700 if (!GetItem(info))
701 return 0;
702 return info.m_data;
703 }
704
705 // Sets the item data
706 bool wxListCtrl::SetItemData(long item, long data)
707 {
708 if (m_genericImpl)
709 return m_genericImpl->SetItemData(item, data);
710
711 wxListItem info;
712
713 info.m_mask = wxLIST_MASK_DATA;
714 info.m_itemId = item;
715 info.m_data = data;
716
717 return SetItem(info);
718 }
719
720 wxRect wxListCtrl::GetViewRect() const
721 {
722 wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
723 _T("wxListCtrl::GetViewRect() only works in icon mode") );
724
725 if (m_genericImpl)
726 return m_genericImpl->GetViewRect();
727
728 wxRect rect;
729 return rect;
730 }
731
732 // Gets the item rectangle
733 bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
734 {
735 if (m_genericImpl)
736 return m_genericImpl->GetItemRect(item, rect, code);
737
738 return true;
739 }
740
741 // Gets the item position
742 bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
743 {
744 if (m_genericImpl)
745 return m_genericImpl->GetItemPosition(item, pos);
746
747 bool success = false;
748
749 return success;
750 }
751
752 // Sets the item position.
753 bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
754 {
755 if (m_genericImpl)
756 return m_genericImpl->SetItemPosition(item, pos);
757
758 return false;
759 }
760
761 // Gets the number of items in the list control
762 int wxListCtrl::GetItemCount() const
763 {
764 if (m_genericImpl)
765 return m_genericImpl->GetItemCount();
766
767 if (m_dbImpl)
768 return m_dbImpl->MacGetCount();
769
770 return m_count;
771 }
772
773 void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
774 {
775 if (m_genericImpl)
776 m_genericImpl->SetItemSpacing(spacing, isSmall);
777 }
778
779 wxSize wxListCtrl::GetItemSpacing() const
780 {
781 if (m_genericImpl)
782 return m_genericImpl->GetItemSpacing();
783
784 return wxSize(0, 0);
785 }
786
787 void wxListCtrl::SetItemTextColour( long item, const wxColour &col )
788 {
789 if (m_genericImpl)
790 {
791 m_genericImpl->SetItemTextColour(item, col);
792 return;
793 }
794
795 wxListItem info;
796 info.m_itemId = item;
797 info.SetTextColour( col );
798 SetItem( info );
799 }
800
801 wxColour wxListCtrl::GetItemTextColour( long item ) const
802 {
803 if (m_genericImpl)
804 return m_genericImpl->GetItemTextColour(item);
805
806 if (m_dbImpl)
807 {
808 wxListItem info;
809 if (GetItem(info))
810 return info.GetTextColour();
811 }
812 return wxNullColour;
813 }
814
815 void wxListCtrl::SetItemBackgroundColour( long item, const wxColour &col )
816 {
817 if (m_genericImpl)
818 {
819 m_genericImpl->SetItemBackgroundColour(item, col);
820 return;
821 }
822
823 wxListItem info;
824 info.m_itemId = item;
825 info.SetBackgroundColour( col );
826 SetItem( info );
827 }
828
829 wxColour wxListCtrl::GetItemBackgroundColour( long item ) const
830 {
831 if (m_genericImpl)
832 return m_genericImpl->GetItemBackgroundColour(item);
833
834 if (m_dbImpl)
835 {
836 wxListItem info;
837 if (GetItem(info))
838 return info.GetBackgroundColour();
839 }
840 return wxNullColour;
841 }
842
843 void wxListCtrl::SetItemFont( long item, const wxFont &f )
844 {
845 if (m_genericImpl)
846 {
847 m_genericImpl->SetItemFont(item, f);
848 return;
849 }
850
851 wxListItem info;
852 info.m_itemId = item;
853 info.SetFont( f );
854 SetItem( info );
855 }
856
857 wxFont wxListCtrl::GetItemFont( long item ) const
858 {
859 if (m_genericImpl)
860 return m_genericImpl->GetItemFont(item);
861
862 if (m_dbImpl)
863 {
864 wxListItem info;
865 if (GetItem(info))
866 return info.GetFont();
867 }
868
869 return wxNullFont;
870 }
871
872 // Gets the number of selected items in the list control
873 int wxListCtrl::GetSelectedItemCount() const
874 {
875 if (m_genericImpl)
876 return m_genericImpl->GetSelectedItemCount();
877
878 if (m_dbImpl)
879 return m_dbImpl->GetSelectedItemCount(NULL, true);
880
881 return 0;
882 }
883
884 // Gets the text colour of the listview
885 wxColour wxListCtrl::GetTextColour() const
886 {
887 if (m_genericImpl)
888 return m_genericImpl->GetTextColour();
889
890 // TODO: we need owner drawn list items to customize text color.
891 if (m_dbImpl)
892 return *wxBLACK;
893
894 return wxNullColour;
895 }
896
897 // Sets the text colour of the listview
898 void wxListCtrl::SetTextColour(const wxColour& col)
899 {
900 if (m_genericImpl)
901 {
902 m_genericImpl->SetTextColour(col);
903 return;
904 }
905
906 // TODO: if we add owner-drawn item support for DataBrowser,
907 // consider supporting this property
908 }
909
910 // Gets the index of the topmost visible item when in
911 // list or report view
912 long wxListCtrl::GetTopItem() const
913 {
914 if (m_genericImpl)
915 return m_genericImpl->GetTopItem();
916
917 return 0;
918 }
919
920 // Searches for an item, starting from 'item'.
921 // 'geometry' is one of
922 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
923 // 'state' is a state bit flag, one or more of
924 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
925 // item can be -1 to find the first item that matches the
926 // specified flags.
927 // Returns the item or -1 if unsuccessful.
928 long wxListCtrl::GetNextItem(long item, int geom, int state) const
929 {
930 if (m_genericImpl)
931 return m_genericImpl->GetNextItem(item, geom, state);
932
933 if (m_dbImpl && geom == wxLIST_NEXT_ALL && state == wxLIST_STATE_SELECTED )
934 {
935 long count = m_dbImpl->MacGetCount() ;
936 for ( long line = item + 1 ; line < count; line++ )
937 {
938 wxMacDataItem* id = m_dbImpl->GetItemFromLine(line);
939 if ( m_dbImpl->IsItemSelected(id ) )
940 return line;
941 }
942 return -1;
943 }
944
945 return 0;
946 }
947
948
949 wxImageList *wxListCtrl::GetImageList(int which) const
950 {
951 if (m_genericImpl)
952 return m_genericImpl->GetImageList(which);
953
954 if ( which == wxIMAGE_LIST_NORMAL )
955 {
956 return m_imageListNormal;
957 }
958 else if ( which == wxIMAGE_LIST_SMALL )
959 {
960 return m_imageListSmall;
961 }
962 else if ( which == wxIMAGE_LIST_STATE )
963 {
964 return m_imageListState;
965 }
966 return NULL;
967 }
968
969 void wxListCtrl::SetImageList(wxImageList *imageList, int which)
970 {
971 if (m_genericImpl)
972 {
973 m_genericImpl->SetImageList(imageList, which);
974 return;
975 }
976
977 if ( which == wxIMAGE_LIST_NORMAL )
978 {
979 if (m_ownsImageListNormal) delete m_imageListNormal;
980 m_imageListNormal = imageList;
981 m_ownsImageListNormal = false;
982 }
983 else if ( which == wxIMAGE_LIST_SMALL )
984 {
985 if (m_ownsImageListSmall) delete m_imageListSmall;
986 m_imageListSmall = imageList;
987 m_ownsImageListSmall = false;
988 }
989 else if ( which == wxIMAGE_LIST_STATE )
990 {
991 if (m_ownsImageListState) delete m_imageListState;
992 m_imageListState = imageList;
993 m_ownsImageListState = false;
994 }
995 }
996
997 void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
998 {
999 if (m_genericImpl)
1000 {
1001 m_genericImpl->AssignImageList(imageList, which);
1002 return;
1003 }
1004
1005 SetImageList(imageList, which);
1006 if ( which == wxIMAGE_LIST_NORMAL )
1007 m_ownsImageListNormal = true;
1008 else if ( which == wxIMAGE_LIST_SMALL )
1009 m_ownsImageListSmall = true;
1010 else if ( which == wxIMAGE_LIST_STATE )
1011 m_ownsImageListState = true;
1012 }
1013
1014 // ----------------------------------------------------------------------------
1015 // Operations
1016 // ----------------------------------------------------------------------------
1017
1018 // Arranges the items
1019 bool wxListCtrl::Arrange(int flag)
1020 {
1021 if (m_genericImpl)
1022 return m_genericImpl->Arrange(flag);
1023 return false;
1024 }
1025
1026 // Deletes an item
1027 bool wxListCtrl::DeleteItem(long item)
1028 {
1029 if (m_genericImpl)
1030 return m_genericImpl->DeleteItem(item);
1031
1032 if (m_dbImpl)
1033 {
1034 m_dbImpl->MacDelete(item);
1035 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ITEM, GetId() );
1036 event.SetEventObject( this );
1037 event.m_itemIndex = item;
1038 GetEventHandler()->ProcessEvent( event );
1039
1040 }
1041 return true;
1042 }
1043
1044 // Deletes all items
1045 bool wxListCtrl::DeleteAllItems()
1046 {
1047 if (m_genericImpl)
1048 return m_genericImpl->DeleteAllItems();
1049
1050 if (m_dbImpl)
1051 {
1052 m_dbImpl->MacClear();
1053 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetId() );
1054 event.SetEventObject( this );
1055 GetEventHandler()->ProcessEvent( event );
1056 }
1057 return true;
1058 }
1059
1060 // Deletes all items
1061 bool wxListCtrl::DeleteAllColumns()
1062 {
1063 if (m_genericImpl)
1064 return m_genericImpl->DeleteAllColumns();
1065
1066 if (m_dbImpl)
1067 {
1068 UInt32 cols;
1069 m_dbImpl->GetColumnCount(&cols);
1070 for (UInt32 col = 0; col < cols; col++)
1071 {
1072 DeleteColumn(col);
1073 }
1074 }
1075
1076 return true;
1077 }
1078
1079 // Deletes a column
1080 bool wxListCtrl::DeleteColumn(int col)
1081 {
1082 if (m_genericImpl)
1083 return m_genericImpl->DeleteColumn(col);
1084
1085 if (m_dbImpl)
1086 {
1087 OSStatus err = m_dbImpl->RemoveColumn(col);
1088 return err == noErr;
1089 }
1090
1091 return true;
1092 }
1093
1094 // Clears items, and columns if there are any.
1095 void wxListCtrl::ClearAll()
1096 {
1097 if (m_genericImpl)
1098 {
1099 m_genericImpl->ClearAll();
1100 return;
1101 }
1102
1103 if (m_dbImpl)
1104 {
1105 DeleteAllItems();
1106 DeleteAllColumns();
1107 }
1108 }
1109
1110 wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
1111 {
1112 if (m_genericImpl)
1113 return m_genericImpl->EditLabel(item, textControlClass);
1114
1115 if (m_dbImpl)
1116 {
1117 wxMacDataItem* id = m_dbImpl->GetItemFromLine(item);
1118 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), (DataBrowserItemID)id, kMinColumnId) );
1119 }
1120 return NULL;
1121 }
1122
1123 // End label editing, optionally cancelling the edit
1124 bool wxListCtrl::EndEditLabel(bool cancel)
1125 {
1126 // TODO: generic impl. doesn't have this method - is it needed for us?
1127 if (m_genericImpl)
1128 return true; // m_genericImpl->EndEditLabel(cancel);
1129
1130 if (m_dbImpl)
1131 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), kDataBrowserNoItem, kMinColumnId) );
1132 return true;
1133 }
1134
1135 // Ensures this item is visible
1136 bool wxListCtrl::EnsureVisible(long item)
1137 {
1138 if (m_genericImpl)
1139 return m_genericImpl->EnsureVisible(item);
1140
1141 if (m_dbImpl)
1142 {
1143 wxMacDataItem* dataItem = m_dbImpl->GetItemFromLine(item);
1144 m_dbImpl->RevealItem(dataItem, kDataBrowserRevealWithoutSelecting);
1145 }
1146
1147 return true;
1148 }
1149
1150 // Find an item whose label matches this string, starting from the item after 'start'
1151 // or the beginning if 'start' is -1.
1152 long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
1153 {
1154 if (m_genericImpl)
1155 return m_genericImpl->FindItem(start, str, partial);
1156
1157 return -1;
1158 }
1159
1160 // Find an item whose data matches this data, starting from the item after 'start'
1161 // or the beginning if 'start' is -1.
1162 long wxListCtrl::FindItem(long start, long data)
1163 {
1164 if (m_genericImpl)
1165 return m_genericImpl->FindItem(start, data);
1166
1167 long idx = start + 1;
1168 long count = GetItemCount();
1169
1170 while (idx < count)
1171 {
1172 if (GetItemData(idx) == data)
1173 return idx;
1174 idx++;
1175 };
1176
1177 return -1;
1178 }
1179
1180 // Find an item nearest this position in the specified direction, starting from
1181 // the item after 'start' or the beginning if 'start' is -1.
1182 long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
1183 {
1184 if (m_genericImpl)
1185 return m_genericImpl->FindItem(start, pt, direction);
1186 return -1;
1187 }
1188
1189 // Determines which item (if any) is at the specified point,
1190 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
1191 long
1192 wxListCtrl::HitTest(const wxPoint& point, int& flags, long *ptrSubItem) const
1193 {
1194 if (m_genericImpl)
1195 return m_genericImpl->HitTest(point, flags, ptrSubItem);
1196
1197 return -1;
1198 }
1199
1200
1201 // Inserts an item, returning the index of the new item if successful,
1202 // -1 otherwise.
1203 long wxListCtrl::InsertItem(wxListItem& info)
1204 {
1205 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
1206
1207 if (m_genericImpl)
1208 return m_genericImpl->InsertItem(info);
1209
1210 if (m_dbImpl)
1211 {
1212 int count = GetItemCount();
1213
1214 if (info.m_itemId > count)
1215 info.m_itemId = count;
1216
1217 m_dbImpl->MacInsertItem(info.m_itemId, &info );
1218 wxListEvent event( wxEVT_COMMAND_LIST_INSERT_ITEM, GetId() );
1219 event.SetEventObject( this );
1220 event.m_itemIndex = info.m_itemId;
1221 GetEventHandler()->ProcessEvent( event );
1222 }
1223
1224 return info.m_itemId;
1225 }
1226
1227 long wxListCtrl::InsertItem(long index, const wxString& label)
1228 {
1229 if (m_genericImpl)
1230 return m_genericImpl->InsertItem(index, label);
1231
1232 wxListItem info;
1233 info.m_text = label;
1234 info.m_mask = wxLIST_MASK_TEXT;
1235 info.m_itemId = index;
1236 return InsertItem(info);
1237 }
1238
1239 // Inserts an image item
1240 long wxListCtrl::InsertItem(long index, int imageIndex)
1241 {
1242 if (m_genericImpl)
1243 return m_genericImpl->InsertItem(index, imageIndex);
1244
1245 wxListItem info;
1246 info.m_image = imageIndex;
1247 info.m_mask = wxLIST_MASK_IMAGE;
1248 info.m_itemId = index;
1249 return InsertItem(info);
1250 }
1251
1252 // Inserts an image/string item
1253 long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
1254 {
1255 if (m_genericImpl)
1256 return m_genericImpl->InsertItem(index, label, imageIndex);
1257
1258 wxListItem info;
1259 info.m_image = imageIndex;
1260 info.m_text = label;
1261 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
1262 info.m_itemId = index;
1263 return InsertItem(info);
1264 }
1265
1266 // For list view mode (only), inserts a column.
1267 long wxListCtrl::InsertColumn(long col, wxListItem& item)
1268 {
1269 if (m_genericImpl)
1270 return m_genericImpl->InsertColumn(col, item);
1271
1272 if (m_dbImpl)
1273 {
1274 if ( !(item.GetMask() & wxLIST_MASK_WIDTH) )
1275 item.SetWidth(150);
1276
1277 DataBrowserPropertyType type = kDataBrowserTextType;
1278 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
1279 if (imageList && imageList->GetImageCount() > 0)
1280 {
1281 wxBitmap bmp = imageList->GetBitmap(0);
1282 if (bmp.Ok())
1283 type = kDataBrowserIconAndTextType;
1284 }
1285
1286 SInt16 just = teFlushDefault;
1287 if (item.GetMask() & wxLIST_MASK_FORMAT)
1288 {
1289 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
1290 just = teFlushLeft;
1291 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
1292 just = teCenter;
1293 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
1294 just = teFlushRight;
1295 }
1296 m_dbImpl->InsertColumn(col, type, item.GetText(), just, item.GetWidth());
1297
1298 // set/remove options based on the wxListCtrl type.
1299 DataBrowserTableViewColumnID id;
1300 m_dbImpl->GetColumnIDFromIndex(col, &id);
1301 DataBrowserPropertyFlags flags;
1302 verify_noerr(m_dbImpl->GetPropertyFlags(id, &flags));
1303 if (GetWindowStyleFlag() & wxLC_EDIT_LABELS)
1304 flags |= kDataBrowserPropertyIsEditable;
1305
1306 if (GetWindowStyleFlag() & wxLC_VIRTUAL){
1307 flags &= ~kDataBrowserListViewSortableColumn;
1308 }
1309 verify_noerr(m_dbImpl->SetPropertyFlags(id, flags));
1310 }
1311
1312 return col;
1313 }
1314
1315 long wxListCtrl::InsertColumn(long col,
1316 const wxString& heading,
1317 int format,
1318 int width)
1319 {
1320 if (m_genericImpl)
1321 return m_genericImpl->InsertColumn(col, heading, format, width);
1322
1323 wxListItem item;
1324 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1325 item.m_text = heading;
1326 if ( width > -1 )
1327 {
1328 item.m_mask |= wxLIST_MASK_WIDTH;
1329 item.m_width = width;
1330 }
1331 item.m_format = format;
1332
1333 return InsertColumn(col, item);
1334 }
1335
1336 // scroll the control by the given number of pixels (exception: in list view,
1337 // dx is interpreted as number of columns)
1338 bool wxListCtrl::ScrollList(int dx, int dy)
1339 {
1340 if (m_genericImpl)
1341 return m_genericImpl->ScrollList(dx, dy);
1342
1343 if (m_dbImpl)
1344 {
1345 m_dbImpl->SetScrollPosition(dx, dy);
1346 }
1347 return true;
1348 }
1349
1350
1351 bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1352 {
1353 if (m_genericImpl)
1354 return m_genericImpl->SortItems(fn, data);
1355
1356 if (m_dbImpl)
1357 {
1358 m_compareFunc = fn;
1359 m_compareFuncData = data;
1360 }
1361
1362 return true;
1363 }
1364
1365 // ----------------------------------------------------------------------------
1366 // virtual list controls
1367 // ----------------------------------------------------------------------------
1368
1369 wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
1370 {
1371 // this is a pure virtual function, in fact - which is not really pure
1372 // because the controls which are not virtual don't need to implement it
1373 wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") );
1374
1375 return wxEmptyString;
1376 }
1377
1378 int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
1379 {
1380 wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
1381 -1,
1382 wxT("List control has an image list, OnGetItemImage or OnGetItemColumnImage should be overridden."));
1383 return -1;
1384 }
1385
1386 int wxListCtrl::OnGetItemColumnImage(long item, long column) const
1387 {
1388 if (!column)
1389 return OnGetItemImage(item);
1390
1391 return -1;
1392 }
1393
1394 wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
1395 {
1396 wxASSERT_MSG( item >= 0 && item < GetItemCount(),
1397 _T("invalid item index in OnGetItemAttr()") );
1398
1399 // no attributes by default
1400 return NULL;
1401 }
1402
1403 void wxListCtrl::SetItemCount(long count)
1404 {
1405 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
1406
1407 if (m_genericImpl)
1408 {
1409 m_genericImpl->SetItemCount(count);
1410 return;
1411 }
1412
1413 if (m_dbImpl)
1414 {
1415 // we need to temporarily disable the new item creation notification
1416 // procedure to speed things up
1417 // FIXME: Even this doesn't seem to help much...
1418 DataBrowserCallbacks callbacks;
1419 DataBrowserItemNotificationUPP itemUPP;
1420 GetDataBrowserCallbacks(m_dbImpl->GetControlRef(), &callbacks);
1421 itemUPP = callbacks.u.v1.itemNotificationCallback;
1422 callbacks.u.v1.itemNotificationCallback = 0;
1423 m_dbImpl->SetCallbacks(&callbacks);
1424 ::AddDataBrowserItems(m_dbImpl->GetControlRef(), kDataBrowserNoItem,
1425 count, NULL, kDataBrowserItemNoProperty);
1426 callbacks.u.v1.itemNotificationCallback = itemUPP;
1427 m_dbImpl->SetCallbacks(&callbacks);
1428 }
1429 m_count = count;
1430 }
1431
1432 void wxListCtrl::RefreshItem(long item)
1433 {
1434 if (m_genericImpl)
1435 {
1436 m_genericImpl->RefreshItem(item);
1437 return;
1438 }
1439
1440 wxRect rect;
1441 GetItemRect(item, rect);
1442 RefreshRect(rect);
1443 }
1444
1445 void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
1446 {
1447 if (m_genericImpl)
1448 {
1449 m_genericImpl->RefreshItems(itemFrom, itemTo);
1450 return;
1451 }
1452
1453 wxRect rect1, rect2;
1454 GetItemRect(itemFrom, rect1);
1455 GetItemRect(itemTo, rect2);
1456
1457 wxRect rect = rect1;
1458 rect.height = rect2.GetBottom() - rect1.GetTop();
1459
1460 RefreshRect(rect);
1461 }
1462
1463
1464 // wxMac internal data structures
1465
1466 wxMacListCtrlItem::~wxMacListCtrlItem()
1467 {
1468 }
1469
1470 void wxMacListCtrlItem::Notification(wxMacDataItemBrowserControl *owner ,
1471 DataBrowserItemNotification message,
1472 DataBrowserItemDataRef itemData ) const
1473 {
1474
1475 wxMacDataBrowserListCtrlControl *lb = dynamic_cast<wxMacDataBrowserListCtrlControl*>(owner);
1476
1477 // we want to depend on as little as possible to make sure tear-down of controls is safe
1478 if ( message == kDataBrowserItemRemoved)
1479 {
1480 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
1481 {
1482 delete (wxClientData*) (m_data);
1483 }
1484
1485 delete this;
1486 return;
1487 }
1488 else if ( message == kDataBrowserItemAdded )
1489 {
1490 // we don't issue events on adding, the item is not really stored in the list yet, so we
1491 // avoid asserts by gettting out now
1492 return ;
1493 }
1494
1495 wxListCtrl *list = wxDynamicCast( owner->GetPeer() , wxListCtrl );
1496 if ( list )
1497 {
1498 bool trigger = false;
1499
1500 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1501 bool isSingle = (list->GetWindowStyle() & wxLC_SINGLE_SEL) != 0;
1502
1503 event.SetEventObject( list );
1504 event.m_itemIndex = owner->GetLineFromItem( this ) ;
1505 if ( !list->IsVirtual() )
1506 {
1507 lb->MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1508 }
1509
1510 switch (message)
1511 {
1512 case kDataBrowserItemDeselected:
1513 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1514 if ( !isSingle )
1515 trigger = !lb->IsSelectionSuppressed();
1516 break;
1517
1518 case kDataBrowserItemSelected:
1519 trigger = !lb->IsSelectionSuppressed();
1520 break;
1521
1522 case kDataBrowserItemDoubleClicked:
1523 event.SetEventType( wxEVT_LEFT_DCLICK );
1524 trigger = true;
1525 break;
1526
1527 case kDataBrowserEditStarted :
1528 // TODO : how to veto ?
1529 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1530 trigger = true ;
1531 break ;
1532
1533 case kDataBrowserEditStopped :
1534 // TODO probably trigger only upon the value store callback, because
1535 // here IIRC we cannot veto
1536 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1537 trigger = true ;
1538 break ;
1539
1540 default:
1541 break;
1542 }
1543
1544 if ( trigger )
1545 {
1546 // direct notification is not always having the listbox GetSelection() having in synch with event
1547 wxPostEvent( list->GetEventHandler(), event );
1548 }
1549 }
1550
1551 }
1552
1553 wxMacDataBrowserListCtrlControl::wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
1554 : wxMacDataItemBrowserControl( peer, pos, size, style )
1555 {
1556 OSStatus err = noErr;
1557 m_clientDataItemsType = wxClientData_None;
1558 m_isVirtual = false;
1559
1560 if ( style & wxLC_VIRTUAL )
1561 m_isVirtual = true;
1562
1563 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
1564 if ( style & wxLC_SINGLE_SEL )
1565 {
1566 options |= kDataBrowserSelectOnlyOne;
1567 }
1568 else
1569 {
1570 options |= kDataBrowserCmdTogglesSelection;
1571 }
1572
1573 err = SetSelectionFlags( options );
1574 verify_noerr( err );
1575
1576 if ( style & wxLC_LIST )
1577 {
1578 InsertColumn(0, kDataBrowserIconAndTextType, wxEmptyString, -1, -1);
1579 verify_noerr( AutoSizeColumns() );
1580 }
1581
1582 if ( style & wxLC_LIST || style & wxLC_NO_HEADER )
1583 verify_noerr( SetHeaderButtonHeight( 0 ) );
1584
1585 if ( m_isVirtual )
1586 SetSortProperty( kMinColumnId - 1 );
1587 else
1588 SetSortProperty( kMinColumnId );
1589 if ( style & wxLC_SORT_ASCENDING )
1590 {
1591 m_sortOrder = SortOrder_Text_Ascending;
1592 SetSortOrder( kDataBrowserOrderIncreasing );
1593 }
1594 else if ( style & wxLC_SORT_DESCENDING )
1595 {
1596 m_sortOrder = SortOrder_Text_Descending;
1597 SetSortOrder( kDataBrowserOrderDecreasing );
1598 }
1599 else
1600 {
1601 m_sortOrder = SortOrder_None;
1602 }
1603
1604 if ( style & wxLC_VRULES )
1605 {
1606 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1607 verify_noerr( DataBrowserChangeAttributes(m_controlRef, kDataBrowserAttributeListViewDrawColumnDividers, kDataBrowserAttributeNone) );
1608 #endif
1609 }
1610
1611 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
1612 err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
1613 }
1614
1615 OSStatus wxMacDataBrowserListCtrlControl::GetSetItemData(DataBrowserItemID itemID,
1616 DataBrowserPropertyID property,
1617 DataBrowserItemDataRef itemData,
1618 Boolean changeValue )
1619 {
1620 wxString text;
1621 int imgIndex = -1;
1622 short listColumn = property - kMinColumnId;
1623
1624 OSStatus err = errDataBrowserPropertyNotSupported;
1625 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1626 wxMacListCtrlItem* lcItem;
1627
1628 if (listColumn >= 0)
1629 {
1630 if (!m_isVirtual)
1631 {
1632 lcItem = (wxMacListCtrlItem*) itemID;
1633 if (lcItem->HasColumnInfo(listColumn)){
1634 wxListItem* item = lcItem->GetColumnInfo(listColumn);
1635 if (item->GetMask() & wxLIST_MASK_TEXT)
1636 text = item->GetText();
1637 if (item->GetMask() & wxLIST_MASK_IMAGE)
1638 imgIndex = item->GetImage();
1639 }
1640 }
1641 else
1642 {
1643 text = list->OnGetItemText( (long)itemID-1, listColumn );
1644 imgIndex = list->OnGetItemColumnImage( (long)itemID-1, listColumn );
1645 }
1646 }
1647
1648 if ( !changeValue )
1649 {
1650 switch (property)
1651 {
1652 case kDataBrowserItemIsEditableProperty :
1653 if ( list && list->HasFlag( wxLC_EDIT_LABELS ) )
1654 {
1655 verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
1656 err = noErr ;
1657 }
1658 break ;
1659 default :
1660 if ( property >= kMinColumnId )
1661 {
1662 wxMacCFStringHolder cfStr;
1663
1664 if (text){
1665 cfStr.Assign( text, wxLocale::GetSystemEncoding() );
1666 err = ::SetDataBrowserItemDataText( itemData, cfStr );
1667 err = noErr;
1668 }
1669
1670
1671
1672 if ( imgIndex != -1 )
1673 {
1674 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
1675 if (imageList && imageList->GetImageCount() > 0){
1676 wxBitmap bmp = imageList->GetBitmap(imgIndex);
1677 IconRef icon = bmp.GetBitmapData()->GetIconRef();
1678 ::SetDataBrowserItemDataIcon(itemData, icon);
1679 }
1680 }
1681
1682 }
1683 break ;
1684 }
1685
1686 }
1687 else
1688 {
1689 switch (property)
1690 {
1691 default:
1692 if ( property >= kMinColumnId )
1693 {
1694 short listColumn = property - kMinColumnId;
1695
1696 // TODO probably send the 'end edit' from here, as we
1697 // can then deal with the veto
1698 CFStringRef sr ;
1699 verify_noerr( GetDataBrowserItemDataText( itemData , &sr ) ) ;
1700 wxMacCFStringHolder cfStr(sr) ;;
1701 if (m_isVirtual)
1702 list->SetItem( (long)itemData-1 , listColumn, cfStr.AsString() ) ;
1703 else
1704 {
1705 if (lcItem)
1706 lcItem->SetColumnTextValue( listColumn, cfStr.AsString() );
1707 }
1708 err = noErr ;
1709 }
1710 break;
1711 }
1712 }
1713 return err;
1714 }
1715
1716 void wxMacDataBrowserListCtrlControl::ItemNotification(DataBrowserItemID itemID,
1717 DataBrowserItemNotification message,
1718 DataBrowserItemDataRef itemData )
1719 {
1720 // we want to depend on as little as possible to make sure tear-down of controls is safe
1721 if ( message == kDataBrowserItemRemoved)
1722 {
1723 // make sure MacDelete does the proper teardown.
1724 return;
1725 }
1726 else if ( message == kDataBrowserItemAdded )
1727 {
1728 // we don't issue events on adding, the item is not really stored in the list yet, so we
1729 // avoid asserts by getting out now
1730 return ;
1731 }
1732
1733 wxListCtrl *list = wxDynamicCast( GetPeer() , wxListCtrl );
1734 if ( list )
1735 {
1736 bool trigger = false;
1737
1738 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1739 bool isSingle = (list->GetWindowStyle() & wxLC_SINGLE_SEL) != 0;
1740
1741 event.SetEventObject( list );
1742 if ( !list->IsVirtual() )
1743 {
1744 DataBrowserTableViewRowIndex result = 0;
1745 verify_noerr( GetItemRow( itemID, &result ) ) ;
1746 event.m_itemIndex = result;
1747
1748 if (event.m_itemIndex >= 0)
1749 MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1750 }
1751 else
1752 {
1753 event.m_itemIndex = (long)itemID;
1754 }
1755
1756 switch (message)
1757 {
1758 case kDataBrowserItemDeselected:
1759 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1760 if ( !isSingle )
1761 trigger = IsSelectionSuppressed();
1762 break;
1763
1764 case kDataBrowserItemSelected:
1765 trigger = IsSelectionSuppressed();
1766 break;
1767
1768 case kDataBrowserItemDoubleClicked:
1769 event.SetEventType( wxEVT_LEFT_DCLICK );
1770 trigger = true;
1771 break;
1772
1773 case kDataBrowserEditStarted :
1774 // TODO : how to veto ?
1775 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1776 trigger = true ;
1777 break ;
1778
1779 case kDataBrowserEditStopped :
1780 // TODO probably trigger only upon the value store callback, because
1781 // here IIRC we cannot veto
1782 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1783 trigger = true ;
1784 break ;
1785
1786 default:
1787 break;
1788 }
1789
1790 if ( trigger )
1791 {
1792 // direct notification is not always having the listbox GetSelection() having in synch with event
1793 wxPostEvent( list->GetEventHandler(), event );
1794 }
1795 }
1796 }
1797
1798 Boolean wxMacDataBrowserListCtrlControl::CompareItems(DataBrowserItemID itemOneID,
1799 DataBrowserItemID itemTwoID,
1800 DataBrowserPropertyID sortProperty)
1801 {
1802
1803 bool retval = false;
1804 wxString itemText;
1805 wxString otherItemText;
1806 int colId = sortProperty - kMinColumnId;
1807 long itemNum = 0;
1808 long otherItemNum = 0;
1809
1810 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1811
1812 // means we need to
1813 if (colId >= 0)
1814 {
1815 if (!m_isVirtual)
1816 {
1817 wxMacListCtrlItem* item = (wxMacListCtrlItem*)itemOneID;
1818 wxMacListCtrlItem* otherItem = (wxMacListCtrlItem*)itemTwoID;
1819 wxListCtrlCompare func = list->GetCompareFunc();
1820 if (func != NULL && item->HasColumnInfo(colId) && otherItem->HasColumnInfo(colId))
1821 return func(item->GetColumnInfo(colId)->GetData(), otherItem->GetColumnInfo(colId)->GetData(), list->GetCompareFuncData()) >= 0;
1822
1823 itemNum = item->GetOrder();
1824 otherItemNum = otherItem->GetOrder();
1825 if (item->HasColumnInfo(colId))
1826 itemText = item->GetColumnInfo(colId)->GetText();
1827 if (otherItem->HasColumnInfo(colId))
1828 otherItemText = otherItem->GetColumnInfo(colId)->GetText();
1829 }
1830 else
1831 {
1832 itemNum = (long)itemOneID;
1833 otherItemNum = (long)itemTwoID;
1834 itemText = list->OnGetItemText( itemNum-1, colId );
1835 otherItemText = list->OnGetItemText( otherItemNum-1, colId );
1836
1837 }
1838
1839 DataBrowserSortOrder sort;
1840 verify_noerr(GetSortOrder(&sort));
1841
1842 if ( sort == kDataBrowserOrderIncreasing )
1843 {
1844 retval = itemText.CmpNoCase( otherItemText ) > 0;
1845 }
1846 else if ( sort == kDataBrowserOrderDecreasing )
1847 {
1848 retval = itemText.CmpNoCase( otherItemText ) < 0;
1849 }
1850 }
1851 else{
1852 // fallback for undefined cases
1853 retval = itemOneID < itemTwoID;
1854 }
1855
1856 return retval;
1857 }
1858
1859 wxMacDataBrowserListCtrlControl::~wxMacDataBrowserListCtrlControl()
1860 {
1861 }
1862
1863 void wxMacDataBrowserListCtrlControl::MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item )
1864 {
1865 wxMacDataItem* dataItem = GetItemFromLine(row);
1866 if (item)
1867 {
1868 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1869 listItem->SetColumnInfo( column, item );
1870 UpdateState(dataItem, item);
1871 }
1872 }
1873
1874 // apply changes that need to happen immediately, rather than when the
1875 // databrowser control fires a callback.
1876 void wxMacDataBrowserListCtrlControl::UpdateState(wxMacDataItem* dataItem, wxListItem* listItem)
1877 {
1878 bool isSelected = IsItemSelected( dataItem );
1879 bool isSelectedState = (listItem->GetState() == wxLIST_STATE_SELECTED);
1880
1881 // toggle the selection state if wxListInfo state and actual state don't match.
1882 if ( isSelected != isSelectedState )
1883 {
1884 DataBrowserSetOption options = kDataBrowserItemsAdd;
1885 if (!isSelectedState)
1886 options = kDataBrowserItemsRemove;
1887 SetSelectedItem(dataItem, options);
1888 }
1889 // TODO: Set column width if item width > than current column width
1890 }
1891
1892 void wxMacDataBrowserListCtrlControl::MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item )
1893 {
1894 wxMacDataItem* dataItem = GetItemFromLine(row);
1895 // CS should this guard against dataItem = 0 ? , as item is not a pointer if (item) is not appropriate
1896 //if (item)
1897 {
1898 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1899 wxListItem* oldItem = listItem->GetColumnInfo( column );
1900
1901 long mask = item.GetMask();
1902 if ( !mask )
1903 // by default, get everything for backwards compatibility
1904 mask = -1;
1905
1906 if ( mask & wxLIST_MASK_TEXT )
1907 item.SetText(oldItem->GetText());
1908 if ( mask & wxLIST_MASK_IMAGE )
1909 item.SetImage(oldItem->GetImage());
1910 if ( mask & wxLIST_MASK_DATA )
1911 item.SetData(oldItem->GetData());
1912 if ( mask & wxLIST_MASK_STATE )
1913 item.SetState(oldItem->GetState());
1914 if ( mask & wxLIST_MASK_WIDTH )
1915 item.SetWidth(oldItem->GetWidth());
1916 if ( mask & wxLIST_MASK_FORMAT )
1917 item.SetAlign(oldItem->GetAlign());
1918
1919 item.SetTextColour(oldItem->GetTextColour());
1920 item.SetBackgroundColour(oldItem->GetBackgroundColour());
1921 item.SetFont(oldItem->GetFont());
1922 }
1923 }
1924
1925 void wxMacDataBrowserListCtrlControl::MacInsertItem( unsigned int n, wxListItem* item )
1926 {
1927 wxMacDataItemBrowserControl::MacInsert(n, item->GetText());
1928 MacSetColumnInfo(n, 0, item);
1929 }
1930
1931 wxMacDataItem* wxMacDataBrowserListCtrlControl::CreateItem()
1932 {
1933 return new wxMacListCtrlItem();
1934 }
1935
1936 wxMacListCtrlItem::wxMacListCtrlItem()
1937 {
1938 m_rowItems = wxListItemList();
1939 }
1940
1941 int wxMacListCtrlItem::GetColumnImageValue( unsigned int column )
1942 {
1943 return GetColumnInfo(column)->GetImage();
1944 }
1945
1946 void wxMacListCtrlItem::SetColumnImageValue( unsigned int column, int imageIndex )
1947 {
1948 GetColumnInfo(column)->SetImage(imageIndex);
1949 }
1950
1951 const wxString& wxMacListCtrlItem::GetColumnTextValue( unsigned int column )
1952 {
1953 if ( column == 0 )
1954 return GetLabel();
1955
1956 return GetColumnInfo(column)->GetText();
1957 }
1958
1959 void wxMacListCtrlItem::SetColumnTextValue( unsigned int column, const wxString& text )
1960 {
1961 GetColumnInfo(column)->SetText(text);
1962
1963 // for compatibility with superclass APIs
1964 if ( column == 0 )
1965 SetLabel(text);
1966 }
1967
1968 wxListItem* wxMacListCtrlItem::GetColumnInfo( unsigned int column )
1969 {
1970 wxListItemList::compatibility_iterator node = m_rowItems.Item( column );
1971 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
1972
1973 return node->GetData();
1974 }
1975
1976 bool wxMacListCtrlItem::HasColumnInfo( unsigned int column )
1977 {
1978 return m_rowItems.GetCount() > column;
1979 }
1980
1981 void wxMacListCtrlItem::SetColumnInfo( unsigned int column, wxListItem* item )
1982 {
1983
1984 if ( column >= m_rowItems.GetCount() )
1985 {
1986 wxListItem* listItem = new wxListItem(*item);
1987 m_rowItems.Append( listItem );
1988 }
1989 else
1990 {
1991 wxListItem* listItem = GetColumnInfo( column );
1992 long mask = item->GetMask();
1993 if (mask & wxLIST_MASK_TEXT)
1994 listItem->SetText(item->GetText());
1995 if (mask & wxLIST_MASK_DATA)
1996 listItem->SetData(item->GetData());
1997 if (mask & wxLIST_MASK_IMAGE)
1998 listItem->SetImage(item->GetImage());
1999 if (mask & wxLIST_MASK_STATE)
2000 listItem->SetState(item->GetState());
2001 if (mask & wxLIST_MASK_FORMAT)
2002 listItem->SetAlign(item->GetAlign());
2003 if (mask & wxLIST_MASK_WIDTH)
2004 listItem->SetWidth(item->GetWidth());
2005 }
2006 }
2007
2008 #endif // wxUSE_LISTCTRL