]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listctrl_mac.cpp
46d53fe1bc821a2161882bb96765643cec060962
[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 return 0;
856 }
857
858
859 wxImageList *wxListCtrl::GetImageList(int which) const
860 {
861 if (m_genericImpl)
862 return m_genericImpl->GetImageList(which);
863
864 if ( which == wxIMAGE_LIST_NORMAL )
865 {
866 return m_imageListNormal;
867 }
868 else if ( which == wxIMAGE_LIST_SMALL )
869 {
870 return m_imageListSmall;
871 }
872 else if ( which == wxIMAGE_LIST_STATE )
873 {
874 return m_imageListState;
875 }
876 return NULL;
877 }
878
879 void wxListCtrl::SetImageList(wxImageList *imageList, int which)
880 {
881 if (m_genericImpl)
882 {
883 m_genericImpl->SetImageList(imageList, which);
884 return;
885 }
886
887 if ( which == wxIMAGE_LIST_NORMAL )
888 {
889 if (m_ownsImageListNormal) delete m_imageListNormal;
890 m_imageListNormal = imageList;
891 m_ownsImageListNormal = false;
892 }
893 else if ( which == wxIMAGE_LIST_SMALL )
894 {
895 if (m_ownsImageListSmall) delete m_imageListSmall;
896 m_imageListSmall = imageList;
897 m_ownsImageListSmall = false;
898 }
899 else if ( which == wxIMAGE_LIST_STATE )
900 {
901 if (m_ownsImageListState) delete m_imageListState;
902 m_imageListState = imageList;
903 m_ownsImageListState = false;
904 }
905 }
906
907 void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
908 {
909 if (m_genericImpl)
910 {
911 m_genericImpl->AssignImageList(imageList, which);
912 return;
913 }
914
915 SetImageList(imageList, which);
916 if ( which == wxIMAGE_LIST_NORMAL )
917 m_ownsImageListNormal = true;
918 else if ( which == wxIMAGE_LIST_SMALL )
919 m_ownsImageListSmall = true;
920 else if ( which == wxIMAGE_LIST_STATE )
921 m_ownsImageListState = true;
922 }
923
924 // ----------------------------------------------------------------------------
925 // Operations
926 // ----------------------------------------------------------------------------
927
928 // Arranges the items
929 bool wxListCtrl::Arrange(int flag)
930 {
931 if (m_genericImpl)
932 return m_genericImpl->Arrange(flag);
933 return false;
934 }
935
936 // Deletes an item
937 bool wxListCtrl::DeleteItem(long item)
938 {
939 if (m_genericImpl)
940 return m_genericImpl->DeleteItem(item);
941
942 if (m_dbImpl)
943 {
944 m_dbImpl->MacDelete(item);
945 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ITEM, GetId() );
946 event.SetEventObject( this );
947 event.m_itemIndex = item;
948 GetEventHandler()->ProcessEvent( event );
949
950 }
951 return true;
952 }
953
954 // Deletes all items
955 bool wxListCtrl::DeleteAllItems()
956 {
957 if (m_genericImpl)
958 return m_genericImpl->DeleteAllItems();
959
960 if (m_dbImpl)
961 {
962 m_dbImpl->MacClear();
963 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetId() );
964 event.SetEventObject( this );
965 GetEventHandler()->ProcessEvent( event );
966 }
967 return true;
968 }
969
970 // Deletes all items
971 bool wxListCtrl::DeleteAllColumns()
972 {
973 if (m_genericImpl)
974 return m_genericImpl->DeleteAllColumns();
975
976 if (m_dbImpl)
977 {
978 UInt32 cols;
979 m_dbImpl->GetColumnCount(&cols);
980 for (UInt32 col = 0; col < cols; col++)
981 {
982 DeleteColumn(col);
983 }
984 }
985
986 return true;
987 }
988
989 // Deletes a column
990 bool wxListCtrl::DeleteColumn(int col)
991 {
992 if (m_genericImpl)
993 return m_genericImpl->DeleteColumn(col);
994
995 if (m_dbImpl)
996 {
997 OSStatus err = m_dbImpl->RemoveColumn(col);
998 return err == noErr;
999 }
1000
1001 return true;
1002 }
1003
1004 // Clears items, and columns if there are any.
1005 void wxListCtrl::ClearAll()
1006 {
1007 if (m_genericImpl)
1008 {
1009 m_genericImpl->ClearAll();
1010 return;
1011 }
1012
1013 if (m_dbImpl)
1014 {
1015 DeleteAllItems();
1016 DeleteAllColumns();
1017 }
1018 }
1019
1020 wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
1021 {
1022 if (m_genericImpl)
1023 return m_genericImpl->EditLabel(item, textControlClass);
1024
1025 if (m_dbImpl)
1026 {
1027 wxMacDataItem* id = m_dbImpl->GetItemFromLine(item);
1028 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), (DataBrowserItemID)id, kMinColumnId) );
1029 }
1030 return NULL;
1031 }
1032
1033 // End label editing, optionally cancelling the edit
1034 bool wxListCtrl::EndEditLabel(bool cancel)
1035 {
1036 // TODO: generic impl. doesn't have this method - is it needed for us?
1037 if (m_genericImpl)
1038 return true; // m_genericImpl->EndEditLabel(cancel);
1039
1040 if (m_dbImpl)
1041 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), kDataBrowserNoItem, kMinColumnId) );
1042 return true;
1043 }
1044
1045 // Ensures this item is visible
1046 bool wxListCtrl::EnsureVisible(long item)
1047 {
1048 if (m_genericImpl)
1049 return m_genericImpl->EnsureVisible(item);
1050
1051 if (m_dbImpl)
1052 {
1053 wxMacDataItem* dataItem = m_dbImpl->GetItemFromLine(item);
1054 m_dbImpl->RevealItem(dataItem, kDataBrowserRevealWithoutSelecting);
1055 }
1056
1057 return true;
1058 }
1059
1060 // Find an item whose label matches this string, starting from the item after 'start'
1061 // or the beginning if 'start' is -1.
1062 long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
1063 {
1064 if (m_genericImpl)
1065 return m_genericImpl->FindItem(start, str, partial);
1066
1067 return -1;
1068 }
1069
1070 // Find an item whose data matches this data, starting from the item after 'start'
1071 // or the beginning if 'start' is -1.
1072 long wxListCtrl::FindItem(long start, long data)
1073 {
1074 if (m_genericImpl)
1075 return m_genericImpl->FindItem(start, data);
1076
1077 long idx = start + 1;
1078 long count = GetItemCount();
1079
1080 while (idx < count)
1081 {
1082 if (GetItemData(idx) == data)
1083 return idx;
1084 idx++;
1085 };
1086
1087 return -1;
1088 }
1089
1090 // Find an item nearest this position in the specified direction, starting from
1091 // the item after 'start' or the beginning if 'start' is -1.
1092 long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
1093 {
1094 if (m_genericImpl)
1095 return m_genericImpl->FindItem(start, pt, direction);
1096 return -1;
1097 }
1098
1099 // Determines which item (if any) is at the specified point,
1100 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
1101 long
1102 wxListCtrl::HitTest(const wxPoint& point, int& flags, long *ptrSubItem) const
1103 {
1104 if (m_genericImpl)
1105 return m_genericImpl->HitTest(point, flags, ptrSubItem);
1106
1107 return -1;
1108 }
1109
1110
1111 // Inserts an item, returning the index of the new item if successful,
1112 // -1 otherwise.
1113 long wxListCtrl::InsertItem(wxListItem& info)
1114 {
1115 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
1116
1117 if (m_genericImpl)
1118 return m_genericImpl->InsertItem(info);
1119
1120 if (m_dbImpl)
1121 {
1122 int count = GetItemCount();
1123
1124 if (info.m_itemId > count)
1125 info.m_itemId = count;
1126
1127 m_dbImpl->MacInsertItem(info.m_itemId, &info );
1128 wxListEvent event( wxEVT_COMMAND_LIST_INSERT_ITEM, GetId() );
1129 event.SetEventObject( this );
1130 event.m_itemIndex = info.m_itemId;
1131 GetEventHandler()->ProcessEvent( event );
1132 }
1133
1134 return info.m_itemId;
1135 }
1136
1137 long wxListCtrl::InsertItem(long index, const wxString& label)
1138 {
1139 if (m_genericImpl)
1140 return m_genericImpl->InsertItem(index, label);
1141
1142 wxListItem info;
1143 info.m_text = label;
1144 info.m_mask = wxLIST_MASK_TEXT;
1145 info.m_itemId = index;
1146 return InsertItem(info);
1147 }
1148
1149 // Inserts an image item
1150 long wxListCtrl::InsertItem(long index, int imageIndex)
1151 {
1152 if (m_genericImpl)
1153 return m_genericImpl->InsertItem(index, imageIndex);
1154
1155 wxListItem info;
1156 info.m_image = imageIndex;
1157 info.m_mask = wxLIST_MASK_IMAGE;
1158 info.m_itemId = index;
1159 return InsertItem(info);
1160 }
1161
1162 // Inserts an image/string item
1163 long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
1164 {
1165 if (m_genericImpl)
1166 return m_genericImpl->InsertItem(index, label, imageIndex);
1167
1168 wxListItem info;
1169 info.m_image = imageIndex;
1170 info.m_text = label;
1171 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
1172 info.m_itemId = index;
1173 return InsertItem(info);
1174 }
1175
1176 // For list view mode (only), inserts a column.
1177 long wxListCtrl::InsertColumn(long col, wxListItem& item)
1178 {
1179 if (m_genericImpl)
1180 return m_genericImpl->InsertColumn(col, item);
1181
1182 if (m_dbImpl)
1183 {
1184 if ( !(item.GetMask() & wxLIST_MASK_WIDTH) )
1185 item.SetWidth(150);
1186
1187 DataBrowserPropertyType type = kDataBrowserTextType;
1188 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
1189 if (imageList && imageList->GetImageCount() > 0)
1190 {
1191 wxBitmap bmp = imageList->GetBitmap(0);
1192 if (bmp.Ok())
1193 type = kDataBrowserIconAndTextType;
1194 }
1195
1196 SInt16 just = teFlushDefault;
1197 if (item.GetMask() & wxLIST_MASK_FORMAT)
1198 {
1199 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
1200 just = teFlushLeft;
1201 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
1202 just = teCenter;
1203 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
1204 just = teFlushRight;
1205 }
1206 m_dbImpl->InsertColumn(col, type, item.GetText(), just, item.GetWidth());
1207
1208 if (GetWindowStyleFlag() & wxLC_EDIT_LABELS)
1209 {
1210 DataBrowserTableViewColumnID id;
1211 m_dbImpl->GetColumnIDFromIndex(col, &id);
1212 DataBrowserPropertyFlags flags;
1213 verify_noerr(m_dbImpl->GetPropertyFlags(id, &flags));
1214 flags |= kDataBrowserPropertyIsEditable;
1215 verify_noerr(m_dbImpl->SetPropertyFlags(id, flags));
1216 }
1217 }
1218
1219 return col;
1220 }
1221
1222 long wxListCtrl::InsertColumn(long col,
1223 const wxString& heading,
1224 int format,
1225 int width)
1226 {
1227 if (m_genericImpl)
1228 return m_genericImpl->InsertColumn(col, heading, format, width);
1229
1230 wxListItem item;
1231 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1232 item.m_text = heading;
1233 if ( width > -1 )
1234 {
1235 item.m_mask |= wxLIST_MASK_WIDTH;
1236 item.m_width = width;
1237 }
1238 item.m_format = format;
1239
1240 return InsertColumn(col, item);
1241 }
1242
1243 // scroll the control by the given number of pixels (exception: in list view,
1244 // dx is interpreted as number of columns)
1245 bool wxListCtrl::ScrollList(int dx, int dy)
1246 {
1247 if (m_genericImpl)
1248 return m_genericImpl->ScrollList(dx, dy);
1249
1250 if (m_dbImpl)
1251 {
1252 m_dbImpl->SetScrollPosition(dx, dy);
1253 }
1254 return true;
1255 }
1256
1257
1258 bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1259 {
1260 if (m_genericImpl)
1261 return m_genericImpl->SortItems(fn, data);
1262
1263 return true;
1264 }
1265
1266 // ----------------------------------------------------------------------------
1267 // virtual list controls
1268 // ----------------------------------------------------------------------------
1269
1270 wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
1271 {
1272 // this is a pure virtual function, in fact - which is not really pure
1273 // because the controls which are not virtual don't need to implement it
1274 wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") );
1275
1276 return wxEmptyString;
1277 }
1278
1279 int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
1280 {
1281 wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
1282 -1,
1283 wxT("List control has an image list, OnGetItemImage or OnGetItemColumnImage should be overridden."));
1284 return -1;
1285 }
1286
1287 int wxListCtrl::OnGetItemColumnImage(long item, long column) const
1288 {
1289 if (!column)
1290 return OnGetItemImage(item);
1291
1292 return -1;
1293 }
1294
1295 wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
1296 {
1297 wxASSERT_MSG( item >= 0 && item < GetItemCount(),
1298 _T("invalid item index in OnGetItemAttr()") );
1299
1300 // no attributes by default
1301 return NULL;
1302 }
1303
1304 void wxListCtrl::SetItemCount(long count)
1305 {
1306 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
1307
1308 if (m_genericImpl)
1309 {
1310 m_genericImpl->SetItemCount(count);
1311 return;
1312 }
1313
1314 if (m_dbImpl)
1315 {
1316 // we need to temporarily disable the new item creation notification
1317 // procedure to speed things up
1318 // FIXME: Even this doesn't seem to help much...
1319 DataBrowserCallbacks callbacks;
1320 DataBrowserItemNotificationUPP itemUPP;
1321 GetDataBrowserCallbacks(m_dbImpl->GetControlRef(), &callbacks);
1322 itemUPP = callbacks.u.v1.itemNotificationCallback;
1323 callbacks.u.v1.itemNotificationCallback = 0;
1324 m_dbImpl->SetCallbacks(&callbacks);
1325 ::AddDataBrowserItems(m_dbImpl->GetControlRef(), kDataBrowserNoItem,
1326 count, NULL, kDataBrowserItemNoProperty);
1327 callbacks.u.v1.itemNotificationCallback = itemUPP;
1328 m_dbImpl->SetCallbacks(&callbacks);
1329 }
1330 m_count = count;
1331 }
1332
1333 void wxListCtrl::RefreshItem(long item)
1334 {
1335 if (m_genericImpl)
1336 {
1337 m_genericImpl->RefreshItem(item);
1338 return;
1339 }
1340
1341 wxRect rect;
1342 GetItemRect(item, rect);
1343 RefreshRect(rect);
1344 }
1345
1346 void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
1347 {
1348 if (m_genericImpl)
1349 {
1350 m_genericImpl->RefreshItems(itemFrom, itemTo);
1351 return;
1352 }
1353
1354 wxRect rect1, rect2;
1355 GetItemRect(itemFrom, rect1);
1356 GetItemRect(itemTo, rect2);
1357
1358 wxRect rect = rect1;
1359 rect.height = rect2.GetBottom() - rect1.GetTop();
1360
1361 RefreshRect(rect);
1362 }
1363
1364
1365 // wxMac internal data structures
1366
1367 wxMacListCtrlItem::~wxMacListCtrlItem()
1368 {
1369 }
1370
1371 void wxMacListCtrlItem::Notification(wxMacDataItemBrowserControl *owner ,
1372 DataBrowserItemNotification message,
1373 DataBrowserItemDataRef itemData ) const
1374 {
1375
1376 wxMacDataBrowserListCtrlControl *lb = dynamic_cast<wxMacDataBrowserListCtrlControl*>(owner);
1377
1378 // we want to depend on as little as possible to make sure tear-down of controls is safe
1379 if ( message == kDataBrowserItemRemoved)
1380 {
1381 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
1382 {
1383 delete (wxClientData*) (m_data);
1384 }
1385
1386 delete this;
1387 return;
1388 }
1389 else if ( message == kDataBrowserItemAdded )
1390 {
1391 // we don't issue events on adding, the item is not really stored in the list yet, so we
1392 // avoid asserts by gettting out now
1393 return ;
1394 }
1395
1396 wxListCtrl *list = wxDynamicCast( owner->GetPeer() , wxListCtrl );
1397 if ( list )
1398 {
1399 bool trigger = false;
1400
1401 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1402 bool isSingle = list->GetWindowStyle() | wxLC_SINGLE_SEL;
1403
1404 event.SetEventObject( list );
1405 event.m_itemIndex = owner->GetLineFromItem( this ) ;
1406 if ( !list->IsVirtual() )
1407 {
1408 lb->MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1409 }
1410
1411 switch (message)
1412 {
1413 case kDataBrowserItemDeselected:
1414 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1415 if ( !isSingle )
1416 trigger = !lb->IsSelectionSuppressed();
1417 break;
1418
1419 case kDataBrowserItemSelected:
1420 trigger = !lb->IsSelectionSuppressed();
1421 break;
1422
1423 case kDataBrowserItemDoubleClicked:
1424 event.SetEventType( wxEVT_LEFT_DCLICK );
1425 trigger = true;
1426 break;
1427
1428 case kDataBrowserEditStarted :
1429 // TODO : how to veto ?
1430 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1431 trigger = true ;
1432 break ;
1433
1434 case kDataBrowserEditStopped :
1435 // TODO probably trigger only upon the value store callback, because
1436 // here IIRC we cannot veto
1437 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1438 trigger = true ;
1439 break ;
1440
1441 default:
1442 break;
1443 }
1444
1445 if ( trigger )
1446 {
1447 // direct notification is not always having the listbox GetSelection() having in synch with event
1448 wxPostEvent( list->GetEventHandler(), event );
1449 }
1450 }
1451
1452 }
1453
1454 wxMacDataBrowserListCtrlControl::wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
1455 : wxMacDataItemBrowserControl( peer, pos, size, style )
1456 {
1457 OSStatus err = noErr;
1458 m_clientDataItemsType = wxClientData_None;
1459 m_isVirtual = false;
1460
1461 if ( style & wxLC_VIRTUAL )
1462 m_isVirtual = true;
1463
1464 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
1465 if ( style & wxLC_SINGLE_SEL )
1466 {
1467 options |= kDataBrowserSelectOnlyOne;
1468 }
1469 else
1470 {
1471 options |= kDataBrowserCmdTogglesSelection;
1472 }
1473
1474 err = SetSelectionFlags( options );
1475 verify_noerr( err );
1476
1477 if ( style & wxLC_LIST )
1478 {
1479 InsertColumn(0, kDataBrowserIconAndTextType, wxEmptyString, -1, -1);
1480 verify_noerr( AutoSizeColumns() );
1481 }
1482
1483 if ( style & wxLC_LIST || style & wxLC_NO_HEADER )
1484 verify_noerr( SetHeaderButtonHeight( 0 ) );
1485
1486 SetSortProperty( kMinColumnId );
1487 if ( style & wxLC_SORT_ASCENDING )
1488 {
1489 m_sortOrder = SortOrder_Text_Ascending;
1490 SetSortOrder( kDataBrowserOrderIncreasing );
1491 }
1492 else if ( style & wxLC_SORT_DESCENDING )
1493 {
1494 m_sortOrder = SortOrder_Text_Descending;
1495 SetSortOrder( kDataBrowserOrderDecreasing );
1496 }
1497 else
1498 {
1499 m_sortOrder = SortOrder_None;
1500 }
1501
1502 if ( style & wxLC_VRULES )
1503 {
1504 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1505 verify_noerr( DataBrowserChangeAttributes(m_controlRef, kDataBrowserAttributeListViewDrawColumnDividers, kDataBrowserAttributeNone) );
1506 #endif
1507 }
1508
1509 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
1510 err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
1511 }
1512
1513 OSStatus wxMacDataBrowserListCtrlControl::GetSetItemData(DataBrowserItemID itemID,
1514 DataBrowserPropertyID property,
1515 DataBrowserItemDataRef itemData,
1516 Boolean changeValue )
1517 {
1518 wxString text;
1519 int imgIndex = -1;
1520 short listColumn = property - kMinColumnId;
1521
1522 OSStatus err = errDataBrowserPropertyNotSupported;
1523 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1524 wxMacListCtrlItem* lcItem;
1525
1526 if (listColumn >= 0)
1527 {
1528 if (!m_isVirtual)
1529 {
1530 lcItem = (wxMacListCtrlItem*) itemID;
1531 if (lcItem->HasColumnInfo(listColumn)){
1532 wxListItem* item = lcItem->GetColumnInfo(listColumn);
1533 if (item->GetMask() & wxLIST_MASK_TEXT)
1534 text = item->GetText();
1535 if (item->GetMask() & wxLIST_MASK_IMAGE)
1536 imgIndex = item->GetImage();
1537 }
1538 }
1539 else
1540 {
1541 text = list->OnGetItemText( (long)itemID-1, listColumn );
1542 imgIndex = list->OnGetItemColumnImage( (long)itemID-1, listColumn );
1543 }
1544 }
1545
1546 if ( !changeValue )
1547 {
1548 switch (property)
1549 {
1550 case kDataBrowserItemIsEditableProperty :
1551 if ( list && list->HasFlag( wxLC_EDIT_LABELS ) )
1552 {
1553 verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
1554 err = noErr ;
1555 }
1556 break ;
1557 default :
1558 if ( property >= kMinColumnId )
1559 {
1560 wxMacCFStringHolder cfStr;
1561
1562 if (text){
1563 cfStr.Assign( text, wxLocale::GetSystemEncoding() );
1564 err = ::SetDataBrowserItemDataText( itemData, cfStr );
1565 err = noErr;
1566 }
1567
1568
1569
1570 if ( imgIndex != -1 )
1571 {
1572 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
1573 if (imageList && imageList->GetImageCount() > 0){
1574 wxBitmap bmp = imageList->GetBitmap(imgIndex);
1575 IconRef icon = bmp.GetBitmapData()->GetIconRef();
1576 ::SetDataBrowserItemDataIcon(itemData, icon);
1577 }
1578 }
1579
1580 }
1581 break ;
1582 }
1583
1584 }
1585 else
1586 {
1587 switch (property)
1588 {
1589 default:
1590 if ( property >= kMinColumnId )
1591 {
1592 short listColumn = property - kMinColumnId;
1593
1594 // TODO probably send the 'end edit' from here, as we
1595 // can then deal with the veto
1596 CFStringRef sr ;
1597 verify_noerr( GetDataBrowserItemDataText( itemData , &sr ) ) ;
1598 wxMacCFStringHolder cfStr(sr) ;;
1599 if (m_isVirtual)
1600 list->SetItem( (long)itemData-1 , listColumn, cfStr.AsString() ) ;
1601 else
1602 {
1603 if (lcItem)
1604 lcItem->SetColumnTextValue( listColumn, cfStr.AsString() );
1605 }
1606 err = noErr ;
1607 }
1608 break;
1609 }
1610 }
1611 return err;
1612 }
1613
1614 void wxMacDataBrowserListCtrlControl::ItemNotification(DataBrowserItemID itemID,
1615 DataBrowserItemNotification message,
1616 DataBrowserItemDataRef itemData )
1617 {
1618 // we want to depend on as little as possible to make sure tear-down of controls is safe
1619 if ( message == kDataBrowserItemRemoved)
1620 {
1621 // make sure MacDelete does the proper teardown.
1622 return;
1623 }
1624 else if ( message == kDataBrowserItemAdded )
1625 {
1626 // we don't issue events on adding, the item is not really stored in the list yet, so we
1627 // avoid asserts by gettting out now
1628 return ;
1629 }
1630
1631 wxListCtrl *list = wxDynamicCast( GetPeer() , wxListCtrl );
1632 if ( list )
1633 {
1634 bool trigger = false;
1635
1636 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1637 bool isSingle = list->GetWindowStyle() | wxLC_SINGLE_SEL;
1638
1639 event.SetEventObject( list );
1640 if ( !list->IsVirtual() )
1641 {
1642 wxMacDataItem* item = (wxMacDataItem*)itemID;
1643 DataBrowserTableViewRowIndex result = 0;
1644 verify_noerr( GetItemRow( itemID, &result ) ) ;
1645 event.m_itemIndex = result;
1646
1647 if (event.m_itemIndex >= 0)
1648 MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1649 }
1650 else
1651 {
1652 event.m_itemIndex = (long)itemID;
1653 }
1654
1655 switch (message)
1656 {
1657 case kDataBrowserItemDeselected:
1658 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1659 if ( !isSingle )
1660 trigger = IsSelectionSuppressed();
1661 break;
1662
1663 case kDataBrowserItemSelected:
1664 trigger = IsSelectionSuppressed();
1665 break;
1666
1667 case kDataBrowserItemDoubleClicked:
1668 event.SetEventType( wxEVT_LEFT_DCLICK );
1669 trigger = true;
1670 break;
1671
1672 case kDataBrowserEditStarted :
1673 // TODO : how to veto ?
1674 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1675 trigger = true ;
1676 break ;
1677
1678 case kDataBrowserEditStopped :
1679 // TODO probably trigger only upon the value store callback, because
1680 // here IIRC we cannot veto
1681 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1682 trigger = true ;
1683 break ;
1684
1685 default:
1686 break;
1687 }
1688
1689 if ( trigger )
1690 {
1691 // direct notification is not always having the listbox GetSelection() having in synch with event
1692 wxPostEvent( list->GetEventHandler(), event );
1693 }
1694 }
1695 }
1696
1697 Boolean wxMacDataBrowserListCtrlControl::CompareItems(DataBrowserItemID itemOneID,
1698 DataBrowserItemID itemTwoID,
1699 DataBrowserPropertyID sortProperty)
1700 {
1701
1702 bool retval = false;
1703 wxString itemText;
1704 wxString otherItemText;
1705 int colId = sortProperty - kMinColumnId;
1706 long itemNum = 0;
1707 long otherItemNum = 0;
1708
1709 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1710
1711 // means we need to
1712 if (colId >= 0)
1713 {
1714 if (!m_isVirtual)
1715 {
1716 wxMacListCtrlItem* item = (wxMacListCtrlItem*)itemOneID;
1717 wxMacListCtrlItem* otherItem = (wxMacListCtrlItem*)itemTwoID;
1718 itemNum = item->GetOrder();
1719 otherItemNum = otherItem->GetOrder();
1720 if (item->HasColumnInfo(colId))
1721 itemText = item->GetColumnInfo(colId)->GetText();
1722 if (otherItem->HasColumnInfo(colId))
1723 otherItemText = otherItem->GetColumnInfo(colId)->GetText();
1724 }
1725 else
1726 {
1727 itemNum = (long)itemOneID;
1728 otherItemNum = (long)itemTwoID;
1729 itemText = list->OnGetItemText( itemNum-1, colId );
1730 otherItemText = list->OnGetItemText( otherItemNum-1, colId );
1731
1732 }
1733
1734 DataBrowserSortOrder sort;
1735 verify_noerr(GetSortOrder(&sort));
1736
1737 if ( sort == kDataBrowserOrderIncreasing )
1738 {
1739 retval = itemText.CmpNoCase( otherItemText ) > 0;
1740 }
1741 else if ( sort == kDataBrowserOrderDecreasing )
1742 {
1743 retval = itemText.CmpNoCase( otherItemText ) < 0;
1744 }
1745 }
1746 else{
1747 // fallback for undefined cases
1748 retval = itemOneID < itemTwoID;
1749 }
1750
1751 return retval;
1752 }
1753
1754 wxMacDataBrowserListCtrlControl::~wxMacDataBrowserListCtrlControl()
1755 {
1756 }
1757
1758 void wxMacDataBrowserListCtrlControl::MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item )
1759 {
1760 wxMacDataItem* dataItem = GetItemFromLine(row);
1761 if (item)
1762 {
1763 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1764 listItem->SetColumnInfo( column, item );
1765 UpdateState(dataItem, item);
1766 }
1767 }
1768
1769 // apply changes that need to happen immediately, rather than when the
1770 // databrowser control fires a callback.
1771 void wxMacDataBrowserListCtrlControl::UpdateState(wxMacDataItem* dataItem, wxListItem* listItem)
1772 {
1773 bool isSelected = IsItemSelected( dataItem );
1774 bool isSelectedState = (listItem->GetState() == wxLIST_STATE_SELECTED);
1775
1776 // toggle the selection state if wxListInfo state and actual state don't match.
1777 if ( isSelected != isSelectedState )
1778 {
1779 DataBrowserSetOption options = kDataBrowserItemsAdd;
1780 if (!isSelectedState)
1781 options = kDataBrowserItemsRemove;
1782 SetSelectedItem(dataItem, options);
1783 }
1784 // TODO: Set column width if item width > than current column width
1785 }
1786
1787 void wxMacDataBrowserListCtrlControl::MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item )
1788 {
1789 wxMacDataItem* dataItem = GetItemFromLine(row);
1790 // CS should this guard against dataItem = 0 ? , as item is not a pointer if (item) is not appropriate
1791 //if (item)
1792 {
1793 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1794 wxListItem* oldItem = listItem->GetColumnInfo( column );
1795
1796 long mask = item.GetMask();
1797 if ( !mask )
1798 // by default, get everything for backwards compatibility
1799 mask = -1;
1800
1801 if ( mask & wxLIST_MASK_TEXT )
1802 item.SetText(oldItem->GetText());
1803 if ( mask & wxLIST_MASK_IMAGE )
1804 item.SetImage(oldItem->GetImage());
1805 if ( mask & wxLIST_MASK_DATA )
1806 item.SetData(oldItem->GetData());
1807 if ( mask & wxLIST_MASK_STATE )
1808 item.SetState(oldItem->GetState());
1809 if ( mask & wxLIST_MASK_WIDTH )
1810 item.SetWidth(oldItem->GetWidth());
1811 if ( mask & wxLIST_MASK_FORMAT )
1812 item.SetAlign(oldItem->GetAlign());
1813
1814 item.SetTextColour(oldItem->GetTextColour());
1815 item.SetBackgroundColour(oldItem->GetBackgroundColour());
1816 item.SetFont(oldItem->GetFont());
1817 }
1818 }
1819
1820 void wxMacDataBrowserListCtrlControl::MacInsertItem( unsigned int n, wxListItem* item )
1821 {
1822 wxMacDataItemBrowserControl::MacInsert(n, item->GetText());
1823 MacSetColumnInfo(n, 0, item);
1824 }
1825
1826 wxMacListCtrlItem* wxMacDataBrowserListCtrlControl::CreateItem()
1827 {
1828 return new wxMacListCtrlItem();
1829 }
1830
1831 wxMacListCtrlItem::wxMacListCtrlItem()
1832 {
1833 m_rowItems = wxListItemList();
1834 }
1835
1836 int wxMacListCtrlItem::GetColumnImageValue( unsigned int column )
1837 {
1838 return GetColumnInfo(column)->GetImage();
1839 }
1840
1841 void wxMacListCtrlItem::SetColumnImageValue( unsigned int column, int imageIndex )
1842 {
1843 GetColumnInfo(column)->SetImage(imageIndex);
1844 }
1845
1846 const wxString& wxMacListCtrlItem::GetColumnTextValue( unsigned int column )
1847 {
1848 if ( column == 0 )
1849 return GetLabel();
1850
1851 return GetColumnInfo(column)->GetText();
1852 }
1853
1854 void wxMacListCtrlItem::SetColumnTextValue( unsigned int column, const wxString& text )
1855 {
1856 GetColumnInfo(column)->SetText(text);
1857
1858 // for compatibility with superclass APIs
1859 if ( column == 0 )
1860 SetLabel(text);
1861 }
1862
1863 wxListItem* wxMacListCtrlItem::GetColumnInfo( unsigned int column )
1864 {
1865 wxListItemList::compatibility_iterator node = m_rowItems.Item( column );
1866 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
1867
1868 return node->GetData();
1869 }
1870
1871 bool wxMacListCtrlItem::HasColumnInfo( unsigned int column )
1872 {
1873 return m_rowItems.GetCount() > column;
1874 }
1875
1876 void wxMacListCtrlItem::SetColumnInfo( unsigned int column, wxListItem* item )
1877 {
1878
1879 if ( column >= m_rowItems.GetCount() )
1880 {
1881 wxListItem* listItem = new wxListItem(*item);
1882 m_rowItems.Append( listItem );
1883 }
1884 else
1885 {
1886 wxListItem* listItem = GetColumnInfo( column );
1887 long mask = item->GetMask();
1888 if (mask & wxLIST_MASK_TEXT)
1889 listItem->SetText(item->GetText());
1890 if (mask & wxLIST_MASK_DATA)
1891 listItem->SetData(item->GetData());
1892 if (mask & wxLIST_MASK_IMAGE)
1893 listItem->SetImage(item->GetImage());
1894 if (mask & wxLIST_MASK_STATE)
1895 listItem->SetState(item->GetState());
1896 if (mask & wxLIST_MASK_FORMAT)
1897 listItem->SetAlign(item->GetAlign());
1898 if (mask & wxLIST_MASK_WIDTH)
1899 listItem->SetWidth(item->GetWidth());
1900 }
1901 }
1902
1903 #endif // wxUSE_LISTCTRL