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