Fixed wxCheckBox on wxGTK (SetLabel called before widget creation),
[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 #include <wx/intl.h>
20
21 //-----------------------------------------------------------------------------
22 // data
23 //-----------------------------------------------------------------------------
24
25 extern bool g_blockEventsOnDrag;
26
27 //-----------------------------------------------------------------------------
28 // "select" and "deselect"
29 //-----------------------------------------------------------------------------
30
31 static void gtk_listitem_select_callback( GtkWidget *WXUNUSED(widget), wxListBox *listbox )
32 {
33 if (!listbox->HasVMT()) return;
34 if (g_blockEventsOnDrag) return;
35
36 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, listbox->GetId() );
37
38 wxArrayInt aSelections;
39 int count = listbox->GetSelections(aSelections);
40 if ( count > 0 )
41 {
42 event.m_commandInt = aSelections[0] ;
43 event.m_clientData = listbox->GetClientData(event.m_commandInt);
44 wxString str(listbox->GetString(event.m_commandInt));
45 if (str != "")
46 event.m_commandString = copystring((char *)(const char *)str);
47 }
48 else
49 {
50 event.m_commandInt = -1 ;
51 event.m_commandString = copystring("") ;
52 }
53
54 event.SetEventObject( listbox );
55
56 listbox->GetEventHandler()->ProcessEvent( event );
57 if (event.m_commandString) delete[] event.m_commandString ;
58 }
59
60 //-----------------------------------------------------------------------------
61 // wxListBox
62 //-----------------------------------------------------------------------------
63
64 IMPLEMENT_DYNAMIC_CLASS(wxListBox,wxControl)
65
66 wxListBox::wxListBox(void)
67 {
68 m_list = (GtkList *) NULL;
69 }
70
71 bool wxListBox::Create( wxWindow *parent, wxWindowID id,
72 const wxPoint &pos, const wxSize &size,
73 int n, const wxString choices[],
74 long style, const wxValidator& validator, const wxString &name )
75 {
76 m_needParent = TRUE;
77
78 PreCreation( parent, id, pos, size, style, name );
79
80 SetValidator( validator );
81
82 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
83 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
84 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
85
86 m_list = GTK_LIST( gtk_list_new() );
87
88 GtkSelectionMode mode = GTK_SELECTION_SINGLE;
89 if (style & wxLB_MULTIPLE)
90 mode = GTK_SELECTION_MULTIPLE;
91 else if (style & wxLB_EXTENDED)
92 mode = GTK_SELECTION_EXTENDED;
93
94 gtk_list_set_selection_mode( GTK_LIST(m_list), mode );
95
96 gtk_container_add (GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
97 gtk_widget_show( GTK_WIDGET(m_list) );
98
99 for (int i = 0; i < n; i++)
100 {
101 GtkWidget *list_item;
102 list_item = gtk_list_item_new_with_label( choices[i] );
103
104 gtk_container_add( GTK_CONTAINER(m_list), list_item );
105
106 gtk_signal_connect( GTK_OBJECT(list_item), "select",
107 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
108
109 if (style & wxLB_MULTIPLE)
110 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
111 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
112
113 m_clientData.Append( (wxObject*)NULL );
114
115 gtk_widget_show( list_item );
116 }
117
118 PostCreation();
119
120 gtk_widget_realize( GTK_WIDGET(m_list) );
121
122 Show( TRUE );
123
124 return TRUE;
125 }
126
127 void wxListBox::Append( const wxString &item )
128 {
129 Append( item, (char*)NULL );
130 }
131
132 void wxListBox::Append( const wxString &item, char *clientData )
133 {
134 GtkWidget *list_item = gtk_list_item_new_with_label( item );
135
136 if (m_hasOwnStyle)
137 {
138 GtkBin *bin = GTK_BIN( list_item );
139 gtk_widget_set_style( bin->child,
140 gtk_style_ref(
141 gtk_widget_get_style( m_widget ) ) );
142 }
143
144 gtk_signal_connect( GTK_OBJECT(list_item), "select",
145 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
146
147 if (GetWindowStyleFlag() & wxLB_MULTIPLE)
148 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
149 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
150
151 m_clientData.Append( (wxObject*)clientData );
152
153 gtk_container_add( GTK_CONTAINER(m_list), list_item );
154
155 gtk_widget_show( list_item );
156
157 ConnectWidget( list_item );
158
159 ConnectDnDWidget( list_item );
160
161 }
162
163 void wxListBox::Clear(void)
164 {
165 gtk_list_clear_items( m_list, 0, Number() );
166
167 m_clientData.Clear();
168 }
169
170 void wxListBox::Delete( int n )
171 {
172 GList *child = g_list_nth( m_list->children, n );
173
174 if (!child)
175 {
176 wxFAIL_MSG("wrong listbox index");
177 return;
178 }
179
180 GList *list = g_list_append( NULL, child->data );
181 gtk_list_remove_items( m_list, list );
182 g_list_free( list );
183
184 wxNode *node = m_clientData.Nth( n );
185 if (!node)
186 {
187 wxFAIL_MSG("wrong listbox index");
188 }
189 else
190 m_clientData.DeleteNode( node );
191 }
192
193 void wxListBox::Deselect( int n )
194 {
195 gtk_list_unselect_item( m_list, n );
196 }
197
198 int wxListBox::FindString( const wxString &item ) const
199 {
200 GList *child = m_list->children;
201 int count = 0;
202 while (child)
203 {
204 GtkBin *bin = GTK_BIN( child->data );
205 GtkLabel *label = GTK_LABEL( bin->child );
206 if (item == label->label) return count;
207 count++;
208 child = child->next;
209 }
210 wxFAIL_MSG("wrong listbox index");
211 return -1;
212 }
213
214 char *wxListBox::GetClientData( int n ) const
215 {
216 wxNode *node = m_clientData.Nth( n );
217 if (node) return ((char*)node->Data());
218
219 wxFAIL_MSG("wrong listbox index");
220 return (char *) NULL;
221 }
222
223 int wxListBox::GetSelection(void) const
224 {
225 GList *selection = m_list->selection;
226 if (selection)
227 {
228 GList *child = m_list->children;
229 int count = 0;
230 while (child)
231 {
232 if (child->data == selection->data) return count;
233 count++;
234 child = child->next;
235 }
236 }
237 // No, I think it's reasonable to return -1 to indicate
238 // there is no selection. -- JACS
239 // wxFAIL_MSG("wrong listbox index");
240 return -1;
241 }
242
243 int wxListBox::GetSelections(wxArrayInt& aSelections) const
244 {
245 // get the number of selected items first
246 GList *child = m_list->children;
247 int count = 0;
248 for ( child = m_list->children; child != NULL; child = child->next )
249 {
250 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
251 count++;
252 }
253
254 aSelections.Empty();
255
256 if ( count > 0 ) {
257 // now fill the list
258 aSelections.Alloc(count); // optimization attempt
259 int i = 0;
260 for ( child = m_list->children; child != NULL; child = child->next, i++ )
261 {
262 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
263 aSelections.Add(i);
264 }
265 }
266
267 return count;
268 }
269
270 wxString wxListBox::GetString( int n ) const
271 {
272 GList *child = g_list_nth( m_list->children, n );
273 if (child)
274 {
275 GtkBin *bin = GTK_BIN( child->data );
276 GtkLabel *label = GTK_LABEL( bin->child );
277 return label->label;
278 }
279 wxFAIL_MSG("wrong listbox index");
280 return "";
281 }
282
283 wxString wxListBox::GetStringSelection(void) const
284 {
285 GList *selection = m_list->selection;
286 if (selection)
287 {
288 GtkBin *bin = GTK_BIN( selection->data );
289 wxString tmp = GTK_LABEL( bin->child )->label;
290 return tmp;
291 }
292 wxFAIL_MSG("no listbox selection available");
293 return "";
294 }
295
296 int wxListBox::Number(void)
297 {
298 GList *child = m_list->children;
299 int count = 0;
300 while (child) { count++; child = child->next; }
301 return count;
302 }
303
304 bool wxListBox::Selected( int n )
305 {
306 GList *target = g_list_nth( m_list->children, n );
307 if (target)
308 {
309 GList *child = m_list->selection;
310 while (child)
311 {
312 if (child->data == target->data) return TRUE;
313 child = child->next;
314 }
315 }
316 wxFAIL_MSG("wrong listbox index");
317 return FALSE;
318 }
319
320 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
321 {
322 wxFAIL_MSG("wxListBox::Set not implemented");
323 }
324
325 void wxListBox::SetClientData( int n, char *clientData )
326 {
327 wxNode *node = m_clientData.Nth( n );
328 if (node)
329 {
330 node->SetData( (wxObject*)clientData );
331 }
332 else
333 {
334 wxFAIL_MSG("wrong listbox index");
335 }
336 }
337
338 void wxListBox::SetFirstItem( int WXUNUSED(n) )
339 {
340 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
341 }
342
343 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
344 {
345 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
346 }
347
348 void wxListBox::SetSelection( int n, bool select )
349 {
350 if (select)
351 gtk_list_select_item( m_list, n );
352 else
353 gtk_list_unselect_item( m_list, n );
354 }
355
356 void wxListBox::SetString( int n, const wxString &string )
357 {
358 GList *child = g_list_nth( m_list->children, n );
359 if (child)
360 {
361 GtkBin *bin = GTK_BIN( child->data );
362 GtkLabel *label = GTK_LABEL( bin->child );
363 gtk_label_set( label, string );
364 }
365 else
366 {
367 wxFAIL_MSG("wrong listbox index");
368 }
369 }
370
371 void wxListBox::SetStringSelection( const wxString &string, bool select )
372 {
373 SetSelection( FindString(string), select );
374 }
375
376 int wxListBox::GetIndex( GtkWidget *item ) const
377 {
378 if (item)
379 {
380 GList *child = m_list->children;
381 int count = 0;
382 while (child)
383 {
384 if (GTK_WIDGET(child->data) == item) return count;
385 count++;
386 child = child->next;
387 }
388 }
389 return -1;
390 }
391
392 void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
393 {
394 GList *child = m_list->children;
395 while (child)
396 {
397 DisconnectDnDWidget( GTK_WIDGET( child->data ) );
398 child = child->next;
399 }
400
401 wxWindow::SetDropTarget( dropTarget );
402
403 child = m_list->children;
404 while (child)
405 {
406 ConnectDnDWidget( GTK_WIDGET( child->data ) );
407 child = child->next;
408 }
409 }
410
411 GtkWidget *wxListBox::GetConnectWidget(void)
412 {
413 return GTK_WIDGET(m_list);
414 }
415
416 void wxListBox::SetFont( const wxFont &font )
417 {
418 wxWindow::SetFont( font );
419
420 GList *child = m_list->children;
421 while (child)
422 {
423 GtkBin *bin = (GtkBin*) child->data;
424 gtk_widget_set_style( bin->child,
425 gtk_style_ref(
426 gtk_widget_get_style( m_widget ) ) );
427 child = child->next;
428 }
429 }
430
431