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