]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/listbox.cpp
Had missed one LPSTR.
[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/listbox.h"
16
17 #if wxUSE_LISTBOX
18
19 #include "wx/dynarray.h"
20 #include "wx/utils.h"
21 #include "wx/intl.h"
22 #include "wx/checklst.h"
23 #include "wx/settings.h"
24
25 #if wxUSE_TOOLTIPS
26 #include "wx/tooltip.h"
27 #endif
28
29 #if wxUSE_DRAG_AND_DROP
30 #include "wx/dnd.h"
31 #endif
32
33 #include "gdk/gdk.h"
34 #include "gtk/gtk.h"
35
36 //-----------------------------------------------------------------------------
37 // idle system
38 //-----------------------------------------------------------------------------
39
40 extern void wxapp_install_idle_handler();
41 extern bool g_isIdle;
42
43 //-------------------------------------------------------------------------
44 // conditional compilation
45 //-------------------------------------------------------------------------
46
47 #if (GTK_MINOR_VERSION > 0)
48 #define NEW_GTK_SCROLL_CODE
49 #endif
50
51 //-----------------------------------------------------------------------------
52 // private functions
53 //-----------------------------------------------------------------------------
54
55 #if wxUSE_CHECKLISTBOX
56
57 #define CHECKBOX_STRING "[-] "
58
59 // checklistboxes have "[±] " prepended to their lables, this macro removes it
60 // (NB: 4 below is the length of CHECKBOX_STRING above)
61 //
62 // the argument to it is a "const char *" pointer
63 #define GET_REAL_LABEL(label) ((m_hasCheckBoxes)?(label)+4 : (label))
64
65 #else // !wxUSE_CHECKLISTBOX
66
67 #define GET_REAL_LABEL(label) (label)
68
69 #endif // wxUSE_CHECKLISTBOX
70
71 //-----------------------------------------------------------------------------
72 // data
73 //-----------------------------------------------------------------------------
74
75 extern bool g_blockEventsOnDrag;
76 extern bool g_blockEventsOnScroll;
77
78 static bool g_hasDoubleClicked = FALSE;
79
80 //-----------------------------------------------------------------------------
81 // "button_release_event"
82 //-----------------------------------------------------------------------------
83
84 /* we would normally emit a wxEVT_COMMAND_LISTBOX_DOUBLECLICKED event once
85 a GDK_2BUTTON_PRESS occurs, but this has the particular problem of the
86 listbox keeping the focus until it receives a GDK_BUTTON_RELEASE event.
87 this can lead to race conditions so that we emit the dclick event
88 after the GDK_BUTTON_RELEASE event after the GDK_2BUTTON_PRESS event */
89
90 static gint
91 gtk_listbox_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxListBox *listbox )
92 {
93 if (g_isIdle) wxapp_install_idle_handler();
94
95 if (g_blockEventsOnDrag) return FALSE;
96 if (g_blockEventsOnScroll) return FALSE;
97
98 if (!listbox->m_hasVMT) return FALSE;
99
100 if (!g_hasDoubleClicked) return FALSE;
101
102 wxCommandEvent event( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, listbox->GetId() );
103 event.SetEventObject( listbox );
104
105 wxArrayInt aSelections;
106 int count = listbox->GetSelections(aSelections);
107 if ( count > 0 )
108 {
109 event.m_commandInt = aSelections[0] ;
110 event.m_clientData = listbox->GetClientData( event.m_commandInt );
111 wxString str(listbox->GetString(event.m_commandInt));
112 if (!str.IsEmpty()) event.m_commandString = str;
113 }
114 else
115 {
116 event.m_commandInt = -1 ;
117 event.m_commandString.Empty();
118 }
119
120 listbox->GetEventHandler()->ProcessEvent( event );
121
122 return FALSE;
123 }
124
125 //-----------------------------------------------------------------------------
126 // "button_press_event"
127 //-----------------------------------------------------------------------------
128
129 static gint
130 gtk_listbox_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxListBox *listbox )
131 {
132 if (g_isIdle) wxapp_install_idle_handler();
133
134 if (g_blockEventsOnDrag) return FALSE;
135 if (g_blockEventsOnScroll) return FALSE;
136
137 if (!listbox->m_hasVMT) return FALSE;
138
139 int sel = listbox->GetIndex( widget );
140
141 #if wxUSE_CHECKLISTBOX
142 if ((listbox->m_hasCheckBoxes) && (gdk_event->x < 15) && (gdk_event->type != GDK_2BUTTON_PRESS))
143 {
144 wxCheckListBox *clb = (wxCheckListBox *)listbox;
145
146 clb->Check( sel, !clb->IsChecked(sel) );
147
148 wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, listbox->GetId() );
149 event.SetEventObject( listbox );
150 event.SetInt( sel );
151 listbox->GetEventHandler()->ProcessEvent( event );
152 }
153 #endif // wxUSE_CHECKLISTBOX
154
155 /* emit wxEVT_COMMAND_LISTBOX_DOUBLECLICKED later */
156 g_hasDoubleClicked = (gdk_event->type == GDK_2BUTTON_PRESS);
157
158 return FALSE;
159 }
160
161 //-----------------------------------------------------------------------------
162 // "key_press_event"
163 //-----------------------------------------------------------------------------
164
165 #if wxUSE_CHECKLISTBOX
166 static gint
167 gtk_listbox_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxListBox *listbox )
168 {
169 if (g_isIdle) wxapp_install_idle_handler();
170
171 if (g_blockEventsOnDrag) return FALSE;
172
173 if (!listbox->m_hasVMT) return FALSE;
174
175 if (gdk_event->keyval != ' ') return FALSE;
176
177 int sel = listbox->GetIndex( widget );
178
179 wxCheckListBox *clb = (wxCheckListBox *)listbox;
180
181 clb->Check( sel, !clb->IsChecked(sel) );
182
183 wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, listbox->GetId() );
184 event.SetEventObject( listbox );
185 event.SetInt( sel );
186 listbox->GetEventHandler()->ProcessEvent( event );
187
188 return FALSE;
189 }
190 #endif // wxUSE_CHECKLISTBOX
191
192 //-----------------------------------------------------------------------------
193 // "select" and "deselect"
194 //-----------------------------------------------------------------------------
195
196 static void gtk_listitem_select_callback( GtkWidget *WXUNUSED(widget), wxListBox *listbox )
197 {
198 if (g_isIdle) wxapp_install_idle_handler();
199
200 if (!listbox->m_hasVMT) return;
201 if (g_blockEventsOnDrag) return;
202
203 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, listbox->GetId() );
204
205 wxArrayInt aSelections;
206 int count = listbox->GetSelections(aSelections);
207 if ( count > 0 )
208 {
209 event.m_commandInt = aSelections[0] ;
210 event.m_clientData = listbox->GetClientData( event.m_commandInt );
211 wxString str(listbox->GetString(event.m_commandInt));
212 if (!str.IsEmpty()) event.m_commandString = str;
213 }
214 else
215 {
216 event.m_commandInt = -1 ;
217 event.m_commandString.Empty();
218 }
219
220 event.SetEventObject( listbox );
221
222 listbox->GetEventHandler()->ProcessEvent( event );
223 }
224
225 //-----------------------------------------------------------------------------
226 // wxListBox
227 //-----------------------------------------------------------------------------
228
229 IMPLEMENT_DYNAMIC_CLASS(wxListBox,wxControl)
230
231 wxListBox::wxListBox()
232 {
233 m_list = (GtkList *) NULL;
234 #if wxUSE_CHECKLISTBOX
235 m_hasCheckBoxes = FALSE;
236 #endif // wxUSE_CHECKLISTBOX
237 }
238
239 bool wxListBox::Create( wxWindow *parent, wxWindowID id,
240 const wxPoint &pos, const wxSize &size,
241 int n, const wxString choices[],
242 long style, const wxValidator& validator, const wxString &name )
243 {
244 m_needParent = TRUE;
245 m_acceptsFocus = TRUE;
246
247 PreCreation( parent, id, pos, size, style, name );
248
249 #if wxUSE_VALIDATORS
250 SetValidator( validator );
251 #endif
252
253 m_widget = gtk_scrolled_window_new( (GtkAdjustment*) NULL, (GtkAdjustment*) NULL );
254 if (style & wxLB_ALWAYS_SB)
255 {
256 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
257 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
258 }
259 else
260 {
261 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
262 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
263 }
264
265 m_list = GTK_LIST( gtk_list_new() );
266
267 GtkSelectionMode mode = GTK_SELECTION_BROWSE;
268 if (style & wxLB_MULTIPLE)
269 mode = GTK_SELECTION_MULTIPLE;
270 else if (style & wxLB_EXTENDED)
271 mode = GTK_SELECTION_EXTENDED;
272
273 gtk_list_set_selection_mode( GTK_LIST(m_list), mode );
274
275 #ifdef NEW_GTK_SCROLL_CODE
276 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), GTK_WIDGET(m_list) );
277 #else
278 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
279 #endif
280
281 gtk_widget_show( GTK_WIDGET(m_list) );
282
283 wxSize newSize = size;
284 if (newSize.x == -1) newSize.x = 100;
285 if (newSize.y == -1) newSize.y = 110;
286 SetSize( newSize.x, newSize.y );
287
288 for (int i = 0; i < n; i++)
289 {
290 m_clientDataList.Append( (wxObject*) NULL );
291 m_clientObjectList.Append( (wxObject*) NULL );
292
293 GtkWidget *list_item;
294
295 wxString str(choices[i]);
296 #if wxUSE_CHECKLISTBOX
297 if (m_hasCheckBoxes)
298 {
299 str.Prepend(CHECKBOX_STRING);
300 }
301 #endif // wxUSE_CHECKLISTBOX
302
303 list_item = gtk_list_item_new_with_label( str.mbc_str() );
304
305 gtk_container_add( GTK_CONTAINER(m_list), list_item );
306
307 gtk_signal_connect( GTK_OBJECT(list_item), "select",
308 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
309
310 if (style & wxLB_MULTIPLE)
311 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
312 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
313
314 gtk_signal_connect( GTK_OBJECT(list_item),
315 "button_press_event",
316 (GtkSignalFunc)gtk_listbox_button_press_callback,
317 (gpointer) this );
318
319 gtk_signal_connect_after( GTK_OBJECT(list_item),
320 "button_release_event",
321 (GtkSignalFunc)gtk_listbox_button_release_callback,
322 (gpointer) this );
323
324 #if wxUSE_CHECKLISTBOX
325 if (m_hasCheckBoxes)
326 {
327 gtk_signal_connect( GTK_OBJECT(list_item),
328 "key_press_event",
329 (GtkSignalFunc)gtk_listbox_key_press_callback,
330 (gpointer)this );
331 }
332 #endif // wxUSE_CHECKLISTBOX
333
334 ConnectWidget( list_item );
335
336 gtk_widget_show( list_item );
337 }
338
339 m_parent->DoAddChild( this );
340
341 PostCreation();
342
343 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOW ) );
344 SetForegroundColour( parent->GetForegroundColour() );
345 SetFont( parent->GetFont() );
346
347 Show( TRUE );
348
349 return TRUE;
350 }
351
352 wxListBox::~wxListBox()
353 {
354 Clear();
355 }
356
357 void wxListBox::InsertItems(int nItems, const wxString items[], int pos)
358 {
359 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
360
361 GList *children = m_list->children;
362 int length = g_list_length(children);
363 wxCHECK_RET( pos <= length, _T("invalid index in wxListBox::InsertItems") );
364
365 // VZ: it seems that GTK 1.0.6 doesn't has a function to insert an item
366 // into a listbox at the given position, this is why we first delete
367 // all items after this position, then append these items and then
368 // reappend back the old ones.
369
370 // first detach the old items
371 int n; // loop var
372
373 if ( pos == length )
374 {
375 // no need to do anything complicated
376 for ( n = 0; n < nItems; n++ )
377 {
378 Append(items[n]);
379 }
380
381 return;
382 }
383
384 wxArrayString deletedLabels;
385 wxArrayPtrVoid deletedData;
386 wxArrayInt deletedChecks; // only for check list boxes
387
388 GList *child = g_list_nth( children, pos );
389 for ( n = 0; child != NULL; n++, child = child->next )
390 {
391 // save label
392 GtkBin *bin = GTK_BIN( child->data );
393 GtkLabel *label = GTK_LABEL( bin->child );
394
395 wxString str(GET_REAL_LABEL(label->label),*wxConvCurrent);
396 deletedLabels.Add(str);
397
398 // save data
399 void *clientData = NULL;
400 wxNode *node = NULL;
401
402 if ( n < (int)m_clientObjectList.GetCount() )
403 node = m_clientObjectList.Nth( n );
404
405 if ( node )
406 {
407 clientData = node->GetData();
408 m_clientObjectList.DeleteNode( node );
409 }
410
411 if ( !clientData )
412 {
413 if ( n < (int)m_clientDataList.GetCount() )
414 node = m_clientDataList.Nth( n );
415
416 if ( node )
417 {
418 clientData = node->GetData();
419 node = m_clientDataList.Nth( n );
420 }
421 }
422
423 deletedData.Add(clientData);
424
425 #if wxUSE_CHECKLISTBOX
426 // save check state
427 if ( m_hasCheckBoxes )
428 {
429 deletedChecks.Add(((wxCheckListBox *)this)->IsChecked(pos + n));
430 }
431 #endif // wxUSE_CHECKLISTBOX
432 }
433
434 int nDeletedCount = n;
435
436 gtk_list_clear_items( m_list, pos, length );
437
438 // now append the new items
439 for ( n = 0; n < nItems; n++ )
440 {
441 Append(items[n]);
442 }
443
444 // and append the old items too
445 pos += nItems; // now the indices are shifter
446 for ( n = 0; n < nDeletedCount; n++ )
447 {
448 Append(deletedLabels[n], deletedData[n]);
449
450 #if wxUSE_CHECKLISTBOX
451 if ( m_hasCheckBoxes )
452 {
453 ((wxCheckListBox *)this)->Check(pos + n, (bool)deletedChecks[n]);
454 }
455 #endif // wxUSE_CHECKLISTBOX
456 }
457 }
458
459 void wxListBox::AppendCommon( const wxString &item )
460 {
461 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
462
463 GtkWidget *list_item;
464
465 wxString label(item);
466 #if wxUSE_CHECKLISTBOX
467 if (m_hasCheckBoxes)
468 {
469 label.Prepend(CHECKBOX_STRING);
470 }
471 #endif // wxUSE_CHECKLISTBOX
472
473 list_item = gtk_list_item_new_with_label( label.mbc_str() );
474
475 gtk_container_add( GTK_CONTAINER(m_list), list_item );
476
477 gtk_signal_connect( GTK_OBJECT(list_item), "select",
478 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
479
480 if (HasFlag(wxLB_MULTIPLE))
481 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
482 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
483
484 gtk_signal_connect( GTK_OBJECT(list_item),
485 "button_press_event",
486 (GtkSignalFunc)gtk_listbox_button_press_callback,
487 (gpointer) this );
488
489 gtk_signal_connect_after( GTK_OBJECT(list_item),
490 "button_release_event",
491 (GtkSignalFunc)gtk_listbox_button_release_callback,
492 (gpointer) this );
493
494 #if wxUSE_CHECKLISTBOX
495 if (m_hasCheckBoxes)
496 {
497 gtk_signal_connect( GTK_OBJECT(list_item),
498 "key_press_event",
499 (GtkSignalFunc)gtk_listbox_key_press_callback,
500 (gpointer)this );
501 }
502 #endif // wxUSE_CHECKLISTBOX
503
504 gtk_widget_show( list_item );
505
506 ConnectWidget( list_item );
507
508 if (GTK_WIDGET_REALIZED(m_widget))
509 {
510 gtk_widget_realize( list_item );
511 gtk_widget_realize( GTK_BIN(list_item)->child );
512
513 if (m_widgetStyle) ApplyWidgetStyle();
514
515 #if wxUSE_DRAG_AND_DROP
516 #ifndef NEW_GTK_DND_CODE
517 if (m_dropTarget) m_dropTarget->RegisterWidget( list_item );
518 #endif
519 #endif
520
521 #if wxUSE_TOOLTIPS
522 if (m_tooltip) m_tooltip->Apply( this );
523 #endif
524 }
525 }
526
527 void wxListBox::Append( const wxString &item )
528 {
529 m_clientDataList.Append( (wxObject*) NULL );
530 m_clientObjectList.Append( (wxObject*) NULL );
531
532 AppendCommon( item );
533 }
534
535 void wxListBox::Append( const wxString &item, void *clientData )
536 {
537 m_clientDataList.Append( (wxObject*) clientData );
538 m_clientObjectList.Append( (wxObject*) NULL );
539
540 AppendCommon( item );
541 }
542
543 void wxListBox::Append( const wxString &item, wxClientData *clientData )
544 {
545 m_clientObjectList.Append( (wxObject*) clientData );
546 m_clientDataList.Append( (wxObject*) NULL );
547
548 AppendCommon( item );
549 }
550
551 void wxListBox::SetClientData( int n, void* clientData )
552 {
553 wxCHECK_RET( m_widget != NULL, _T("invalid combobox") );
554
555 wxNode *node = m_clientDataList.Nth( n );
556 if (!node) return;
557
558 node->SetData( (wxObject*) clientData );
559 }
560
561 void* wxListBox::GetClientData( int n )
562 {
563 wxCHECK_MSG( m_widget != NULL, NULL, _T("invalid combobox") );
564
565 wxNode *node = m_clientDataList.Nth( n );
566 if (!node) return NULL;
567
568 return node->Data();
569 }
570
571 void wxListBox::SetClientObject( int n, wxClientData* clientData )
572 {
573 wxCHECK_RET( m_widget != NULL, _T("invalid combobox") );
574
575 wxNode *node = m_clientObjectList.Nth( n );
576 if (!node) return;
577
578 wxClientData *cd = (wxClientData*) node->Data();
579 if (cd) delete cd;
580
581 node->SetData( (wxObject*) clientData );
582 }
583
584 wxClientData* wxListBox::GetClientObject( int n )
585 {
586 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, _T("invalid combobox") );
587
588 wxNode *node = m_clientObjectList.Nth( n );
589 if (!node) return (wxClientData*) NULL;
590
591 return (wxClientData*) node->Data();
592 }
593
594 void wxListBox::Clear()
595 {
596 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
597
598 gtk_list_clear_items( m_list, 0, Number() );
599
600 wxNode *node = m_clientObjectList.First();
601 while (node)
602 {
603 wxClientData *cd = (wxClientData*)node->Data();
604 if (cd) delete cd;
605 node = node->Next();
606 }
607 m_clientObjectList.Clear();
608
609 m_clientDataList.Clear();
610 }
611
612 void wxListBox::Delete( int n )
613 {
614 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
615
616 GList *child = g_list_nth( m_list->children, n );
617
618 wxCHECK_RET( child, _T("wrong listbox index") );
619
620 GList *list = g_list_append( (GList*) NULL, child->data );
621 gtk_list_remove_items( m_list, list );
622 g_list_free( list );
623
624 wxNode *node = m_clientObjectList.Nth( n );
625 if (node)
626 {
627 wxClientData *cd = (wxClientData*)node->Data();
628 if (cd) delete cd;
629 m_clientObjectList.DeleteNode( node );
630 }
631
632 node = m_clientDataList.Nth( n );
633 if (node)
634 {
635 m_clientDataList.DeleteNode( node );
636 }
637 }
638
639 void wxListBox::Deselect( int n )
640 {
641 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
642
643 gtk_list_unselect_item( m_list, n );
644 }
645
646 int wxListBox::FindString( const wxString &item ) const
647 {
648 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
649
650 GList *child = m_list->children;
651 int count = 0;
652 while (child)
653 {
654 GtkBin *bin = GTK_BIN( child->data );
655 GtkLabel *label = GTK_LABEL( bin->child );
656
657 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
658
659 if (str == item)
660 return count;
661
662 count++;
663 child = child->next;
664 }
665
666 // it's not an error if the string is not found -> no wxCHECK
667
668 return -1;
669 }
670
671 int wxListBox::GetSelection() const
672 {
673 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
674
675 GList *child = m_list->children;
676 int count = 0;
677 while (child)
678 {
679 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
680 count++;
681 child = child->next;
682 }
683 return -1;
684 }
685
686 int wxListBox::GetSelections( wxArrayInt& aSelections ) const
687 {
688 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
689
690 // get the number of selected items first
691 GList *child = m_list->children;
692 int count = 0;
693 for (child = m_list->children; child != NULL; child = child->next)
694 {
695 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
696 count++;
697 }
698
699 aSelections.Empty();
700
701 if (count > 0)
702 {
703 // now fill the list
704 aSelections.Alloc(count); // optimization attempt
705 int i = 0;
706 for (child = m_list->children; child != NULL; child = child->next, i++)
707 {
708 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
709 aSelections.Add(i);
710 }
711 }
712
713 return count;
714 }
715
716 wxString wxListBox::GetString( int n ) const
717 {
718 wxCHECK_MSG( m_list != NULL, _T(""), _T("invalid listbox") );
719
720 GList *child = g_list_nth( m_list->children, n );
721 if (child)
722 {
723 GtkBin *bin = GTK_BIN( child->data );
724 GtkLabel *label = GTK_LABEL( bin->child );
725
726 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
727
728 return str;
729 }
730
731 wxFAIL_MSG(_T("wrong listbox index"));
732
733 return _T("");
734 }
735
736 wxString wxListBox::GetStringSelection() const
737 {
738 wxCHECK_MSG( m_list != NULL, _T(""), _T("invalid listbox") );
739
740 GList *selection = m_list->selection;
741 if (selection)
742 {
743 GtkBin *bin = GTK_BIN( selection->data );
744 GtkLabel *label = GTK_LABEL( bin->child );
745
746 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
747
748 return str;
749 }
750
751 wxFAIL_MSG(_T("no listbox selection available"));
752 return _T("");
753 }
754
755 int wxListBox::Number()
756 {
757 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
758
759 GList *child = m_list->children;
760 int count = 0;
761 while (child) { count++; child = child->next; }
762 return count;
763 }
764
765 bool wxListBox::Selected( int n )
766 {
767 wxCHECK_MSG( m_list != NULL, FALSE, _T("invalid listbox") );
768
769 GList *target = g_list_nth( m_list->children, n );
770 if (target)
771 {
772 GList *child = m_list->selection;
773 while (child)
774 {
775 if (child->data == target->data) return TRUE;
776 child = child->next;
777 }
778 }
779 wxFAIL_MSG(_T("wrong listbox index"));
780 return FALSE;
781 }
782
783 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
784 {
785 wxFAIL_MSG(_T("wxListBox::Set not implemented"));
786 }
787
788 void wxListBox::SetFirstItem( int WXUNUSED(n) )
789 {
790 wxFAIL_MSG(_T("wxListBox::SetFirstItem not implemented"));
791 }
792
793 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
794 {
795 wxFAIL_MSG(_T("wxListBox::SetFirstItem not implemented"));
796 }
797
798 void wxListBox::SetSelection( int n, bool select )
799 {
800 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
801
802 if (select)
803 gtk_list_select_item( m_list, n );
804 else
805 gtk_list_unselect_item( m_list, n );
806 }
807
808 void wxListBox::SetString( int n, const wxString &string )
809 {
810 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
811
812 GList *child = g_list_nth( m_list->children, n );
813 if (child)
814 {
815 GtkBin *bin = GTK_BIN( child->data );
816 GtkLabel *label = GTK_LABEL( bin->child );
817
818 wxString str;
819 #if wxUSE_CHECKLISTBOX
820 if (m_hasCheckBoxes)
821 str += CHECKBOX_STRING;
822 #endif // wxUSE_CHECKLISTBOX
823 str += string;
824
825 gtk_label_set( label, str.mbc_str() );
826 }
827 else
828 {
829 wxFAIL_MSG(_T("wrong listbox index"));
830 }
831 }
832
833 void wxListBox::SetStringSelection( const wxString &string, bool select )
834 {
835 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
836
837 SetSelection( FindString(string), select );
838 }
839
840 int wxListBox::GetIndex( GtkWidget *item ) const
841 {
842 if (item)
843 {
844 GList *child = m_list->children;
845 int count = 0;
846 while (child)
847 {
848 if (GTK_WIDGET(child->data) == item) return count;
849 count++;
850 child = child->next;
851 }
852 }
853 return -1;
854 }
855
856 #if wxUSE_TOOLTIPS
857 void wxListBox::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
858 {
859 GList *child = m_list->children;
860 while (child)
861 {
862 gtk_tooltips_set_tip( tips, GTK_WIDGET( child->data ), wxConvLocal.cWX2MB(tip), (gchar*) NULL );
863 child = child->next;
864 }
865 }
866 #endif // wxUSE_TOOLTIPS
867
868 #if wxUSE_DRAG_AND_DROP
869 void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
870 {
871 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
872
873 #ifndef NEW_GTK_DND_CODE
874 if (m_dropTarget)
875 {
876 GList *child = m_list->children;
877 while (child)
878 {
879 m_dropTarget->UnregisterWidget( GTK_WIDGET( child->data ) );
880 child = child->next;
881 }
882 }
883 #endif
884
885 wxWindow::SetDropTarget( dropTarget );
886
887 #ifndef NEW_GTK_DND_CODE
888 if (m_dropTarget)
889 {
890 GList *child = m_list->children;
891 while (child)
892 {
893 m_dropTarget->RegisterWidget( GTK_WIDGET( child->data ) );
894 child = child->next;
895 }
896 }
897 #endif
898 }
899 #endif
900
901 GtkWidget *wxListBox::GetConnectWidget()
902 {
903 return GTK_WIDGET(m_list);
904 }
905
906 bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
907 {
908 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
909
910 GList *child = m_list->children;
911 while (child)
912 {
913 GtkWidget *bin = GTK_WIDGET( child->data );
914 if (bin->window == window) return TRUE;
915 child = child->next;
916 }
917
918 return FALSE;
919 }
920
921 void wxListBox::ApplyWidgetStyle()
922 {
923 SetWidgetStyle();
924
925 if (m_backgroundColour.Ok())
926 {
927 GdkWindow *window = GTK_WIDGET(m_list)->window;
928 if ( window )
929 {
930 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
931 gdk_window_set_background( window, m_backgroundColour.GetColor() );
932 gdk_window_clear( window );
933 }
934 }
935
936 GList *child = m_list->children;
937 while (child)
938 {
939 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
940
941 GtkBin *bin = GTK_BIN( child->data );
942 GtkWidget *label = GTK_WIDGET( bin->child );
943 gtk_widget_set_style( label, m_widgetStyle );
944
945 child = child->next;
946 }
947 }
948
949 #endif