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/private/scrollview.h"
27 #include "wx/cocoa/NSTableDataSource.h"
29 #import <Foundation/NSArray.h>
30 #import <Foundation/NSEnumerator.h>
31 #import <AppKit/NSTableView.h>
32 #import <AppKit/NSTableColumn.h>
33 #import <AppKit/NSScrollView.h>
35 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControlWithItems)
36 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
38 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
40 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
43 const wxArrayString& choices,
45 const wxValidator& validator,
48 wxCArrayString chs(choices);
50 return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
51 style, validator, name);
54 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
57 int n, const wxString choices[],
59 const wxValidator& validator,
64 Single-selection list.
67 Multiple-selection list: the user can toggle multiple items on and off.
70 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
73 Create horizontal scrollbar if contents are too wide (Windows only).
76 Always show a vertical scrollbar.
79 Only create a vertical scrollbar if needed.
82 The listbox contents are sorted in alphabetical order.
84 wxAutoNSAutoreleasePool pool;
85 if(!CreateControl(parent,winid,pos,size,style,validator,name))
89 m_cocoaItems = wxGCSafeRetain([NSMutableArray arrayWithCapacity:n]);
90 for(int i=0; i < n; i++)
92 [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
95 m_itemClientData.Clear();
96 // Initialize n elements to NULL
97 m_itemClientData.SetCount(n,NULL);
99 SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
100 [m_cocoaNSView release];
101 [GetNSTableView() setHeaderView: nil];
103 // Set up the data source
104 m_cocoaDataSource = [[WX_GET_OBJC_CLASS(wxCocoaNSTableDataSource) alloc] init];
105 [GetNSTableView() setDataSource:m_cocoaDataSource];
107 // Add the single column
108 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
109 [GetNSTableView() addTableColumn: tableColumn];
110 [tableColumn release];
112 [GetNSTableView() sizeToFit];
115 m_parent->CocoaAddChild(this);
116 // NSTableView does WEIRD things with sizes. Wrapping it in an
117 // NSScrollView seems to be the only reasonable solution.
118 CocoaCreateNSScrollView();
119 SetInitialFrameRect(pos,size);
121 // Force showing of a vertical scrollbar
122 [m_wxCocoaScrollView->GetNSScrollView() setHasVerticalScroller:YES];
124 // Set up extended/multiple selection flags
125 if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE))
126 //diff is that mult requires shift down for multi selection
127 [GetNSTableView() setAllowsMultipleSelection:true];
129 [GetNSTableView() setAllowsColumnSelection:false];
134 wxListBox::~wxListBox()
136 [GetNSTableView() setDataSource: nil];
137 [m_cocoaDataSource release];
138 wxGCSafeRelease(m_cocoaItems);
140 DisassociateNSTableView(GetNSTableView());
143 int wxListBox::CocoaDataSource_numberOfRows()
145 return [m_cocoaItems count];
148 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
149 WX_NSTableColumn tableColumn, int rowIndex)
151 return [m_cocoaItems objectAtIndex:rowIndex];
154 // pure virtuals from wxListBoxBase
155 bool wxListBox::IsSelected(int n) const
157 return [GetNSTableView() isRowSelected: n];
160 void wxListBox::DoSetSelection(int n, bool select)
163 [GetNSTableView() selectRow: n byExtendingSelection:NO];
165 [GetNSTableView() deselectRow: n];
168 int wxListBox::GetSelections(wxArrayInt& aSelections) const
171 NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
172 while(NSNumber *num = [enumerator nextObject])
174 aSelections.Add([num intValue]);
176 return [GetNSTableView() numberOfSelectedRows];
179 int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type)
181 wxAutoNSAutoreleasePool pool;
183 const unsigned int numItems = items.GetCount();
184 for ( unsigned int i = 0; i < numItems; ++i, ++pos )
186 [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
188 m_itemClientData.Insert(NULL, pos);
189 AssignNewItemClientData(pos, clientData, i, type);
192 [GetNSTableView() reloadData];
196 void wxListBox::DoSetFirstItem(int n)
198 [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
199 void* pOld = m_itemClientData[n];
200 m_itemClientData[n] = m_itemClientData[0];
201 m_itemClientData[0] = pOld;
202 [GetNSTableView() reloadData];
206 // pure virtuals from wxItemContainer
208 void wxListBox::DoClear()
210 [m_cocoaItems removeAllObjects];
211 m_itemClientData.Clear();
212 [GetNSTableView() reloadData];
215 void wxListBox::DoDeleteOneItem(unsigned int n)
217 [m_cocoaItems removeObjectAtIndex:n];
218 m_itemClientData.RemoveAt(n);
219 [GetNSTableView() reloadData];
223 unsigned int wxListBox::GetCount() const
225 return (unsigned int)[m_cocoaItems count];
228 wxString wxListBox::GetString(unsigned int n) const
230 return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
233 void wxListBox::SetString(unsigned int n, const wxString& s)
235 wxAutoNSAutoreleasePool pool;
236 [m_cocoaItems removeObjectAtIndex:n];
237 [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
238 [GetNSTableView() reloadData];
241 int wxListBox::FindString(const wxString& s, bool bCase) const
243 // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
244 wxAutoNSAutoreleasePool pool;
245 return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
249 int wxListBox::GetSelection() const
251 return [GetNSTableView() selectedRow];
254 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
256 m_itemClientData[n] = clientData;
259 void* wxListBox::DoGetItemClientData(unsigned int n) const
261 return m_itemClientData[n];
264 #endif // wxUSE_LISTBOX