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