Add support for uniquifying to all wxCocoa Objective-C classes.
[wxWidgets.git] / src / cocoa / listbox.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/listbox.mm
3 // Purpose:     wxListBox
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/03/18
7 // Id:          $Id$
8 // Copyright:   (c) 2003 David Elliott
9 // Licence:     wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_LISTBOX
15
16 #include "wx/listbox.h"
17
18 #ifndef WX_PRECOMP
19     #include "wx/log.h"
20     #include "wx/app.h"
21 #endif //WX_PRECOMP
22
23 #include "wx/cocoa/string.h"
24 #include "wx/cocoa/autorelease.h"
25 #include "wx/cocoa/NSTableDataSource.h"
26
27 #import <Foundation/NSArray.h>
28 #import <Foundation/NSEnumerator.h>
29 #import <AppKit/NSTableView.h>
30 #import <AppKit/NSTableColumn.h>
31
32 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
33 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
34 END_EVENT_TABLE()
35 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
36
37 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
38             const wxPoint& pos,
39             const wxSize& size,
40             const wxArrayString& choices,
41             long style,
42             const wxValidator& validator,
43             const wxString& name)
44 {
45     wxCArrayString chs(choices);
46
47     return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
48                   style, validator, name);
49 }
50
51 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
52             const wxPoint& pos,
53             const wxSize& size,
54             int n, const wxString choices[],
55             long style,
56             const wxValidator& validator,
57             const wxString& name)
58 {
59 /*
60 wxLB_SINGLE
61 Single-selection list.
62
63 wxLB_MULTIPLE
64 Multiple-selection list: the user can toggle multiple items on and off.
65
66 wxLB_EXTENDED
67 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations.
68
69 wxLB_HSCROLL
70 Create horizontal scrollbar if contents are too wide (Windows only).
71
72 wxLB_ALWAYS_SB
73 Always show a vertical scrollbar.
74
75 wxLB_NEEDED_SB
76 Only create a vertical scrollbar if needed.
77
78 wxLB_SORT
79 The listbox contents are sorted in alphabetical order.
80 */
81     wxAutoNSAutoreleasePool pool;
82     if(!CreateControl(parent,winid,pos,size,style,validator,name))
83         return false;
84
85     // Provide the data
86     m_cocoaItems = [[NSMutableArray arrayWithCapacity:n] retain];
87     for(int i=0; i < n; i++)
88     {
89         [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
90     }
91     // Remove everything
92     m_itemClientData.Clear();
93     // Initialize n elements to NULL
94     m_itemClientData.SetCount(n,NULL);
95
96     SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
97     [m_cocoaNSView release];
98     [GetNSTableView() setHeaderView: nil];
99
100     // Set up the data source
101     m_cocoaDataSource = [[WX_GET_OBJC_CLASS(wxCocoaNSTableDataSource) alloc] init];
102     [GetNSTableView() setDataSource:m_cocoaDataSource];
103
104     // Add the single column
105     NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
106     [GetNSTableView() addTableColumn: tableColumn];
107     [tableColumn release];
108
109     [GetNSTableView() sizeToFit];
110     // Finish
111     if(m_parent)
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);
117
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];
122
123     [GetNSTableView() setAllowsColumnSelection:false];
124
125     return true;
126 }
127
128 wxListBox::~wxListBox()
129 {
130     [GetNSTableView() setDataSource: nil];
131     [m_cocoaDataSource release];
132     [m_cocoaItems release];
133     DisassociateNSTableView(GetNSTableView());
134 }
135
136 int wxListBox::CocoaDataSource_numberOfRows()
137 {
138     return [m_cocoaItems count];
139 }
140
141 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
142         WX_NSTableColumn tableColumn, int rowIndex)
143 {
144     return [m_cocoaItems objectAtIndex:rowIndex];
145 }
146
147 // pure virtuals from wxListBoxBase
148 bool wxListBox::IsSelected(int n) const
149 {
150     return [GetNSTableView() isRowSelected: n];
151 }
152
153 void wxListBox::DoSetSelection(int n, bool select)
154 {
155     if(select)
156         [GetNSTableView() selectRow: n byExtendingSelection:NO];
157     else
158         [GetNSTableView() deselectRow: n];
159 }
160
161 int wxListBox::GetSelections(wxArrayInt& aSelections) const
162 {
163     aSelections.Clear();
164     NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
165     while(NSNumber *num = [enumerator nextObject])
166     {
167         aSelections.Add([num intValue]);
168     }
169     return [GetNSTableView() numberOfSelectedRows];
170 }
171
172 int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, unsigned int pos, void **clientData, wxClientDataType type)
173 {
174     wxAutoNSAutoreleasePool pool;
175
176     const unsigned int numItems = items.GetCount();
177     for ( unsigned int i = 0; i < numItems; ++i, ++pos )
178     {
179         [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
180             atIndex: pos];
181         m_itemClientData.Insert(NULL, pos);
182         AssignNewItemClientData(pos, clientData, i, type);
183     }
184
185     [GetNSTableView() reloadData];
186     return pos - 1;
187 }
188
189 void wxListBox::DoSetFirstItem(int n)
190 {
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];
196 }
197
198
199 // pure virtuals from wxItemContainer
200     // deleting items
201 void wxListBox::DoClear()
202 {
203     [m_cocoaItems removeAllObjects];
204     m_itemClientData.Clear();
205     [GetNSTableView() reloadData];
206 }
207
208 void wxListBox::DoDeleteOneItem(unsigned int n)
209 {
210     [m_cocoaItems removeObjectAtIndex:n];
211     m_itemClientData.RemoveAt(n);
212     [GetNSTableView() reloadData];
213 }
214
215     // accessing strings
216 unsigned int wxListBox::GetCount() const
217 {
218     return (unsigned int)[m_cocoaItems count];
219 }
220
221 wxString wxListBox::GetString(unsigned int n) const
222 {
223     return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
224 }
225
226 void wxListBox::SetString(unsigned int n, const wxString& s)
227 {
228     wxAutoNSAutoreleasePool pool;
229     [m_cocoaItems removeObjectAtIndex:n];
230     [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
231     [GetNSTableView() reloadData];
232 }
233
234 int wxListBox::FindString(const wxString& s, bool bCase) const
235 {
236     // FIXME: use wxItemContainerImmutable::FindString for bCase parameter
237     wxAutoNSAutoreleasePool pool;
238     return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
239 }
240
241     // selection
242 int wxListBox::GetSelection() const
243 {
244     return [GetNSTableView() selectedRow];
245 }
246
247 void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
248 {
249     m_itemClientData[n] = clientData;
250 }
251
252 void* wxListBox::DoGetItemClientData(unsigned int n) const
253 {
254     return m_itemClientData[n];
255 }
256
257 #endif // wxUSE_LISTBOX