Added background colour again
[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 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 SetBackgroundColour( parent->GetBackgroundColour() );
127
128 Show( TRUE );
129
130 return TRUE;
131 }
132
133 void wxListBox::Append( const wxString &item )
134 {
135 Append( item, (char*)NULL );
136 }
137
138 void wxListBox::Append( const wxString &item, char *clientData )
139 {
140 wxCHECK_RET( m_list != NULL, "invalid listbox" );
141
142 GtkWidget *list_item = gtk_list_item_new_with_label( item );
143
144 if (m_widgetStyle)
145 {
146 gtk_widget_set_style( list_item, m_widgetStyle );
147 gtk_widget_set_style( GTK_BIN( list_item )->child, m_widgetStyle );
148 }
149
150 gtk_signal_connect( GTK_OBJECT(list_item), "select",
151 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
152
153 if (GetWindowStyleFlag() & wxLB_MULTIPLE)
154 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
155 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
156
157 m_clientData.Append( (wxObject*)clientData );
158
159 gtk_container_add( GTK_CONTAINER(m_list), list_item );
160
161 gtk_widget_show( list_item );
162
163 ConnectWidget( list_item );
164
165 ConnectDnDWidget( list_item );
166 }
167
168 void wxListBox::Clear(void)
169 {
170 wxCHECK_RET( m_list != NULL, "invalid listbox" );
171
172 gtk_list_clear_items( m_list, 0, Number() );
173
174 m_clientData.Clear();
175 }
176
177 void wxListBox::Delete( int n )
178 {
179 wxCHECK_RET( m_list != NULL, "invalid listbox" );
180
181 GList *child = g_list_nth( m_list->children, n );
182
183 if (!child)
184 {
185 wxFAIL_MSG("wrong listbox index");
186 return;
187 }
188
189 GList *list = g_list_append( NULL, child->data );
190 gtk_list_remove_items( m_list, list );
191 g_list_free( list );
192
193 wxNode *node = m_clientData.Nth( n );
194 if (!node)
195 {
196 wxFAIL_MSG("wrong listbox index");
197 }
198 else
199 m_clientData.DeleteNode( node );
200 }
201
202 void wxListBox::Deselect( int n )
203 {
204 wxCHECK_RET( m_list != NULL, "invalid listbox" );
205
206 gtk_list_unselect_item( m_list, n );
207 }
208
209 int wxListBox::FindString( const wxString &item ) const
210 {
211 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
212
213 GList *child = m_list->children;
214 int count = 0;
215 while (child)
216 {
217 GtkBin *bin = GTK_BIN( child->data );
218 GtkLabel *label = GTK_LABEL( bin->child );
219 if (item == label->label) return count;
220 count++;
221 child = child->next;
222 }
223
224 // it's not an error if the string is not found - this function may be used to
225 // test for existence of the string in the listbox, so don't give any
226 // errors/assert failures.
227
228 return -1;
229 }
230
231 char *wxListBox::GetClientData( int n ) const
232 {
233 wxCHECK_MSG( m_list != NULL, (char*) NULL, "invalid listbox" );
234
235 wxNode *node = m_clientData.Nth( n );
236 if (node) return ((char*)node->Data());
237
238 wxFAIL_MSG("wrong listbox index");
239 return (char *) NULL;
240 }
241
242 int wxListBox::GetSelection(void) const
243 {
244 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
245
246 GList *child = m_list->children;
247 int count = 0;
248 while (child)
249 {
250 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
251 count++;
252 child = child->next;
253 }
254 return -1;
255 }
256
257 int wxListBox::GetSelections(wxArrayInt& aSelections) const
258 {
259 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
260
261 // get the number of selected items first
262 GList *child = m_list->children;
263 int count = 0;
264 for ( child = m_list->children; child != NULL; child = child->next )
265 {
266 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
267 count++;
268 }
269
270 aSelections.Empty();
271
272 if ( count > 0 ) {
273 // now fill the list
274 aSelections.Alloc(count); // optimization attempt
275 int i = 0;
276 for ( child = m_list->children; child != NULL; child = child->next, i++ )
277 {
278 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
279 aSelections.Add(i);
280 }
281 }
282
283 return count;
284 }
285
286 wxString wxListBox::GetString( int n ) const
287 {
288 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
289
290 GList *child = g_list_nth( m_list->children, n );
291 if (child)
292 {
293 GtkBin *bin = GTK_BIN( child->data );
294 GtkLabel *label = GTK_LABEL( bin->child );
295 return label->label;
296 }
297 wxFAIL_MSG("wrong listbox index");
298 return "";
299 }
300
301 wxString wxListBox::GetStringSelection(void) const
302 {
303 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
304
305 GList *selection = m_list->selection;
306 if (selection)
307 {
308 GtkBin *bin = GTK_BIN( selection->data );
309 wxString tmp = GTK_LABEL( bin->child )->label;
310 return tmp;
311 }
312 wxFAIL_MSG("no listbox selection available");
313 return "";
314 }
315
316 int wxListBox::Number(void)
317 {
318 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
319
320 GList *child = m_list->children;
321 int count = 0;
322 while (child) { count++; child = child->next; }
323 return count;
324 }
325
326 bool wxListBox::Selected( int n )
327 {
328 wxCHECK_MSG( m_list != NULL, FALSE, "invalid listbox" );
329
330 GList *target = g_list_nth( m_list->children, n );
331 if (target)
332 {
333 GList *child = m_list->selection;
334 while (child)
335 {
336 if (child->data == target->data) return TRUE;
337 child = child->next;
338 }
339 }
340 wxFAIL_MSG("wrong listbox index");
341 return FALSE;
342 }
343
344 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
345 {
346 wxFAIL_MSG("wxListBox::Set not implemented");
347 }
348
349 void wxListBox::SetClientData( int n, char *clientData )
350 {
351 wxCHECK_RET( m_list != NULL, "invalid listbox" );
352
353 wxNode *node = m_clientData.Nth( n );
354 if (node)
355 {
356 node->SetData( (wxObject*)clientData );
357 }
358 else
359 {
360 wxFAIL_MSG("wrong listbox index");
361 }
362 }
363
364 void wxListBox::SetFirstItem( int WXUNUSED(n) )
365 {
366 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
367 }
368
369 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
370 {
371 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
372 }
373
374 void wxListBox::SetSelection( int n, bool select )
375 {
376 wxCHECK_RET( m_list != NULL, "invalid listbox" );
377
378 if (select)
379 gtk_list_select_item( m_list, n );
380 else
381 gtk_list_unselect_item( m_list, n );
382 }
383
384 void wxListBox::SetString( int n, const wxString &string )
385 {
386 wxCHECK_RET( m_list != NULL, "invalid listbox" );
387
388 GList *child = g_list_nth( m_list->children, n );
389 if (child)
390 {
391 GtkBin *bin = GTK_BIN( child->data );
392 GtkLabel *label = GTK_LABEL( bin->child );
393 gtk_label_set( label, string );
394 }
395 else
396 {
397 wxFAIL_MSG("wrong listbox index");
398 }
399 }
400
401 void wxListBox::SetStringSelection( const wxString &string, bool select )
402 {
403 wxCHECK_RET( m_list != NULL, "invalid listbox" );
404
405 SetSelection( FindString(string), select );
406 }
407
408 int wxListBox::GetIndex( GtkWidget *item ) const
409 {
410 if (item)
411 {
412 GList *child = m_list->children;
413 int count = 0;
414 while (child)
415 {
416 if (GTK_WIDGET(child->data) == item) return count;
417 count++;
418 child = child->next;
419 }
420 }
421 return -1;
422 }
423
424 void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
425 {
426 wxCHECK_RET( m_list != NULL, "invalid listbox" );
427
428 GList *child = m_list->children;
429 while (child)
430 {
431 DisconnectDnDWidget( GTK_WIDGET( child->data ) );
432 child = child->next;
433 }
434
435 wxWindow::SetDropTarget( dropTarget );
436
437 child = m_list->children;
438 while (child)
439 {
440 ConnectDnDWidget( GTK_WIDGET( child->data ) );
441 child = child->next;
442 }
443 }
444
445 GtkWidget *wxListBox::GetConnectWidget(void)
446 {
447 return GTK_WIDGET(m_list);
448 }
449
450 bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
451 {
452 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
453
454 GList *child = m_list->children;
455 while (child)
456 {
457 GtkBin *bin = GTK_BIN( child->data );
458 if (bin->child->window == window) return TRUE;
459 child = child->next;
460 }
461
462 return FALSE;
463 }
464
465 void wxListBox::SetFont( const wxFont &font )
466 {
467 wxCHECK_RET( m_list != NULL, "invalid listbox" );
468
469 wxControl::SetFont( font );
470
471 GList *child = m_list->children;
472 while (child)
473 {
474 gtk_widget_set_style( GTK_BIN(child->data)->child, m_widgetStyle );
475
476 child = child->next;
477 }
478 }
479
480 void wxListBox::SetBackgroundColour( const wxColour &colour )
481 {
482 wxCHECK_RET( m_list != NULL, "invalid listbox" );
483
484 wxControl::SetBackgroundColour( colour );
485
486 if (!m_backgroundColour.Ok()) return;
487
488 // gtk_widget_set_style( GTK_WIDGET(m_list), m_widgetStyle );
489
490 GdkWindow *window = GTK_WIDGET(m_list)->window;
491 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
492 gdk_window_set_background( window, m_backgroundColour.GetColor() );
493 gdk_window_clear( window );
494
495 GList *child = m_list->children;
496 while (child)
497 {
498 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
499 // gtk_widget_set_style( GTK_BIN(child->data)->child, m_widgetStyle );
500
501 child = child->next;
502 }
503 }
504