Added trailing newline.
[wxWidgets.git] / src / cocoa / listbox.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        cocoa/listbox.mm
3 // Purpose:     wxListBox
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/03/18
7 // RCS-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 #ifndef WX_PRECOMP
17     #include "wx/log.h"
18     #include "wx/app.h"
19     #include "wx/listbox.h"
20 #endif //WX_PRECOMP
21
22 #include "wx/cocoa/string.h"
23 #include "wx/cocoa/autorelease.h"
24 #include "wx/cocoa/NSTableDataSource.h"
25
26 #import <Foundation/NSArray.h>
27 #import <Foundation/NSEnumerator.h>
28 #import <AppKit/NSTableView.h>
29 #import <AppKit/NSTableColumn.h>
30
31 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
32 BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase)
33 END_EVENT_TABLE()
34 WX_IMPLEMENT_COCOA_OWNER(wxListBox,NSTableView,NSControl,NSView)
35
36 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
37             const wxPoint& pos,
38             const wxSize& size,
39             const wxArrayString& choices,
40             long style,
41             const wxValidator& validator,
42             const wxString& name)
43 {
44     wxCArrayString chs(choices);
45
46     return Create(parent, winid, pos, size, chs.GetCount(), chs.GetStrings(),
47                   style, validator, name);
48 }
49
50 bool wxListBox::Create(wxWindow *parent, wxWindowID winid,
51             const wxPoint& pos,
52             const wxSize& size,
53             int n, const wxString choices[],
54             long style,
55             const wxValidator& validator,
56             const wxString& name)
57 {
58 /*
59 wxLB_SINGLE 
60 Single-selection list. 
61
62 wxLB_MULTIPLE 
63 Multiple-selection list: the user can toggle multiple items on and off. 
64
65 wxLB_EXTENDED 
66 Extended-selection list: the user can select multiple items using the SHIFT key and the mouse or special key combinations. 
67
68 wxLB_HSCROLL 
69 Create horizontal scrollbar if contents are too wide (Windows only). 
70
71 wxLB_ALWAYS_SB 
72 Always show a vertical scrollbar. 
73
74 wxLB_NEEDED_SB 
75 Only create a vertical scrollbar if needed. 
76
77 wxLB_SORT 
78 The listbox contents are sorted in alphabetical order. 
79 */
80     wxAutoNSAutoreleasePool pool;
81     if(!CreateControl(parent,winid,pos,size,style,validator,name))
82         return false;
83
84     // Provide the data
85     m_cocoaItems = [[NSMutableArray arrayWithCapacity:n] retain];
86     for(int i=0; i < n; i++)
87     {
88         [m_cocoaItems addObject: wxNSStringWithWxString(choices[i])];
89     }
90     // Remove everything
91     m_itemClientData.Clear();
92     // Initialize n elements to NULL
93     m_itemClientData.SetCount(n,NULL);
94
95     SetNSTableView([[NSTableView alloc] initWithFrame: MakeDefaultNSRect(size)]);
96     [m_cocoaNSView release];
97     [GetNSTableView() setHeaderView: nil];
98
99     // Set up the data source
100     m_cocoaDataSource = [[wxCocoaNSTableDataSource alloc] init];
101     [GetNSTableView() setDataSource:m_cocoaDataSource];
102
103     // Add the single column
104     NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:nil];
105     [GetNSTableView() addTableColumn: tableColumn];
106     [tableColumn release];
107
108     [GetNSTableView() sizeToFit];
109     // Finish
110     if(m_parent)
111         m_parent->CocoaAddChild(this);
112     // NSTableView does WEIRD things with sizes.  Wrapping it in an
113     // NSScrollView seems to be the only reasonable solution.
114     CocoaCreateNSScrollView();
115     SetInitialFrameRect(pos,size);
116     
117     // Set up extended/multiple selection flags
118     if ((style & wxLB_EXTENDED) || (style & wxLB_MULTIPLE)) 
119         //diff is that mult requires shift down for multi selection
120         [GetNSTableView() setAllowsMultipleSelection:true];
121
122     [GetNSTableView() setAllowsColumnSelection:false];
123
124     return true;
125 }
126
127 wxListBox::~wxListBox()
128 {
129     [GetNSTableView() setDataSource: nil];
130     [m_cocoaDataSource release];
131     [m_cocoaItems release];
132     DisassociateNSTableView(GetNSTableView());
133 }
134
135 int wxListBox::CocoaDataSource_numberOfRows()
136 {
137     return [m_cocoaItems count];
138 }
139
140 struct objc_object* wxListBox::CocoaDataSource_objectForTableColumn(
141         WX_NSTableColumn tableColumn, int rowIndex)
142 {
143     return [m_cocoaItems objectAtIndex:rowIndex];
144 }
145
146 // pure virtuals from wxListBoxBase
147 bool wxListBox::IsSelected(int n) const
148 {
149     return [GetNSTableView() isRowSelected: n];
150 }
151
152 void wxListBox::DoSetSelection(int n, bool select)
153 {
154     if(select)
155         [GetNSTableView() selectRow: n byExtendingSelection:NO];
156     else
157         [GetNSTableView() deselectRow: n];
158 }
159
160 int wxListBox::GetSelections(wxArrayInt& aSelections) const
161 {
162     aSelections.Clear();
163     NSEnumerator *enumerator = [GetNSTableView() selectedRowEnumerator];
164     while(NSNumber *num = [enumerator nextObject])
165     {
166         aSelections.Add([num intValue]);
167     }
168     return [GetNSTableView() numberOfSelectedRows];
169 }
170
171 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
172 {
173     wxAutoNSAutoreleasePool pool;
174
175     for(int i=int(items.GetCount())-1; i >= 0; i--)
176     {
177         [m_cocoaItems insertObject: wxNSStringWithWxString(items[i])
178             atIndex: pos];
179         m_itemClientData.Insert(NULL,pos);
180     }
181     [GetNSTableView() reloadData];
182 }
183
184 void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
185 {
186     wxAutoNSAutoreleasePool pool;
187     
188     // Remove everything
189     [m_cocoaItems removeAllObjects];
190     m_itemClientData.Clear();
191     // Provide the data
192     for(size_t i=0; i < items.GetCount(); i++)
193     {
194         [m_cocoaItems addObject: wxNSStringWithWxString(items[i])];
195         m_itemClientData.Add(clientData[i]);
196     }
197     [GetNSTableView() reloadData];
198 }
199
200 void wxListBox::DoSetFirstItem(int n)
201 {
202     [m_cocoaItems exchangeObjectAtIndex:0 withObjectAtIndex:n];
203     void* pOld = m_itemClientData[n];
204     m_itemClientData[n] = m_itemClientData[0];
205     m_itemClientData[0] = pOld;
206     [GetNSTableView() reloadData];
207 }
208
209
210 // pure virtuals from wxItemContainer
211     // deleting items
212 void wxListBox::Clear()
213 {
214     [m_cocoaItems removeAllObjects];
215     m_itemClientData.Clear();
216     [GetNSTableView() reloadData];
217 }
218
219 void wxListBox::Delete(int n)
220 {
221     [m_cocoaItems removeObjectAtIndex:n];
222     m_itemClientData.RemoveAt(n);
223     [GetNSTableView() reloadData];    
224 }
225
226     // accessing strings
227 int wxListBox::GetCount() const
228 {
229     return [m_cocoaItems count];
230 }
231
232 wxString wxListBox::GetString(int n) const
233 {
234     return wxStringWithNSString([m_cocoaItems objectAtIndex:n]);
235 }
236
237 void wxListBox::SetString(int n, const wxString& s)
238 {
239     wxAutoNSAutoreleasePool pool;
240     [m_cocoaItems removeObjectAtIndex:n];
241     [m_cocoaItems insertObject: wxNSStringWithWxString(s) atIndex: n];
242     [GetNSTableView() reloadData];    
243 }
244
245 int wxListBox::FindString(const wxString& s) const
246 {
247     wxAutoNSAutoreleasePool pool;
248     return [m_cocoaItems indexOfObject:wxNSStringWithWxString(s)];
249 }
250
251     // selection
252 int wxListBox::GetSelection() const
253 {
254     return [GetNSTableView() selectedRow];
255 }
256
257 int wxListBox::DoAppend(const wxString& item)
258 {
259     wxAutoNSAutoreleasePool pool;
260     [m_cocoaItems addObject:wxNSStringWithWxString(item)];    
261     [GetNSTableView() reloadData];    
262     m_itemClientData.Add(NULL);
263     return [m_cocoaItems count];
264 }
265
266 void wxListBox::DoSetItemClientData(int n, void* clientData)
267 {
268     m_itemClientData[n] = clientData;
269 }
270
271 void* wxListBox::DoGetItemClientData(int n) const
272 {
273     return m_itemClientData[n];
274 }
275
276 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
277 {
278     m_itemClientData[n] = (void*) clientData;
279 }
280
281 wxClientData* wxListBox::DoGetItemClientObject(int n) const
282 {
283     return (wxClientData*) m_itemClientData[n];
284 }
285
286 #endif