(1) Denis Pershin's patch for wxGTK (memory leaks corrections)
[wxWidgets.git] / src / gtk / listbox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: listbox.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id:
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 #ifdef __GNUG__
13 #pragma implementation "listbox.h"
14 #endif
15
16 #include "wx/dynarray.h"
17 #include "wx/listbox.h"
18 #include "wx/utils.h"
19
20 //-----------------------------------------------------------------------------
21 // data
22 //-----------------------------------------------------------------------------
23
24 extern bool g_blockEventsOnDrag;
25
26 //-----------------------------------------------------------------------------
27 // wxListBox
28 //-----------------------------------------------------------------------------
29
30 static void gtk_listitem_select_callback( GtkWidget *WXUNUSED(widget), wxListBox *listbox )
31 {
32 if (!listbox->HasVMT()) return;
33 if (g_blockEventsOnDrag) return;
34
35 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, listbox->GetId() );
36
37 wxArrayInt aSelections;
38 int count = listbox->GetSelections(aSelections);
39 if ( count > 0 )
40 {
41 event.m_commandInt = aSelections[0] ;
42 event.m_clientData = listbox->GetClientData(event.m_commandInt);
43 wxString str(listbox->GetString(event.m_commandInt));
44 if (str != "")
45 event.m_commandString = copystring((char *)(const char *)str);
46 }
47 else
48 {
49 event.m_commandInt = -1 ;
50 event.m_commandString = copystring("") ;
51 }
52
53 event.SetEventObject( listbox );
54
55 listbox->GetEventHandler()->ProcessEvent( event );
56 if (event.m_commandString) delete[] event.m_commandString ;
57 };
58
59 //-----------------------------------------------------------------------------
60
61 IMPLEMENT_DYNAMIC_CLASS(wxListBox,wxControl)
62
63 wxListBox::wxListBox(void)
64 {
65 m_list = NULL;
66 };
67
68 wxListBox::wxListBox( wxWindow *parent, wxWindowID id,
69 const wxPoint &pos, const wxSize &size,
70 int n, const wxString choices[],
71 long style, const wxString &name )
72 {
73 Create( parent, id, pos, size, n, choices, style, name );
74 };
75
76 bool wxListBox::Create( wxWindow *parent, wxWindowID id,
77 const wxPoint &pos, const wxSize &size,
78 int n, const wxString choices[],
79 long style, const wxString &name )
80 {
81 m_needParent = TRUE;
82
83 PreCreation( parent, id, pos, size, style, name );
84
85 m_widget = gtk_scrolled_window_new( NULL, NULL );
86 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
87 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
88
89 m_list = GTK_LIST( gtk_list_new() );
90
91 // @@ what's the difference between BROWSE and SINGLE?
92 GtkSelectionMode mode = GTK_SELECTION_BROWSE;
93 if ( style & wxLB_MULTIPLE )
94 mode = GTK_SELECTION_MULTIPLE;
95 else if ( style & wxLB_EXTENDED )
96 mode = GTK_SELECTION_EXTENDED;
97
98 gtk_list_set_selection_mode( GTK_LIST(m_list), mode );
99
100 gtk_container_add (GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
101 gtk_widget_show( GTK_WIDGET(m_list) );
102
103 for (int i = 0; i < n; i++)
104 {
105 GtkWidget *list_item;
106 list_item = gtk_list_item_new_with_label( choices[i] );
107
108 gtk_container_add( GTK_CONTAINER(m_list), list_item );
109
110 gtk_signal_connect( GTK_OBJECT(list_item), "select",
111 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
112
113 if ( style & wxLB_MULTIPLE )
114 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
115 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
116
117 m_clientData.Append( (wxObject*)NULL );
118
119 gtk_widget_show( list_item );
120 };
121
122 PostCreation();
123
124 gtk_widget_realize( GTK_WIDGET(m_list) );
125
126 Show( TRUE );
127
128 return TRUE;
129 };
130
131 void wxListBox::Append( const wxString &item )
132 {
133 Append( item, (char*)NULL );
134 };
135
136 void wxListBox::Append( const wxString &item, char *clientData )
137 {
138 GtkWidget *list_item;
139 list_item = gtk_list_item_new_with_label( item );
140
141 gtk_signal_connect( GTK_OBJECT(list_item), "select",
142 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
143
144 if ( GetWindowStyleFlag() & wxLB_MULTIPLE )
145 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
146 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
147
148 gtk_container_add( GTK_CONTAINER(m_list), list_item );
149
150 m_clientData.Append( (wxObject*)clientData );
151
152 gtk_widget_show( list_item );
153 };
154
155 void wxListBox::Clear(void)
156 {
157 gtk_list_clear_items( m_list, 0, Number() );
158
159 m_clientData.Clear();
160 };
161
162 void wxListBox::Delete( int n )
163 {
164 gtk_list_clear_items( m_list, n, n );
165
166 wxNode *node = m_clientData.Nth( n );
167 if (!node)
168 {
169 wxFAIL_MSG("wxListBox::Delete wrong index");
170 }
171 else
172 m_clientData.DeleteNode( node );
173 };
174
175 void wxListBox::Deselect( int n )
176 {
177 gtk_list_unselect_item( m_list, n );
178 };
179
180 int wxListBox::FindString( const wxString &item ) const
181 {
182 GList *child = m_list->children;
183 int count = 0;
184 while (child)
185 {
186 GtkBin *bin = GTK_BIN( child->data );
187 GtkLabel *label = GTK_LABEL( bin->child );
188 if (item == label->label) return count;
189 count++;
190 child = child->next;
191 };
192 return -1;
193 };
194
195 char *wxListBox::GetClientData( int n ) const
196 {
197 wxNode *node = m_clientData.Nth( n );
198 if (node) return ((char*)node->Data());
199 return NULL;
200 };
201
202 int wxListBox::GetSelection(void) const
203 {
204 GList *selection = m_list->selection;
205 if (selection)
206 {
207 GList *child = m_list->children;
208 int count = 0;
209 while (child)
210 {
211 if (child->data == selection->data) return count;
212 count++;
213 child = child->next;
214 };
215 };
216 return -1;
217 };
218
219 int wxListBox::GetSelections(wxArrayInt& aSelections) const
220 {
221 // get the number of selected items first
222 GList *child = m_list->children;
223 int count = 0;
224 for ( child = m_list->children; child != NULL; child = child->next ) {
225 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
226 count++;
227 }
228
229 aSelections.Empty();
230
231 if ( count > 0 ) {
232 // now fill the list
233 aSelections.Alloc(count); // optimization attempt
234 int i = 0;
235 for ( child = m_list->children; child != NULL; child = child->next, i++ ) {
236 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
237 aSelections.Add(i);
238 }
239 }
240
241 return count;
242 };
243
244 wxString wxListBox::GetString( int n ) const
245 {
246 GList *child = g_list_nth( m_list->children, n );
247 if (child)
248 {
249 GtkBin *bin = GTK_BIN( child->data );
250 GtkLabel *label = GTK_LABEL( bin->child );
251 return label->label;
252 };
253 return "";
254 };
255
256 wxString wxListBox::GetStringSelection(void) const
257 {
258 GList *selection = m_list->selection;
259 if (selection)
260 {
261 GtkBin *bin = GTK_BIN( selection->data );
262 wxString tmp = GTK_LABEL( bin->child )->label;
263 return tmp;
264 };
265 return "";
266 };
267
268 int wxListBox::Number(void)
269 {
270 GList *child = m_list->children;
271 int count = 0;
272 while (child) { count++; child = child->next; };
273 return count;
274 };
275
276 bool wxListBox::Selected( int n )
277 {
278 GList *target = g_list_nth( m_list->children, n );
279 if (target)
280 {
281 GList *child = m_list->selection;
282 while (child)
283 {
284 if (child->data == target->data) return TRUE;
285 child = child->next;
286 };
287 };
288 return FALSE;
289 };
290
291 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
292 {
293 };
294
295 void wxListBox::SetClientData( int n, char *clientData )
296 {
297 wxNode *node = m_clientData.Nth( n );
298 if (node) node->SetData( (wxObject*)clientData );
299 };
300
301 void wxListBox::SetFirstItem( int WXUNUSED(n) )
302 {
303 };
304
305 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
306 {
307 };
308
309 void wxListBox::SetSelection( int n, bool select )
310 {
311 if (select)
312 gtk_list_select_item( m_list, n );
313 else
314 gtk_list_unselect_item( m_list, n );
315 };
316
317 void wxListBox::SetString( int n, const wxString &string )
318 {
319 GList *child = g_list_nth( m_list->children, n );
320 if (child)
321 {
322 GtkBin *bin = GTK_BIN( child->data );
323 GtkLabel *label = GTK_LABEL( bin->child );
324 gtk_label_set( label, string );
325 };
326 };
327
328 void wxListBox::SetStringSelection( const wxString &string, bool select )
329 {
330 SetSelection( FindString(string), select );
331 };
332
333 int wxListBox::GetIndex( GtkWidget *item ) const
334 {
335 if (item)
336 {
337 GList *child = m_list->children;
338 int count = 0;
339 while (child)
340 {
341 if (GTK_WIDGET(child->data) == item) return count;
342 count++;
343 child = child->next;
344 };
345 };
346 return -1;
347 };
348
349 GtkWidget *wxListBox::GetDropTargetWidget(void)
350 {
351 return GTK_WIDGET(m_list);
352 };
353
354
355