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/NSTableDataSource.h"
28 #import <Foundation/NSArray.h>
29 #import <Foundation/NSEnumerator.h>
30 #import <AppKit/NSTableView.h>
31 #import <AppKit/NSTableColumn.h>
33 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControlWithItems)
34 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
36 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
38 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
41 const wxArrayString& choices,
43 const wxValidator& validator,
46 wxCArrayString chs(choices);
48 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
49 style, validator, name);
52 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
55 int n, const wxString choices[],
57 const wxValidator& validator,
62 Single-selection list.
65 Multiple-selection list: the user can toggle multiple items on and off.
68 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
71 Create horizontal scrollbar if contents are too wide (Windows only).
74 Always show a vertical scrollbar.
77 Only create a vertical scrollbar if needed.
80 The listbox contents are sorted in alphabetical order.
82 wxAutoNSAutoreleasePool pool;
83 if(!CreateControl(parent,winid,pos,size,style,validator,name))
87 m_cocoaItems = wxGCSafeRetain([NSMutableArray arrayWithCapacity:n]);
88 for(int i=0; i < n; i++)
90 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
93 m_itemClientData.Clear();
94 // Initialize n elements to NULL
95 m_itemClientData.SetCount(n,NULL);
97 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
98 [m_cocoaNSView release];
99 [GetNSTableView() setHeaderView: nil];
101 // Set up the data source
102 m_cocoaDataSource = [[WX_GET_OBJC_CLASS(wxCocoaNSTableDataSource) alloc] init];
103 [GetNSTableView() setDataSource:m_cocoaDataSource];
105 // Add the single column
106 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
107 [GetNSTableView() addTableColumn: tableColumn];
108 [tableColumn release];
110 [GetNSTableView() sizeToFit];
113 m_parent->CocoaAddChild(this);
114 // NSTableView does WEIRD things with sizes. Wrapping it in an
115 // NSScrollView seems to be the only reasonable solution.
116 CocoaCreateNSScrollView();
117 SetInitialFrameRect(pos,size);
119 // Set up extended/multiple selection flags
120 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
121 //diff is that mult requires shift down for multi selection
122 [GetNSTableView() setAllowsMultipleSelection:true];
124 [GetNSTableView() setAllowsColumnSelection:false];
129 wxListBox::~wxListBox()
131 [GetNSTableView() setDataSource: nil];
132 [m_cocoaDataSource release];
133 wxGCSafeRelease(m_cocoaItems);
135 DisassociateNSTableView(GetNSTableView());
138 int wxListBox::CocoaDataSource_numberOfRows()
140 return [m_cocoaItems count];
143 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
144 WX_NSTableColumn tableColumn, int rowIndex)
146 return [m_cocoaItems objectAtIndex:rowIndex];
149 // pure virtuals from wxListBoxBase
150 bool wxListBox::IsSelected(int n) const
152 return [GetNSTableView() isRowSelected: n];
155 void wxListBox::DoSetSelection(int n, bool select)
158 [GetNSTableView() selectRow: n byExtendingSelection:NO];
160 [GetNSTableView() deselectRow: n];
163 int wxListBox::GetSelections(wxArrayInt& aSelections) const
166 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
167 while(NSNumber *num = [enumerator nextObject])
169 aSelections.Add([num intValue]);
171 return [GetNSTableView() numberOfSelectedRows];
174 int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type)
176 wxAutoNSAutoreleasePool pool;
178 const unsigned int numItems = items.GetCount();
179 for ( unsigned int i = 0; i < numItems; ++i, ++pos )
181 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
183 m_itemClientData.Insert(NULL, pos);
184 AssignNewItemClientData(pos, clientData, i, type);
187 [GetNSTableView() reloadData];
191 void wxListBox::DoSetFirstItem(int n)
193 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
194 void* pOld = m_itemClientData[n];
195 m_itemClientData[n] = m_itemClientData[0];
196 m_itemClientData[0] = pOld;
197 [GetNSTableView() reloadData];
201 // pure virtuals from wxItemContainer
203 void wxListBox::DoClear()
205 [m_cocoaItems removeAllObjects];
206 m_itemClientData.Clear();
207 [GetNSTableView() reloadData];
210 void wxListBox::DoDeleteOneItem(unsigned int n)
212 [m_cocoaItems removeObjectAtIndex:n];
213 m_itemClientData.RemoveAt(n);
214 [GetNSTableView() reloadData];
218 unsigned int wxListBox::GetCount() const
220 return (unsigned int)[m_cocoaItems count];
223 wxString wxListBox::GetString(unsigned int n) const
225 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
228 void wxListBox::SetString(unsigned int n, const wxString& s)
230 wxAutoNSAutoreleasePool pool;
231 [m_cocoaItems removeObjectAtIndex:n];
232 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
233 [GetNSTableView() reloadData];
236 int wxListBox::FindString(const wxString& s, bool bCase) const
238 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
239 wxAutoNSAutoreleasePool pool;
240 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
244 int wxListBox::GetSelection() const
246 return [GetNSTableView() selectedRow];
249 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
251 m_itemClientData[n] = clientData;
254 void* wxListBox::DoGetItemClientData(unsigned int n) const
256 return m_itemClientData[n];
259 #endif // wxUSE_LISTBOX