Fixes, typos etc...
[wxWidgets.git] / src / gtk / listbox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: listbox.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "listbox.h"
13 #endif
14
15 #include "wx/dynarray.h"
16 #include "wx/listbox.h"
17 #include "wx/utils.h"
18 #include <wx/intl.h>
19
20 //-----------------------------------------------------------------------------
21 // data
22 //-----------------------------------------------------------------------------
23
24 extern bool g_blockEventsOnDrag;
25
26 //-----------------------------------------------------------------------------
27 // "select" and "deselect"
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 // wxListBox
61 //-----------------------------------------------------------------------------
62
63 IMPLEMENT_DYNAMIC_CLASS(wxListBox,wxControl)
64
65 wxListBox::wxListBox(void)
66 {
67 m_list = (GtkList *) NULL;
68 }
69
70 bool wxListBox::Create( wxWindow *parent, wxWindowID id,
71 const wxPoint &pos, const wxSize &size,
72 int n, const wxString choices[],
73 long style, const wxValidator& validator, const wxString &name )
74 {
75 m_needParent = TRUE;
76
77 PreCreation( parent, id, pos, size, style, name );
78
79 SetValidator( validator );
80
81 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
82 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
83 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
84
85 m_list = GTK_LIST( gtk_list_new() );
86
87 GtkSelectionMode mode = GTK_SELECTION_BROWSE;
88 if (style & wxLB_MULTIPLE)
89 mode = GTK_SELECTION_MULTIPLE;
90 else if (style & wxLB_EXTENDED)
91 mode = GTK_SELECTION_EXTENDED;
92
93 gtk_list_set_selection_mode( GTK_LIST(m_list), mode );
94
95 gtk_container_add (GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
96 gtk_widget_show( GTK_WIDGET(m_list) );
97
98 wxSize newSize = size;
99 if (newSize.x == -1) newSize.x = 100;
100 if (newSize.y == -1) newSize.y = 110;
101 SetSize( newSize.x, newSize.y );
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 ConnectWidget( list_item );
118
119 m_clientData.Append( (wxObject*)NULL );
120
121 gtk_widget_show( list_item );
122 }
123
124 PostCreation();
125
126 gtk_widget_realize( GTK_WIDGET(m_list) );
127
128 SetBackgroundColour( parent->GetBackgroundColour() );
129
130 Show( TRUE );
131
132 return TRUE;
133 }
134
135 void wxListBox::Append( const wxString &item )
136 {
137 Append( item, (char*)NULL );
138 }
139
140 void wxListBox::Append( const wxString &item, char *clientData )
141 {
142 wxCHECK_RET( m_list != NULL, "invalid listbox" );
143
144 GtkWidget *list_item = gtk_list_item_new_with_label( item );
145
146 if (m_widgetStyle)
147 {
148 gtk_widget_set_style( list_item, m_widgetStyle );
149 gtk_widget_set_style( GTK_BIN( list_item )->child, m_widgetStyle );
150 }
151
152 gtk_signal_connect( GTK_OBJECT(list_item), "select",
153 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
154
155 if (GetWindowStyleFlag() & wxLB_MULTIPLE)
156 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
157 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
158
159 ConnectWidget( list_item );
160
161 m_clientData.Append( (wxObject*)clientData );
162
163 gtk_container_add( GTK_CONTAINER(m_list), list_item );
164
165 gtk_widget_show( list_item );
166
167 ConnectWidget( list_item );
168
169 ConnectDnDWidget( list_item );
170 }
171
172 void wxListBox::Clear(void)
173 {
174 wxCHECK_RET( m_list != NULL, "invalid listbox" );
175
176 gtk_list_clear_items( m_list, 0, Number() );
177
178 m_clientData.Clear();
179 }
180
181 void wxListBox::Delete( int n )
182 {
183 wxCHECK_RET( m_list != NULL, "invalid listbox" );
184
185 GList *child = g_list_nth( m_list->children, n );
186
187 if (!child)
188 {
189 wxFAIL_MSG("wrong listbox index");
190 return;
191 }
192
193 GList *list = g_list_append( NULL, child->data );
194 gtk_list_remove_items( m_list, list );
195 g_list_free( list );
196
197 wxNode *node = m_clientData.Nth( n );
198 if (!node)
199 {
200 wxFAIL_MSG("wrong listbox index");
201 }
202 else
203 m_clientData.DeleteNode( node );
204 }
205
206 void wxListBox::Deselect( int n )
207 {
208 wxCHECK_RET( m_list != NULL, "invalid listbox" );
209
210 gtk_list_unselect_item( m_list, n );
211 }
212
213 int wxListBox::FindString( const wxString &item ) const
214 {
215 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
216
217 GList *child = m_list->children;
218 int count = 0;
219 while (child)
220 {
221 GtkBin *bin = GTK_BIN( child->data );
222 GtkLabel *label = GTK_LABEL( bin->child );
223 if (item == label->label) return count;
224 count++;
225 child = child->next;
226 }
227
228 // it's not an error if the string is not found - this function may be used to
229 // test for existence of the string in the listbox, so don't give any
230 // errors/assert failures.
231
232 return -1;
233 }
234
235 char *wxListBox::GetClientData( int n ) const
236 {
237 wxCHECK_MSG( m_list != NULL, (char*) NULL, "invalid listbox" );
238
239 wxNode *node = m_clientData.Nth( n );
240 if (node) return ((char*)node->Data());
241
242 wxFAIL_MSG("wrong listbox index");
243 return (char *) NULL;
244 }
245
246 int wxListBox::GetSelection(void) const
247 {
248 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
249
250 GList *child = m_list->children;
251 int count = 0;
252 while (child)
253 {
254 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
255 count++;
256 child = child->next;
257 }
258 return -1;
259 }
260
261 int wxListBox::GetSelections(wxArrayInt& aSelections) const
262 {
263 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
264
265 // get the number of selected items first
266 GList *child = m_list->children;
267 int count = 0;
268 for ( child = m_list->children; child != NULL; child = child->next )
269 {
270 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
271 count++;
272 }
273
274 aSelections.Empty();
275
276 if ( count > 0 ) {
277 // now fill the list
278 aSelections.Alloc(count); // optimization attempt
279 int i = 0;
280 for ( child = m_list->children; child != NULL; child = child->next, i++ )
281 {
282 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
283 aSelections.Add(i);
284 }
285 }
286
287 return count;
288 }
289
290 wxString wxListBox::GetString( int n ) const
291 {
292 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
293
294 GList *child = g_list_nth( m_list->children, n );
295 if (child)
296 {
297 GtkBin *bin = GTK_BIN( child->data );
298 GtkLabel *label = GTK_LABEL( bin->child );
299 return label->label;
300 }
301 wxFAIL_MSG("wrong listbox index");
302 return "";
303 }
304
305 wxString wxListBox::GetStringSelection(void) const
306 {
307 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
308
309 GList *selection = m_list->selection;
310 if (selection)
311 {
312 GtkBin *bin = GTK_BIN( selection->data );
313 wxString tmp = GTK_LABEL( bin->child )->label;
314 return tmp;
315 }
316 wxFAIL_MSG("no listbox selection available");
317 return "";
318 }
319
320 int wxListBox::Number(void)
321 {
322 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
323
324 GList *child = m_list->children;
325 int count = 0;
326 while (child) { count++; child = child->next; }
327 return count;
328 }
329
330 bool wxListBox::Selected( int n )
331 {
332 wxCHECK_MSG( m_list != NULL, FALSE, "invalid listbox" );
333
334 GList *target = g_list_nth( m_list->children, n );
335 if (target)
336 {
337 GList *child = m_list->selection;
338 while (child)
339 {
340 if (child->data == target->data) return TRUE;
341 child = child->next;
342 }
343 }
344 wxFAIL_MSG("wrong listbox index");
345 return FALSE;
346 }
347
348 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
349 {
350 wxFAIL_MSG("wxListBox::Set not implemented");
351 }
352
353 void wxListBox::SetClientData( int n, char *clientData )
354 {
355 wxCHECK_RET( m_list != NULL, "invalid listbox" );
356
357 wxNode *node = m_clientData.Nth( n );
358 if (node)
359 {
360 node->SetData( (wxObject*)clientData );
361 }
362 else
363 {
364 wxFAIL_MSG("wrong listbox index");
365 }
366 }
367
368 void wxListBox::SetFirstItem( int WXUNUSED(n) )
369 {
370 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
371 }
372
373 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
374 {
375 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
376 }
377
378 void wxListBox::SetSelection( int n, bool select )
379 {
380 wxCHECK_RET( m_list != NULL, "invalid listbox" );
381
382 if (select)
383 gtk_list_select_item( m_list, n );
384 else
385 gtk_list_unselect_item( m_list, n );
386 }
387
388 void wxListBox::SetString( int n, const wxString &string )
389 {
390 wxCHECK_RET( m_list != NULL, "invalid listbox" );
391
392 GList *child = g_list_nth( m_list->children, n );
393 if (child)
394 {
395 GtkBin *bin = GTK_BIN( child->data );
396 GtkLabel *label = GTK_LABEL( bin->child );
397 gtk_label_set( label, string );
398 }
399 else
400 {
401 wxFAIL_MSG("wrong listbox index");
402 }
403 }
404
405 void wxListBox::SetStringSelection( const wxString &string, bool select )
406 {
407 wxCHECK_RET( m_list != NULL, "invalid listbox" );
408
409 SetSelection( FindString(string), select );
410 }
411
412 int wxListBox::GetIndex( GtkWidget *item ) const
413 {
414 if (item)
415 {
416 GList *child = m_list->children;
417 int count = 0;
418 while (child)
419 {
420 if (GTK_WIDGET(child->data) == item) return count;
421 count++;
422 child = child->next;
423 }
424 }
425 return -1;
426 }
427
428 void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
429 {
430 wxCHECK_RET( m_list != NULL, "invalid listbox" );
431
432 GList *child = m_list->children;
433 while (child)
434 {
435 DisconnectDnDWidget( GTK_WIDGET( child->data ) );
436 child = child->next;
437 }
438
439 wxWindow::SetDropTarget( dropTarget );
440
441 child = m_list->children;
442 while (child)
443 {
444 ConnectDnDWidget( GTK_WIDGET( child->data ) );
445 child = child->next;
446 }
447 }
448
449 GtkWidget *wxListBox::GetConnectWidget(void)
450 {
451 return GTK_WIDGET(m_list);
452 }
453
454 bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
455 {
456 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
457
458 GList *child = m_list->children;
459 while (child)
460 {
461 GtkWidget *bin = GTK_WIDGET( child->data );
462 if (bin->window == window) return TRUE;
463 child = child->next;
464 }
465
466 return FALSE;
467 }
468
469 void wxListBox::SetFont( const wxFont &font )
470 {
471 wxCHECK_RET( m_list != NULL, "invalid listbox" );
472
473 wxControl::SetFont( font );
474
475 GList *child = m_list->children;
476 while (child)
477 {
478 gtk_widget_set_style( GTK_BIN(child->data)->child, m_widgetStyle );
479 child = child->next;
480 }
481 }
482
483 void wxListBox::SetBackgroundColour( const wxColour &colour )
484 {
485 wxCHECK_RET( m_list != NULL, "invalid listbox" );
486
487 wxControl::SetBackgroundColour( colour );
488
489 if (!m_backgroundColour.Ok()) return;
490
491 GdkWindow *window = GTK_WIDGET(m_list)->window;
492 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
493 gdk_window_set_background( window, m_backgroundColour.GetColor() );
494 gdk_window_clear( window );
495
496 GList *child = m_list->children;
497 while (child)
498 {
499 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
500 child = child->next;
501 }
502 }
503