]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listctrl_mac.cpp
Override CreateItem so wxListBox can turn its notifications into events.
[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 // set/remove options based on the wxListCtrl type.
1221 DataBrowserTableViewColumnID id;
1222 m_dbImpl->GetColumnIDFromIndex(col, &id);
1223 DataBrowserPropertyFlags flags;
1224 verify_noerr(m_dbImpl->GetPropertyFlags(id, &flags));
1225 if (GetWindowStyleFlag() & wxLC_EDIT_LABELS)
1226 flags |= kDataBrowserPropertyIsEditable;
1227
1228 if (GetWindowStyleFlag() & wxLC_VIRTUAL){
1229 flags &= ~kDataBrowserListViewSortableColumn;
1230 }
1231 verify_noerr(m_dbImpl->SetPropertyFlags(id, flags));
1232 }
1233
1234 return col;
1235 }
1236
1237 long wxListCtrl::InsertColumn(long col,
1238 const wxString& heading,
1239 int format,
1240 int width)
1241 {
1242 if (m_genericImpl)
1243 return m_genericImpl->InsertColumn(col, heading, format, width);
1244
1245 wxListItem item;
1246 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1247 item.m_text = heading;
1248 if ( width > -1 )
1249 {
1250 item.m_mask |= wxLIST_MASK_WIDTH;
1251 item.m_width = width;
1252 }
1253 item.m_format = format;
1254
1255 return InsertColumn(col, item);
1256 }
1257
1258 // scroll the control by the given number of pixels (exception: in list view,
1259 // dx is interpreted as number of columns)
1260 bool wxListCtrl::ScrollList(int dx, int dy)
1261 {
1262 if (m_genericImpl)
1263 return m_genericImpl->ScrollList(dx, dy);
1264
1265 if (m_dbImpl)
1266 {
1267 m_dbImpl->SetScrollPosition(dx, dy);
1268 }
1269 return true;
1270 }
1271
1272
1273 bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1274 {
1275 if (m_genericImpl)
1276 return m_genericImpl->SortItems(fn, data);
1277
1278 return true;
1279 }
1280
1281 // ----------------------------------------------------------------------------
1282 // virtual list controls
1283 // ----------------------------------------------------------------------------
1284
1285 wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
1286 {
1287 // this is a pure virtual function, in fact - which is not really pure
1288 // because the controls which are not virtual don't need to implement it
1289 wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") );
1290
1291 return wxEmptyString;
1292 }
1293
1294 int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
1295 {
1296 wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
1297 -1,
1298 wxT("List control has an image list, OnGetItemImage or OnGetItemColumnImage should be overridden."));
1299 return -1;
1300 }
1301
1302 int wxListCtrl::OnGetItemColumnImage(long item, long column) const
1303 {
1304 if (!column)
1305 return OnGetItemImage(item);
1306
1307 return -1;
1308 }
1309
1310 wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
1311 {
1312 wxASSERT_MSG( item >= 0 && item < GetItemCount(),
1313 _T("invalid item index in OnGetItemAttr()") );
1314
1315 // no attributes by default
1316 return NULL;
1317 }
1318
1319 void wxListCtrl::SetItemCount(long count)
1320 {
1321 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
1322
1323 if (m_genericImpl)
1324 {
1325 m_genericImpl->SetItemCount(count);
1326 return;
1327 }
1328
1329 if (m_dbImpl)
1330 {
1331 // we need to temporarily disable the new item creation notification
1332 // procedure to speed things up
1333 // FIXME: Even this doesn't seem to help much...
1334 DataBrowserCallbacks callbacks;
1335 DataBrowserItemNotificationUPP itemUPP;
1336 GetDataBrowserCallbacks(m_dbImpl->GetControlRef(), &callbacks);
1337 itemUPP = callbacks.u.v1.itemNotificationCallback;
1338 callbacks.u.v1.itemNotificationCallback = 0;
1339 m_dbImpl->SetCallbacks(&callbacks);
1340 ::AddDataBrowserItems(m_dbImpl->GetControlRef(), kDataBrowserNoItem,
1341 count, NULL, kDataBrowserItemNoProperty);
1342 callbacks.u.v1.itemNotificationCallback = itemUPP;
1343 m_dbImpl->SetCallbacks(&callbacks);
1344 }
1345 m_count = count;
1346 }
1347
1348 void wxListCtrl::RefreshItem(long item)
1349 {
1350 if (m_genericImpl)
1351 {
1352 m_genericImpl->RefreshItem(item);
1353 return;
1354 }
1355
1356 wxRect rect;
1357 GetItemRect(item, rect);
1358 RefreshRect(rect);
1359 }
1360
1361 void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
1362 {
1363 if (m_genericImpl)
1364 {
1365 m_genericImpl->RefreshItems(itemFrom, itemTo);
1366 return;
1367 }
1368
1369 wxRect rect1, rect2;
1370 GetItemRect(itemFrom, rect1);
1371 GetItemRect(itemTo, rect2);
1372
1373 wxRect rect = rect1;
1374 rect.height = rect2.GetBottom() - rect1.GetTop();
1375
1376 RefreshRect(rect);
1377 }
1378
1379
1380 // wxMac internal data structures
1381
1382 wxMacListCtrlItem::~wxMacListCtrlItem()
1383 {
1384 }
1385
1386 void wxMacListCtrlItem::Notification(wxMacDataItemBrowserControl *owner ,
1387 DataBrowserItemNotification message,
1388 DataBrowserItemDataRef itemData ) const
1389 {
1390
1391 wxMacDataBrowserListCtrlControl *lb = dynamic_cast<wxMacDataBrowserListCtrlControl*>(owner);
1392
1393 // we want to depend on as little as possible to make sure tear-down of controls is safe
1394 if ( message == kDataBrowserItemRemoved)
1395 {
1396 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
1397 {
1398 delete (wxClientData*) (m_data);
1399 }
1400
1401 delete this;
1402 return;
1403 }
1404 else if ( message == kDataBrowserItemAdded )
1405 {
1406 // we don't issue events on adding, the item is not really stored in the list yet, so we
1407 // avoid asserts by gettting out now
1408 return ;
1409 }
1410
1411 wxListCtrl *list = wxDynamicCast( owner->GetPeer() , wxListCtrl );
1412 if ( list )
1413 {
1414 bool trigger = false;
1415
1416 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1417 bool isSingle = list->GetWindowStyle() | wxLC_SINGLE_SEL;
1418
1419 event.SetEventObject( list );
1420 event.m_itemIndex = owner->GetLineFromItem( this ) ;
1421 if ( !list->IsVirtual() )
1422 {
1423 lb->MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1424 }
1425
1426 switch (message)
1427 {
1428 case kDataBrowserItemDeselected:
1429 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1430 if ( !isSingle )
1431 trigger = !lb->IsSelectionSuppressed();
1432 break;
1433
1434 case kDataBrowserItemSelected:
1435 trigger = !lb->IsSelectionSuppressed();
1436 break;
1437
1438 case kDataBrowserItemDoubleClicked:
1439 event.SetEventType( wxEVT_LEFT_DCLICK );
1440 trigger = true;
1441 break;
1442
1443 case kDataBrowserEditStarted :
1444 // TODO : how to veto ?
1445 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1446 trigger = true ;
1447 break ;
1448
1449 case kDataBrowserEditStopped :
1450 // TODO probably trigger only upon the value store callback, because
1451 // here IIRC we cannot veto
1452 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1453 trigger = true ;
1454 break ;
1455
1456 default:
1457 break;
1458 }
1459
1460 if ( trigger )
1461 {
1462 // direct notification is not always having the listbox GetSelection() having in synch with event
1463 wxPostEvent( list->GetEventHandler(), event );
1464 }
1465 }
1466
1467 }
1468
1469 wxMacDataBrowserListCtrlControl::wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
1470 : wxMacDataItemBrowserControl( peer, pos, size, style )
1471 {
1472 OSStatus err = noErr;
1473 m_clientDataItemsType = wxClientData_None;
1474 m_isVirtual = false;
1475
1476 if ( style & wxLC_VIRTUAL )
1477 m_isVirtual = true;
1478
1479 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
1480 if ( style & wxLC_SINGLE_SEL )
1481 {
1482 options |= kDataBrowserSelectOnlyOne;
1483 }
1484 else
1485 {
1486 options |= kDataBrowserCmdTogglesSelection;
1487 }
1488
1489 err = SetSelectionFlags( options );
1490 verify_noerr( err );
1491
1492 if ( style & wxLC_LIST )
1493 {
1494 InsertColumn(0, kDataBrowserIconAndTextType, wxEmptyString, -1, -1);
1495 verify_noerr( AutoSizeColumns() );
1496 }
1497
1498 if ( style & wxLC_LIST || style & wxLC_NO_HEADER )
1499 verify_noerr( SetHeaderButtonHeight( 0 ) );
1500
1501 if ( m_isVirtual )
1502 SetSortProperty( kMinColumnId - 1 );
1503 else
1504 SetSortProperty( kMinColumnId );
1505 if ( style & wxLC_SORT_ASCENDING )
1506 {
1507 m_sortOrder = SortOrder_Text_Ascending;
1508 SetSortOrder( kDataBrowserOrderIncreasing );
1509 }
1510 else if ( style & wxLC_SORT_DESCENDING )
1511 {
1512 m_sortOrder = SortOrder_Text_Descending;
1513 SetSortOrder( kDataBrowserOrderDecreasing );
1514 }
1515 else
1516 {
1517 m_sortOrder = SortOrder_None;
1518 }
1519
1520 if ( style & wxLC_VRULES )
1521 {
1522 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1523 verify_noerr( DataBrowserChangeAttributes(m_controlRef, kDataBrowserAttributeListViewDrawColumnDividers, kDataBrowserAttributeNone) );
1524 #endif
1525 }
1526
1527 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
1528 err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
1529 }
1530
1531 OSStatus wxMacDataBrowserListCtrlControl::GetSetItemData(DataBrowserItemID itemID,
1532 DataBrowserPropertyID property,
1533 DataBrowserItemDataRef itemData,
1534 Boolean changeValue )
1535 {
1536 wxString text;
1537 int imgIndex = -1;
1538 short listColumn = property - kMinColumnId;
1539
1540 OSStatus err = errDataBrowserPropertyNotSupported;
1541 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1542 wxMacListCtrlItem* lcItem;
1543
1544 if (listColumn >= 0)
1545 {
1546 if (!m_isVirtual)
1547 {
1548 lcItem = (wxMacListCtrlItem*) itemID;
1549 if (lcItem->HasColumnInfo(listColumn)){
1550 wxListItem* item = lcItem->GetColumnInfo(listColumn);
1551 if (item->GetMask() & wxLIST_MASK_TEXT)
1552 text = item->GetText();
1553 if (item->GetMask() & wxLIST_MASK_IMAGE)
1554 imgIndex = item->GetImage();
1555 }
1556 }
1557 else
1558 {
1559 text = list->OnGetItemText( (long)itemID-1, listColumn );
1560 imgIndex = list->OnGetItemColumnImage( (long)itemID-1, listColumn );
1561 }
1562 }
1563
1564 if ( !changeValue )
1565 {
1566 switch (property)
1567 {
1568 case kDataBrowserItemIsEditableProperty :
1569 if ( list && list->HasFlag( wxLC_EDIT_LABELS ) )
1570 {
1571 verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
1572 err = noErr ;
1573 }
1574 break ;
1575 default :
1576 if ( property >= kMinColumnId )
1577 {
1578 wxMacCFStringHolder cfStr;
1579
1580 if (text){
1581 cfStr.Assign( text, wxLocale::GetSystemEncoding() );
1582 err = ::SetDataBrowserItemDataText( itemData, cfStr );
1583 err = noErr;
1584 }
1585
1586
1587
1588 if ( imgIndex != -1 )
1589 {
1590 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
1591 if (imageList && imageList->GetImageCount() > 0){
1592 wxBitmap bmp = imageList->GetBitmap(imgIndex);
1593 IconRef icon = bmp.GetBitmapData()->GetIconRef();
1594 ::SetDataBrowserItemDataIcon(itemData, icon);
1595 }
1596 }
1597
1598 }
1599 break ;
1600 }
1601
1602 }
1603 else
1604 {
1605 switch (property)
1606 {
1607 default:
1608 if ( property >= kMinColumnId )
1609 {
1610 short listColumn = property - kMinColumnId;
1611
1612 // TODO probably send the 'end edit' from here, as we
1613 // can then deal with the veto
1614 CFStringRef sr ;
1615 verify_noerr( GetDataBrowserItemDataText( itemData , &sr ) ) ;
1616 wxMacCFStringHolder cfStr(sr) ;;
1617 if (m_isVirtual)
1618 list->SetItem( (long)itemData-1 , listColumn, cfStr.AsString() ) ;
1619 else
1620 {
1621 if (lcItem)
1622 lcItem->SetColumnTextValue( listColumn, cfStr.AsString() );
1623 }
1624 err = noErr ;
1625 }
1626 break;
1627 }
1628 }
1629 return err;
1630 }
1631
1632 void wxMacDataBrowserListCtrlControl::ItemNotification(DataBrowserItemID itemID,
1633 DataBrowserItemNotification message,
1634 DataBrowserItemDataRef itemData )
1635 {
1636 // we want to depend on as little as possible to make sure tear-down of controls is safe
1637 if ( message == kDataBrowserItemRemoved)
1638 {
1639 // make sure MacDelete does the proper teardown.
1640 return;
1641 }
1642 else if ( message == kDataBrowserItemAdded )
1643 {
1644 // we don't issue events on adding, the item is not really stored in the list yet, so we
1645 // avoid asserts by gettting out now
1646 return ;
1647 }
1648
1649 wxListCtrl *list = wxDynamicCast( GetPeer() , wxListCtrl );
1650 if ( list )
1651 {
1652 bool trigger = false;
1653
1654 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
1655 bool isSingle = list->GetWindowStyle() | wxLC_SINGLE_SEL;
1656
1657 event.SetEventObject( list );
1658 if ( !list->IsVirtual() )
1659 {
1660 DataBrowserTableViewRowIndex result = 0;
1661 verify_noerr( GetItemRow( itemID, &result ) ) ;
1662 event.m_itemIndex = result;
1663
1664 if (event.m_itemIndex >= 0)
1665 MacGetColumnInfo(event.m_itemIndex,0,event.m_item);
1666 }
1667 else
1668 {
1669 event.m_itemIndex = (long)itemID;
1670 }
1671
1672 switch (message)
1673 {
1674 case kDataBrowserItemDeselected:
1675 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
1676 if ( !isSingle )
1677 trigger = IsSelectionSuppressed();
1678 break;
1679
1680 case kDataBrowserItemSelected:
1681 trigger = IsSelectionSuppressed();
1682 break;
1683
1684 case kDataBrowserItemDoubleClicked:
1685 event.SetEventType( wxEVT_LEFT_DCLICK );
1686 trigger = true;
1687 break;
1688
1689 case kDataBrowserEditStarted :
1690 // TODO : how to veto ?
1691 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
1692 trigger = true ;
1693 break ;
1694
1695 case kDataBrowserEditStopped :
1696 // TODO probably trigger only upon the value store callback, because
1697 // here IIRC we cannot veto
1698 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
1699 trigger = true ;
1700 break ;
1701
1702 default:
1703 break;
1704 }
1705
1706 if ( trigger )
1707 {
1708 // direct notification is not always having the listbox GetSelection() having in synch with event
1709 wxPostEvent( list->GetEventHandler(), event );
1710 }
1711 }
1712 }
1713
1714 Boolean wxMacDataBrowserListCtrlControl::CompareItems(DataBrowserItemID itemOneID,
1715 DataBrowserItemID itemTwoID,
1716 DataBrowserPropertyID sortProperty)
1717 {
1718
1719 bool retval = false;
1720 wxString itemText;
1721 wxString otherItemText;
1722 int colId = sortProperty - kMinColumnId;
1723 long itemNum = 0;
1724 long otherItemNum = 0;
1725
1726 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
1727
1728 // means we need to
1729 if (colId >= 0)
1730 {
1731 if (!m_isVirtual)
1732 {
1733 wxMacListCtrlItem* item = (wxMacListCtrlItem*)itemOneID;
1734 wxMacListCtrlItem* otherItem = (wxMacListCtrlItem*)itemTwoID;
1735 itemNum = item->GetOrder();
1736 otherItemNum = otherItem->GetOrder();
1737 if (item->HasColumnInfo(colId))
1738 itemText = item->GetColumnInfo(colId)->GetText();
1739 if (otherItem->HasColumnInfo(colId))
1740 otherItemText = otherItem->GetColumnInfo(colId)->GetText();
1741 }
1742 else
1743 {
1744 itemNum = (long)itemOneID;
1745 otherItemNum = (long)itemTwoID;
1746 itemText = list->OnGetItemText( itemNum-1, colId );
1747 otherItemText = list->OnGetItemText( otherItemNum-1, colId );
1748
1749 }
1750
1751 DataBrowserSortOrder sort;
1752 verify_noerr(GetSortOrder(&sort));
1753
1754 if ( sort == kDataBrowserOrderIncreasing )
1755 {
1756 retval = itemText.CmpNoCase( otherItemText ) > 0;
1757 }
1758 else if ( sort == kDataBrowserOrderDecreasing )
1759 {
1760 retval = itemText.CmpNoCase( otherItemText ) < 0;
1761 }
1762 }
1763 else{
1764 // fallback for undefined cases
1765 retval = itemOneID < itemTwoID;
1766 }
1767
1768 return retval;
1769 }
1770
1771 wxMacDataBrowserListCtrlControl::~wxMacDataBrowserListCtrlControl()
1772 {
1773 }
1774
1775 void wxMacDataBrowserListCtrlControl::MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item )
1776 {
1777 wxMacDataItem* dataItem = GetItemFromLine(row);
1778 if (item)
1779 {
1780 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1781 listItem->SetColumnInfo( column, item );
1782 UpdateState(dataItem, item);
1783 }
1784 }
1785
1786 // apply changes that need to happen immediately, rather than when the
1787 // databrowser control fires a callback.
1788 void wxMacDataBrowserListCtrlControl::UpdateState(wxMacDataItem* dataItem, wxListItem* listItem)
1789 {
1790 bool isSelected = IsItemSelected( dataItem );
1791 bool isSelectedState = (listItem->GetState() == wxLIST_STATE_SELECTED);
1792
1793 // toggle the selection state if wxListInfo state and actual state don't match.
1794 if ( isSelected != isSelectedState )
1795 {
1796 DataBrowserSetOption options = kDataBrowserItemsAdd;
1797 if (!isSelectedState)
1798 options = kDataBrowserItemsRemove;
1799 SetSelectedItem(dataItem, options);
1800 }
1801 // TODO: Set column width if item width > than current column width
1802 }
1803
1804 void wxMacDataBrowserListCtrlControl::MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item )
1805 {
1806 wxMacDataItem* dataItem = GetItemFromLine(row);
1807 // CS should this guard against dataItem = 0 ? , as item is not a pointer if (item) is not appropriate
1808 //if (item)
1809 {
1810 wxMacListCtrlItem* listItem = dynamic_cast<wxMacListCtrlItem*>(dataItem);
1811 wxListItem* oldItem = listItem->GetColumnInfo( column );
1812
1813 long mask = item.GetMask();
1814 if ( !mask )
1815 // by default, get everything for backwards compatibility
1816 mask = -1;
1817
1818 if ( mask & wxLIST_MASK_TEXT )
1819 item.SetText(oldItem->GetText());
1820 if ( mask & wxLIST_MASK_IMAGE )
1821 item.SetImage(oldItem->GetImage());
1822 if ( mask & wxLIST_MASK_DATA )
1823 item.SetData(oldItem->GetData());
1824 if ( mask & wxLIST_MASK_STATE )
1825 item.SetState(oldItem->GetState());
1826 if ( mask & wxLIST_MASK_WIDTH )
1827 item.SetWidth(oldItem->GetWidth());
1828 if ( mask & wxLIST_MASK_FORMAT )
1829 item.SetAlign(oldItem->GetAlign());
1830
1831 item.SetTextColour(oldItem->GetTextColour());
1832 item.SetBackgroundColour(oldItem->GetBackgroundColour());
1833 item.SetFont(oldItem->GetFont());
1834 }
1835 }
1836
1837 void wxMacDataBrowserListCtrlControl::MacInsertItem( unsigned int n, wxListItem* item )
1838 {
1839 wxMacDataItemBrowserControl::MacInsert(n, item->GetText());
1840 MacSetColumnInfo(n, 0, item);
1841 }
1842
1843 wxMacListCtrlItem* wxMacDataBrowserListCtrlControl::CreateItem()
1844 {
1845 return new wxMacListCtrlItem();
1846 }
1847
1848 wxMacListCtrlItem::wxMacListCtrlItem()
1849 {
1850 m_rowItems = wxListItemList();
1851 }
1852
1853 int wxMacListCtrlItem::GetColumnImageValue( unsigned int column )
1854 {
1855 return GetColumnInfo(column)->GetImage();
1856 }
1857
1858 void wxMacListCtrlItem::SetColumnImageValue( unsigned int column, int imageIndex )
1859 {
1860 GetColumnInfo(column)->SetImage(imageIndex);
1861 }
1862
1863 const wxString& wxMacListCtrlItem::GetColumnTextValue( unsigned int column )
1864 {
1865 if ( column == 0 )
1866 return GetLabel();
1867
1868 return GetColumnInfo(column)->GetText();
1869 }
1870
1871 void wxMacListCtrlItem::SetColumnTextValue( unsigned int column, const wxString& text )
1872 {
1873 GetColumnInfo(column)->SetText(text);
1874
1875 // for compatibility with superclass APIs
1876 if ( column == 0 )
1877 SetLabel(text);
1878 }
1879
1880 wxListItem* wxMacListCtrlItem::GetColumnInfo( unsigned int column )
1881 {
1882 wxListItemList::compatibility_iterator node = m_rowItems.Item( column );
1883 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
1884
1885 return node->GetData();
1886 }
1887
1888 bool wxMacListCtrlItem::HasColumnInfo( unsigned int column )
1889 {
1890 return m_rowItems.GetCount() > column;
1891 }
1892
1893 void wxMacListCtrlItem::SetColumnInfo( unsigned int column, wxListItem* item )
1894 {
1895
1896 if ( column >= m_rowItems.GetCount() )
1897 {
1898 wxListItem* listItem = new wxListItem(*item);
1899 m_rowItems.Append( listItem );
1900 }
1901 else
1902 {
1903 wxListItem* listItem = GetColumnInfo( column );
1904 long mask = item->GetMask();
1905 if (mask & wxLIST_MASK_TEXT)
1906 listItem->SetText(item->GetText());
1907 if (mask & wxLIST_MASK_DATA)
1908 listItem->SetData(item->GetData());
1909 if (mask & wxLIST_MASK_IMAGE)
1910 listItem->SetImage(item->GetImage());
1911 if (mask & wxLIST_MASK_STATE)
1912 listItem->SetState(item->GetState());
1913 if (mask & wxLIST_MASK_FORMAT)
1914 listItem->SetAlign(item->GetAlign());
1915 if (mask & wxLIST_MASK_WIDTH)
1916 listItem->SetWidth(item->GetWidth());
1917 }
1918 }
1919
1920 #endif // wxUSE_LISTCTRL