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"
19 #include "wx/listbox.h"
22 #include "wx/cocoa/string.h"
23 #include "wx/cocoa/autorelease.h"
24 #include "wx/cocoa/NSTableDataSource.h"
26 #import <Foundation/NSArray.h>
27 #import <Foundation/NSEnumerator.h>
28 #import <AppKit/NSTableView.h>
29 #import <AppKit/NSTableColumn.h>
31 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
32 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
34 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
36 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
39 const wxArrayString& choices,
41 const wxValidator& validator,
44 wxCArrayString chs(choices);
46 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
47 style, validator, name);
50 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
53 int n, const wxString choices[],
55 const wxValidator& validator,
60 Single-selection list.
63 Multiple-selection list: the user can toggle multiple items on and off.
66 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
69 Create horizontal scrollbar if contents are too wide (Windows only).
72 Always show a vertical scrollbar.
75 Only create a vertical scrollbar if needed.
78 The listbox contents are sorted in alphabetical order.
80 wxAutoNSAutoreleasePool pool;
81 if(!CreateControl(parent,winid,pos,size,style,validator,name))
85 m_cocoaItems = [[NSMutableArray arrayWithCapacity:n] retain];
86 for(int i=0; i < n; i++)
88 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
91 m_itemClientData.Clear();
92 // Initialize n elements to NULL
93 m_itemClientData.SetCount(n,NULL);
95 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
96 [m_cocoaNSView release];
97 [GetNSTableView() setHeaderView: nil];
99 // Set up the data source
100 m_cocoaDataSource = [[wxCocoaNSTableDataSource alloc] init];
101 [GetNSTableView() setDataSource:m_cocoaDataSource];
103 // Add the single column
104 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
105 [GetNSTableView() addTableColumn: tableColumn];
106 [tableColumn release];
108 [GetNSTableView() sizeToFit];
111 m_parent->CocoaAddChild(this);
112 // NSTableView does WEIRD things with sizes. Wrapping it in an
113 // NSScrollView seems to be the only reasonable solution.
114 CocoaCreateNSScrollView();
115 SetInitialFrameRect(pos,size);
117 // Set up extended/multiple selection flags
118 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
119 //diff is that mult requires shift down for multi selection
120 [GetNSTableView() setAllowsMultipleSelection:true];
122 [GetNSTableView() setAllowsColumnSelection:false];
127 wxListBox::~wxListBox()
129 [GetNSTableView() setDataSource: nil];
130 [m_cocoaDataSource release];
131 [m_cocoaItems release];
132 DisassociateNSTableView(GetNSTableView());
135 int wxListBox::CocoaDataSource_numberOfRows()
137 return [m_cocoaItems count];
140 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
141 WX_NSTableColumn tableColumn, int rowIndex)
143 return [m_cocoaItems objectAtIndex:rowIndex];
146 // pure virtuals from wxListBoxBase
147 bool wxListBox::IsSelected(int n) const
149 return [GetNSTableView() isRowSelected: n];
152 void wxListBox::DoSetSelection(int n, bool select)
155 [GetNSTableView() selectRow: n byExtendingSelection:NO];
157 [GetNSTableView() deselectRow: n];
160 int wxListBox::GetSelections(wxArrayInt& aSelections) const
163 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
164 while(NSNumber *num = [enumerator nextObject])
166 aSelections.Add([num intValue]);
168 return [GetNSTableView() numberOfSelectedRows];
171 void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
173 wxAutoNSAutoreleasePool pool;
175 for(int i=int(items.GetCount())-1; i >= 0; i--)
177 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
179 m_itemClientData.Insert(NULL,pos);
181 [GetNSTableView() reloadData];
184 void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
186 wxAutoNSAutoreleasePool pool;
189 [m_cocoaItems removeAllObjects];
190 m_itemClientData.Clear();
192 for(unsigned int i=0; i < items.GetCount(); i++)
194 [m_cocoaItems addObject: wxNSStringWithWxString(items[i])];
195 m_itemClientData.Add(clientData[i]);
197 [GetNSTableView() reloadData];
200 void wxListBox::DoSetFirstItem(int n)
202 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
203 void* pOld = m_itemClientData[n];
204 m_itemClientData[n] = m_itemClientData[0];
205 m_itemClientData[0] = pOld;
206 [GetNSTableView() reloadData];
210 // pure virtuals from wxItemContainer
212 void wxListBox::Clear()
214 [m_cocoaItems removeAllObjects];
215 m_itemClientData.Clear();
216 [GetNSTableView() reloadData];
219 void wxListBox::Delete(unsigned int n)
221 [m_cocoaItems removeObjectAtIndex:n];
222 m_itemClientData.RemoveAt(n);
223 [GetNSTableView() reloadData];
227 unsigned int wxListBox::GetCount() const
229 return (unsigned int)[m_cocoaItems count];
232 wxString wxListBox::GetString(unsigned int n) const
234 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
237 void wxListBox::SetString(unsigned int n, const wxString& s)
239 wxAutoNSAutoreleasePool pool;
240 [m_cocoaItems removeObjectAtIndex:n];
241 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
242 [GetNSTableView() reloadData];
245 int wxListBox::FindString(const wxString& s, bool bCase) const
247 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
248 wxAutoNSAutoreleasePool pool;
249 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
253 int wxListBox::GetSelection() const
255 return [GetNSTableView() selectedRow];
258 int wxListBox::DoAppend(const wxString& item)
260 wxAutoNSAutoreleasePool pool;
261 [m_cocoaItems addObject:wxNSStringWithWxString(item)];
262 [GetNSTableView() reloadData];
263 m_itemClientData.Add(NULL);
264 return [m_cocoaItems count];
267 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
269 m_itemClientData[n] = clientData;
272 void* wxListBox::DoGetItemClientData(unsigned int n) const
274 return m_itemClientData[n];
277 void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
279 m_itemClientData[n] = (void*) clientData;
282 wxClientData* wxListBox::DoGetItemClientObject(unsigned int n) const
284 return (wxClientData*) m_itemClientData[n];