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