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 int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type)
174 wxAutoNSAutoreleasePool pool;
176 const unsigned int numItems = items.GetCount();
177 for ( unsigned int i = 0; i < numItems; ++i, ++pos )
179 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
181 m_itemClientData.Insert(NULL, pos);
182 AssignNewItemClientData(pos, clientData, i, type);
185 [GetNSTableView() reloadData];
189 void wxListBox::DoSetFirstItem(int n)
191 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
192 void* pOld = m_itemClientData[n];
193 m_itemClientData[n] = m_itemClientData[0];
194 m_itemClientData[0] = pOld;
195 [GetNSTableView() reloadData];
199 // pure virtuals from wxItemContainer
201 void wxListBox::DoClear()
203 [m_cocoaItems removeAllObjects];
204 m_itemClientData.Clear();
205 [GetNSTableView() reloadData];
208 void wxListBox::DoDeleteOneItem(unsigned int n)
210 [m_cocoaItems removeObjectAtIndex:n];
211 m_itemClientData.RemoveAt(n);
212 [GetNSTableView() reloadData];
216 unsigned int wxListBox::GetCount() const
218 return (unsigned int)[m_cocoaItems count];
221 wxString wxListBox::GetString(unsigned int n) const
223 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
226 void wxListBox::SetString(unsigned int n, const wxString& s)
228 wxAutoNSAutoreleasePool pool;
229 [m_cocoaItems removeObjectAtIndex:n];
230 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
231 [GetNSTableView() reloadData];
234 int wxListBox::FindString(const wxString& s, bool bCase) const
236 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
237 wxAutoNSAutoreleasePool pool;
238 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
242 int wxListBox::GetSelection() const
244 return [GetNSTableView() selectedRow];
247 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
249 m_itemClientData[n] = clientData;
252 void* wxListBox::DoGetItemClientData(unsigned int n) const
254 return m_itemClientData[n];
257 #endif // wxUSE_LISTBOX