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/NSTableDataSource.h"
27 #import <Foundation/NSArray.h>
28 #import <Foundation/NSEnumerator.h>
29 #import <AppKit/NSTableView.h>
30 #import <AppKit/NSTableColumn.h>
32 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
33 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
35 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
37 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
40 const wxArrayString& choices,
42 const wxValidator& validator,
45 wxCArrayString chs(choices);
47 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
48 style, validator, name);
51 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
54 int n, const wxString choices[],
56 const wxValidator& validator,
61 Single-selection list.
64 Multiple-selection list: the user can toggle multiple items on and off.
67 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
70 Create horizontal scrollbar if contents are too wide (Windows only).
73 Always show a vertical scrollbar.
76 Only create a vertical scrollbar if needed.
79 The listbox contents are sorted in alphabetical order.
81 wxAutoNSAutoreleasePool pool;
82 if(!CreateControl(parent,winid,pos,size,style,validator,name))
86 m_cocoaItems = [[NSMutableArray arrayWithCapacity:n] retain];
87 for(int i=0; i < n; i++)
89 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
92 m_itemClientData.Clear();
93 // Initialize n elements to NULL
94 m_itemClientData.SetCount(n,NULL);
96 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
97 [m_cocoaNSView release];
98 [GetNSTableView() setHeaderView: nil];
100 // Set up the data source
101 m_cocoaDataSource = [[wxCocoaNSTableDataSource alloc] init];
102 [GetNSTableView() setDataSource:m_cocoaDataSource];
104 // Add the single column
105 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
106 [GetNSTableView() addTableColumn: tableColumn];
107 [tableColumn release];
109 [GetNSTableView() sizeToFit];
112 m_parent->CocoaAddChild(this);
113 // NSTableView does WEIRD things with sizes. Wrapping it in an
114 // NSScrollView seems to be the only reasonable solution.
115 CocoaCreateNSScrollView();
116 SetInitialFrameRect(pos,size);
118 // Set up extended/multiple selection flags
119 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
120 //diff is that mult requires shift down for multi selection
121 [GetNSTableView() setAllowsMultipleSelection:true];
123 [GetNSTableView() setAllowsColumnSelection:false];
128 wxListBox::~wxListBox()
130 [GetNSTableView() setDataSource: nil];
131 [m_cocoaDataSource release];
132 [m_cocoaItems release];
133 DisassociateNSTableView(GetNSTableView());
136 int wxListBox::CocoaDataSource_numberOfRows()
138 return [m_cocoaItems count];
141 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
142 WX_NSTableColumn tableColumn, int rowIndex)
144 return [m_cocoaItems objectAtIndex:rowIndex];
147 // pure virtuals from wxListBoxBase
148 bool wxListBox::IsSelected(int n) const
150 return [GetNSTableView() isRowSelected: n];
153 void wxListBox::DoSetSelection(int n, bool select)
156 [GetNSTableView() selectRow: n byExtendingSelection:NO];
158 [GetNSTableView() deselectRow: n];
161 int wxListBox::GetSelections(wxArrayInt& aSelections) const
164 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
165 while(NSNumber *num = [enumerator nextObject])
167 aSelections.Add([num intValue]);
169 return [GetNSTableView() numberOfSelectedRows];
172 void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
174 wxAutoNSAutoreleasePool pool;
176 for(int i=int(items.GetCount())-1; i >= 0; i--)
178 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
180 m_itemClientData.Insert(NULL,pos);
182 [GetNSTableView() reloadData];
185 void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
187 wxAutoNSAutoreleasePool pool;
190 [m_cocoaItems removeAllObjects];
191 m_itemClientData.Clear();
193 for(unsigned int i=0; i < items.GetCount(); i++)
195 [m_cocoaItems addObject: wxNSStringWithWxString(items[i])];
196 m_itemClientData.Add(clientData[i]);
198 [GetNSTableView() reloadData];
201 void wxListBox::DoSetFirstItem(int n)
203 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
204 void* pOld = m_itemClientData[n];
205 m_itemClientData[n] = m_itemClientData[0];
206 m_itemClientData[0] = pOld;
207 [GetNSTableView() reloadData];
211 // pure virtuals from wxItemContainer
213 void wxListBox::Clear()
215 [m_cocoaItems removeAllObjects];
216 m_itemClientData.Clear();
217 [GetNSTableView() reloadData];
220 void wxListBox::Delete(unsigned int n)
222 [m_cocoaItems removeObjectAtIndex:n];
223 m_itemClientData.RemoveAt(n);
224 [GetNSTableView() reloadData];
228 unsigned int wxListBox::GetCount() const
230 return (unsigned int)[m_cocoaItems count];
233 wxString wxListBox::GetString(unsigned int n) const
235 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
238 void wxListBox::SetString(unsigned int n, const wxString& s)
240 wxAutoNSAutoreleasePool pool;
241 [m_cocoaItems removeObjectAtIndex:n];
242 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
243 [GetNSTableView() reloadData];
246 int wxListBox::FindString(const wxString& s, bool bCase) const
248 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
249 wxAutoNSAutoreleasePool pool;
250 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
254 int wxListBox::GetSelection() const
256 return [GetNSTableView() selectedRow];
259 int wxListBox::DoAppend(const wxString& item)
261 wxAutoNSAutoreleasePool pool;
262 [m_cocoaItems addObject:wxNSStringWithWxString(item)];
263 [GetNSTableView() reloadData];
264 m_itemClientData.Add(NULL);
265 return [m_cocoaItems count];
268 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
270 m_itemClientData[n] = clientData;
273 void* wxListBox::DoGetItemClientData(unsigned int n) const
275 return m_itemClientData[n];
278 void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
280 m_itemClientData[n] = (void*) clientData;
283 wxClientData* wxListBox::DoGetItemClientObject(unsigned int n) const
285 return (wxClientData*) m_itemClientData[n];