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