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