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