1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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"
19 #include "wx/cocoa/string.h"
20 #include "wx/cocoa/autorelease.h"
21 #include "wx/cocoa/NSTableDataSource.h"
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSEnumerator.h>
25 #import <AppKit/NSTableView.h>
26 #import <AppKit/NSTableColumn.h>
28 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
29 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
31 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
33 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
36 const wxArrayString& choices,
38 const wxValidator& validator,
41 wxCArrayString chs(choices);
43 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
44 style, validator, name);
47 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
50 int n, const wxString choices[],
52 const wxValidator& validator,
57 Single-selection list.
60 Multiple-selection list: the user can toggle multiple items on and off.
63 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
66 Create horizontal scrollbar if contents are too wide (Windows only).
69 Always show a vertical scrollbar.
72 Only create a vertical scrollbar if needed.
75 The listbox contents are sorted in alphabetical order.
77 wxAutoNSAutoreleasePool pool;
78 if(!CreateControl(parent,winid,pos,size,style,validator,name))
82 m_cocoaItems = [[NSMutableArray arrayWithCapacity:n] retain];
83 for(int i=0; i < n; i++)
85 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
88 m_itemClientData.Clear();
89 // Initialize n elements to NULL
90 m_itemClientData.SetCount(n,NULL);
92 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
93 [m_cocoaNSView release];
94 [GetNSTableView() setHeaderView: nil];
96 // Set up the data source
97 m_cocoaDataSource = [[wxCocoaNSTableDataSource alloc] init];
98 [GetNSTableView() setDataSource:m_cocoaDataSource];
100 // Add the single column
101 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
102 [GetNSTableView() addTableColumn: tableColumn];
103 [tableColumn release];
105 [GetNSTableView() sizeToFit];
108 m_parent->CocoaAddChild(this);
109 // NSTableView does WEIRD things with sizes. Wrapping it in an
110 // NSScrollView seems to be the only reasonable solution.
111 CocoaCreateNSScrollView();
112 SetInitialFrameRect(pos,size);
114 // Set up extended/multiple selection flags
115 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
116 //diff is that mult requires shift down for multi selection
117 [GetNSTableView() setAllowsMultipleSelection:true];
119 [GetNSTableView() setAllowsColumnSelection:false];
124 wxListBox::~wxListBox()
126 [GetNSTableView() setDataSource: nil];
127 [m_cocoaDataSource release];
128 [m_cocoaItems release];
129 DisassociateNSTableView(GetNSTableView());
132 int wxListBox::CocoaDataSource_numberOfRows()
134 return [m_cocoaItems count];
137 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
138 WX_NSTableColumn tableColumn, int rowIndex)
140 return [m_cocoaItems objectAtIndex:rowIndex];
143 // pure virtuals from wxListBoxBase
144 bool wxListBox::IsSelected(int n) const
146 return [GetNSTableView() isRowSelected: n];
149 void wxListBox::DoSetSelection(int n, bool select)
152 [GetNSTableView() selectRow: n byExtendingSelection:NO];
154 [GetNSTableView() deselectRow: n];
157 int wxListBox::GetSelections(wxArrayInt& aSelections) const
160 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
161 while(NSNumber *num = [enumerator nextObject])
163 aSelections.Add([num intValue]);
165 return [GetNSTableView() numberOfSelectedRows];
168 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
170 wxAutoNSAutoreleasePool pool;
172 for(int i=int(items.GetCount())-1; i >= 0; i--)
174 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
176 m_itemClientData.Insert(NULL,pos);
178 [GetNSTableView() reloadData];
181 void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
183 wxAutoNSAutoreleasePool pool;
186 [m_cocoaItems removeAllObjects];
187 m_itemClientData.Clear();
189 for(size_t i=0; i < items.GetCount(); i++)
191 [m_cocoaItems addObject: wxNSStringWithWxString(items[i])];
192 m_itemClientData.Add(clientData[i]);
194 [GetNSTableView() reloadData];
197 void wxListBox::DoSetFirstItem(int n)
199 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
200 void* pOld = m_itemClientData[n];
201 m_itemClientData[n] = m_itemClientData[0];
202 m_itemClientData[0] = pOld;
203 [GetNSTableView() reloadData];
207 // pure virtuals from wxItemContainer
209 void wxListBox::Clear()
211 [m_cocoaItems removeAllObjects];
212 m_itemClientData.Clear();
213 [GetNSTableView() reloadData];
216 void wxListBox::Delete(int n)
218 [m_cocoaItems removeObjectAtIndex:n];
219 m_itemClientData.RemoveAt(n);
220 [GetNSTableView() reloadData];
224 int wxListBox::GetCount() const
226 return [m_cocoaItems count];
229 wxString wxListBox::GetString(int n) const
231 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
234 void wxListBox::SetString(int n, const wxString& s)
236 wxAutoNSAutoreleasePool pool;
237 [m_cocoaItems removeObjectAtIndex:n];
238 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
239 [GetNSTableView() reloadData];
242 int wxListBox::FindString(const wxString& s) const
244 wxAutoNSAutoreleasePool pool;
245 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
249 int wxListBox::GetSelection() const
251 return [GetNSTableView() selectedRow];
254 int wxListBox::DoAppend(const wxString& item)
256 wxAutoNSAutoreleasePool pool;
257 [m_cocoaItems addObject:wxNSStringWithWxString(item)];
258 [GetNSTableView() reloadData];
259 m_itemClientData.Add(NULL);
260 return [m_cocoaItems count];
263 void wxListBox::DoSetItemClientData(int n, void* clientData)
265 m_itemClientData[n] = clientData;
268 void* wxListBox::DoGetItemClientData(int n) const
270 return m_itemClientData[n];
273 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
275 m_itemClientData[n] = (void*) clientData;
278 wxClientData* wxListBox::DoGetItemClientObject(int n) const
280 return (wxClientData*) m_itemClientData[n];