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