1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/listbox.mm
4 // Author: David Elliott
8 // Copyright: (c) 2003 David Elliott
9 // Licence: wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
16 #include "wx/listbox.h"
23 #include "wx/cocoa/string.h"
24 #include "wx/cocoa/autorelease.h"
25 #include "wx/cocoa/ObjcRef.h"
26 #include "wx/cocoa/private/scrollview.h"
27 #include "wx/cocoa/NSTableDataSource.h"
29 #import <Foundation/NSArray.h>
30 #import <Foundation/NSEnumerator.h>
31 #import <AppKit/NSTableView.h>
32 #import <AppKit/NSTableColumn.h>
33 #import <AppKit/NSScrollView.h>
35 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControlWithItems)
36 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
38 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
40 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
43 const wxArrayString& choices,
45 const wxValidator& validator,
48 wxCArrayString chs(choices);
50 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
51 style, validator, name);
54 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
57 int n, const wxString choices[],
59 const wxValidator& validator,
64 Single-selection list.
67 Multiple-selection list: the user can toggle multiple items on and off.
70 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
73 Create horizontal scrollbar if contents are too wide (Windows only).
76 Always show a vertical scrollbar.
79 Only create a vertical scrollbar if needed.
82 The listbox contents are sorted in alphabetical order.
84 wxAutoNSAutoreleasePool pool;
85 if(!CreateControl(parent,winid,pos,size,style,validator,name))
89 m_cocoaItems = wxGCSafeRetain([NSMutableArray arrayWithCapacity:n]);
90 for(int i=0; i < n; i++)
92 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
95 m_itemClientData.Clear();
96 // Initialize n elements to NULL
97 m_itemClientData.SetCount(n,NULL);
99 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
100 [m_cocoaNSView release];
101 [GetNSTableView() setHeaderView: nil];
103 // Set up the data source
104 m_cocoaDataSource = [[WX_GET_OBJC_CLASS(wxCocoaNSTableDataSource) alloc] init];
105 [GetNSTableView() setDataSource:m_cocoaDataSource];
107 // Add the single column
108 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
109 [GetNSTableView() addTableColumn: tableColumn];
110 [tableColumn release];
112 [GetNSTableView() sizeToFit];
115 m_parent->CocoaAddChild(this);
116 // NSTableView does WEIRD things with sizes. Wrapping it in an
117 // NSScrollView seems to be the only reasonable solution.
118 CocoaCreateNSScrollView();
119 SetInitialFrameRect(pos,size);
121 [m_wxCocoaScrollView->GetNSScrollView() setHasVerticalScroller:YES];
122 // Pre-10.3: Always show vertical scroller, never show horizontal scroller
123 // Post-10.3: Show scrollers dynamically (turn them both on, set auto-hide)
124 if([m_wxCocoaScrollView->GetNSScrollView() respondsToSelector:@selector(setAutohidesScrollers:)])
126 [m_wxCocoaScrollView->GetNSScrollView() setHasHorizontalScroller:YES];
127 [m_wxCocoaScrollView->GetNSScrollView() setAutohidesScrollers:YES];
130 // Set up extended/multiple selection flags
131 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
132 //diff is that mult requires shift down for multi selection
133 [GetNSTableView() setAllowsMultipleSelection:true];
135 [GetNSTableView() setAllowsColumnSelection:false];
140 wxListBox::~wxListBox()
142 [GetNSTableView() setDataSource: nil];
143 [m_cocoaDataSource release];
144 wxGCSafeRelease(m_cocoaItems);
146 DisassociateNSTableView(GetNSTableView());
149 int wxListBox::CocoaDataSource_numberOfRows()
151 return [m_cocoaItems count];
154 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
155 WX_NSTableColumn tableColumn, int rowIndex)
157 return [m_cocoaItems objectAtIndex:rowIndex];
160 // pure virtuals from wxListBoxBase
161 bool wxListBox::IsSelected(int n) const
163 return [GetNSTableView() isRowSelected: n];
166 void wxListBox::DoSetSelection(int n, bool select)
169 [GetNSTableView() selectRow: n byExtendingSelection:NO];
171 [GetNSTableView() deselectRow: n];
174 int wxListBox::GetSelections(wxArrayInt& aSelections) const
177 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
178 while(NSNumber *num = [enumerator nextObject])
180 aSelections.Add([num intValue]);
182 return [GetNSTableView() numberOfSelectedRows];
185 int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type)
187 wxAutoNSAutoreleasePool pool;
189 const unsigned int numItems = items.GetCount();
190 for ( unsigned int i = 0; i < numItems; ++i, ++pos )
192 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
194 m_itemClientData.Insert(NULL, pos);
195 AssignNewItemClientData(pos, clientData, i, type);
198 [GetNSTableView() reloadData];
202 void wxListBox::DoSetFirstItem(int n)
204 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
205 void* pOld = m_itemClientData[n];
206 m_itemClientData[n] = m_itemClientData[0];
207 m_itemClientData[0] = pOld;
208 [GetNSTableView() reloadData];
212 // pure virtuals from wxItemContainer
214 void wxListBox::DoClear()
216 [m_cocoaItems removeAllObjects];
217 m_itemClientData.Clear();
218 [GetNSTableView() reloadData];
221 void wxListBox::DoDeleteOneItem(unsigned int n)
223 [m_cocoaItems removeObjectAtIndex:n];
224 m_itemClientData.RemoveAt(n);
225 [GetNSTableView() reloadData];
229 unsigned int wxListBox::GetCount() const
231 return (unsigned int)[m_cocoaItems count];
234 wxString wxListBox::GetString(unsigned int n) const
236 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
239 void wxListBox::SetString(unsigned int n, const wxString& s)
241 wxAutoNSAutoreleasePool pool;
242 [m_cocoaItems removeObjectAtIndex:n];
243 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
244 [GetNSTableView() reloadData];
247 int wxListBox::FindString(const wxString& s, bool bCase) const
249 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
250 wxAutoNSAutoreleasePool pool;
251 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
255 int wxListBox::GetSelection() const
257 return [GetNSTableView() selectedRow];
260 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
262 m_itemClientData[n] = clientData;
265 void* wxListBox::DoGetItemClientData(unsigned int n) const
267 return m_itemClientData[n];
270 #endif // wxUSE_LISTBOX