]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/listbox.cpp
Documented help API extension and fixed gsocket compilation.
[wxWidgets.git] / src / gtk1 / 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 DisableEvents();
644
645 gtk_list_unselect_item( m_list, n );
646
647 EnableEvents();
648 }
649
650 int wxListBox::FindString( const wxString &item ) const
651 {
652 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
653
654 GList *child = m_list->children;
655 int count = 0;
656 while (child)
657 {
658 GtkBin *bin = GTK_BIN( child->data );
659 GtkLabel *label = GTK_LABEL( bin->child );
660
661 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
662
663 if (str == item)
664 return count;
665
666 count++;
667 child = child->next;
668 }
669
670 // it's not an error if the string is not found -> no wxCHECK
671
672 return -1;
673 }
674
675 int wxListBox::GetSelection() const
676 {
677 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
678
679 GList *child = m_list->children;
680 int count = 0;
681 while (child)
682 {
683 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
684 count++;
685 child = child->next;
686 }
687 return -1;
688 }
689
690 int wxListBox::GetSelections( wxArrayInt& aSelections ) const
691 {
692 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
693
694 // get the number of selected items first
695 GList *child = m_list->children;
696 int count = 0;
697 for (child = m_list->children; child != NULL; child = child->next)
698 {
699 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
700 count++;
701 }
702
703 aSelections.Empty();
704
705 if (count > 0)
706 {
707 // now fill the list
708 aSelections.Alloc(count); // optimization attempt
709 int i = 0;
710 for (child = m_list->children; child != NULL; child = child->next, i++)
711 {
712 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
713 aSelections.Add(i);
714 }
715 }
716
717 return count;
718 }
719
720 wxString wxListBox::GetString( int n ) const
721 {
722 wxCHECK_MSG( m_list != NULL, _T(""), _T("invalid listbox") );
723
724 GList *child = g_list_nth( m_list->children, n );
725 if (child)
726 {
727 GtkBin *bin = GTK_BIN( child->data );
728 GtkLabel *label = GTK_LABEL( bin->child );
729
730 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
731
732 return str;
733 }
734
735 wxFAIL_MSG(_T("wrong listbox index"));
736
737 return _T("");
738 }
739
740 wxString wxListBox::GetStringSelection() const
741 {
742 wxCHECK_MSG( m_list != NULL, _T(""), _T("invalid listbox") );
743
744 GList *selection = m_list->selection;
745 if (selection)
746 {
747 GtkBin *bin = GTK_BIN( selection->data );
748 GtkLabel *label = GTK_LABEL( bin->child );
749
750 wxString str = wxString(GET_REAL_LABEL(label->label),*wxConvCurrent);
751
752 return str;
753 }
754
755 wxFAIL_MSG(_T("no listbox selection available"));
756 return _T("");
757 }
758
759 int wxListBox::Number()
760 {
761 wxCHECK_MSG( m_list != NULL, -1, _T("invalid listbox") );
762
763 GList *child = m_list->children;
764 int count = 0;
765 while (child) { count++; child = child->next; }
766 return count;
767 }
768
769 bool wxListBox::Selected( int n )
770 {
771 wxCHECK_MSG( m_list != NULL, FALSE, _T("invalid listbox") );
772
773 GList *target = g_list_nth( m_list->children, n );
774 if (target)
775 {
776 GList *child = m_list->selection;
777 while (child)
778 {
779 if (child->data == target->data) return TRUE;
780 child = child->next;
781 }
782 }
783 wxFAIL_MSG(_T("wrong listbox index"));
784 return FALSE;
785 }
786
787 void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
788 {
789 wxFAIL_MSG(_T("wxListBox::Set not implemented"));
790 }
791
792 void wxListBox::SetFirstItem( int WXUNUSED(n) )
793 {
794 wxFAIL_MSG(_T("wxListBox::SetFirstItem not implemented"));
795 }
796
797 void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
798 {
799 wxFAIL_MSG(_T("wxListBox::SetFirstItem not implemented"));
800 }
801
802 void wxListBox::SetSelection( int n, bool select )
803 {
804 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
805
806 DisableEvents();
807
808 if (select)
809 gtk_list_select_item( m_list, n );
810 else
811 gtk_list_unselect_item( m_list, n );
812
813 EnableEvents();
814 }
815
816 void wxListBox::SetString( int n, const wxString &string )
817 {
818 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
819
820 GList *child = g_list_nth( m_list->children, n );
821 if (child)
822 {
823 GtkBin *bin = GTK_BIN( child->data );
824 GtkLabel *label = GTK_LABEL( bin->child );
825
826 wxString str;
827 #if wxUSE_CHECKLISTBOX
828 if (m_hasCheckBoxes)
829 str += CHECKBOX_STRING;
830 #endif // wxUSE_CHECKLISTBOX
831 str += string;
832
833 gtk_label_set( label, str.mbc_str() );
834 }
835 else
836 {
837 wxFAIL_MSG(_T("wrong listbox index"));
838 }
839 }
840
841 void wxListBox::SetStringSelection( const wxString &string, bool select )
842 {
843 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
844
845 SetSelection( FindString(string), select );
846 }
847
848 int wxListBox::GetIndex( GtkWidget *item ) const
849 {
850 if (item)
851 {
852 GList *child = m_list->children;
853 int count = 0;
854 while (child)
855 {
856 if (GTK_WIDGET(child->data) == item) return count;
857 count++;
858 child = child->next;
859 }
860 }
861 return -1;
862 }
863
864 #if wxUSE_TOOLTIPS
865 void wxListBox::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
866 {
867 GList *child = m_list->children;
868 while (child)
869 {
870 gtk_tooltips_set_tip( tips, GTK_WIDGET( child->data ), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
871 child = child->next;
872 }
873 }
874 #endif // wxUSE_TOOLTIPS
875
876 #if wxUSE_DRAG_AND_DROP
877 void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
878 {
879 wxCHECK_RET( m_list != NULL, _T("invalid listbox") );
880
881 #ifndef NEW_GTK_DND_CODE
882 if (m_dropTarget)
883 {
884 GList *child = m_list->children;
885 while (child)
886 {
887 m_dropTarget->UnregisterWidget( GTK_WIDGET( child->data ) );
888 child = child->next;
889 }
890 }
891 #endif
892
893 wxWindow::SetDropTarget( dropTarget );
894
895 #ifndef NEW_GTK_DND_CODE
896 if (m_dropTarget)
897 {
898 GList *child = m_list->children;
899 while (child)
900 {
901 m_dropTarget->RegisterWidget( GTK_WIDGET( child->data ) );
902 child = child->next;
903 }
904 }
905 #endif
906 }
907 #endif
908
909 void wxListBox::DisableEvents()
910 {
911 GList *child = m_list->children;
912 while (child)
913 {
914 gtk_signal_disconnect_by_func( GTK_OBJECT(child->data),
915 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
916
917 if (HasFlag(wxLB_MULTIPLE))
918 gtk_signal_disconnect_by_func( GTK_OBJECT(child->data),
919 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
920
921 child = child->next;
922 }
923 }
924
925 void wxListBox::EnableEvents()
926 {
927 GList *child = m_list->children;
928 while (child)
929 {
930 gtk_signal_connect( GTK_OBJECT(child->data), "select",
931 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
932
933 if (HasFlag(wxLB_MULTIPLE))
934 gtk_signal_connect( GTK_OBJECT(child->data), "deselect",
935 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
936
937 child = child->next;
938 }
939 }
940
941 GtkWidget *wxListBox::GetConnectWidget()
942 {
943 return GTK_WIDGET(m_list);
944 }
945
946 bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
947 {
948 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
949
950 GList *child = m_list->children;
951 while (child)
952 {
953 GtkWidget *bin = GTK_WIDGET( child->data );
954 if (bin->window == window) return TRUE;
955 child = child->next;
956 }
957
958 return FALSE;
959 }
960
961 void wxListBox::ApplyWidgetStyle()
962 {
963 SetWidgetStyle();
964
965 if (m_backgroundColour.Ok())
966 {
967 GdkWindow *window = GTK_WIDGET(m_list)->window;
968 if ( window )
969 {
970 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
971 gdk_window_set_background( window, m_backgroundColour.GetColor() );
972 gdk_window_clear( window );
973 }
974 }
975
976 GList *child = m_list->children;
977 while (child)
978 {
979 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
980
981 GtkBin *bin = GTK_BIN( child->data );
982 GtkWidget *label = GTK_WIDGET( bin->child );
983 gtk_widget_set_style( label, m_widgetStyle );
984
985 child = child->next;
986 }
987 }
988
989 #endif