1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "listbox.h" 
  15 #include "wx/dynarray.h" 
  16 #include "wx/listbox.h" 
  20 //----------------------------------------------------------------------------- 
  22 //----------------------------------------------------------------------------- 
  24 extern bool   g_blockEventsOnDrag
; 
  26 //----------------------------------------------------------------------------- 
  27 // "select" and "deselect" 
  28 //----------------------------------------------------------------------------- 
  30 static void gtk_listitem_select_callback( GtkWidget 
*WXUNUSED(widget
), wxListBox 
*listbox 
) 
  32     if (!listbox
->HasVMT()) return; 
  33     if (g_blockEventsOnDrag
) return; 
  35     wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, listbox
->GetId() ); 
  37     wxArrayInt aSelections
; 
  38     int count 
= listbox
->GetSelections(aSelections
); 
  41         event
.m_commandInt 
= aSelections
[0] ; 
  42         event
.m_clientData 
= listbox
->GetClientData( event
.m_commandInt 
); 
  43         wxString 
str(listbox
->GetString(event
.m_commandInt
)); 
  44         if (str 
!= "") event
.m_commandString 
= copystring((char *)(const char *)str
); 
  48         event
.m_commandInt 
= -1 ; 
  49         event
.m_commandString 
= copystring("") ; 
  52     event
.SetEventObject( listbox 
); 
  54     listbox
->GetEventHandler()->ProcessEvent( event 
); 
  55     if (event
.m_commandString
) delete[] event
.m_commandString 
; 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  62 IMPLEMENT_DYNAMIC_CLASS(wxListBox
,wxControl
) 
  64 wxListBox::wxListBox() 
  66     m_list 
= (GtkList 
*) NULL
; 
  69 bool wxListBox::Create( wxWindow 
*parent
, wxWindowID id
, 
  70                         const wxPoint 
&pos
, const wxSize 
&size
, 
  71                         int n
, const wxString choices
[], 
  72                         long style
, const wxValidator
& validator
, const wxString 
&name 
) 
  76     PreCreation( parent
, id
, pos
, size
, style
, name 
); 
  78     SetValidator( validator 
); 
  80     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL 
); 
  81     gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget
), 
  82       GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
  84     m_list 
= GTK_LIST( gtk_list_new() ); 
  86     GtkSelectionMode mode 
= GTK_SELECTION_BROWSE
; 
  87     if (style 
& wxLB_MULTIPLE
) 
  88         mode 
= GTK_SELECTION_MULTIPLE
; 
  89     else if (style 
& wxLB_EXTENDED
) 
  90         mode 
= GTK_SELECTION_EXTENDED
; 
  92     gtk_list_set_selection_mode( GTK_LIST(m_list
), mode 
); 
  94     gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_list
) ); 
  95     gtk_widget_show( GTK_WIDGET(m_list
) ); 
  97     wxSize newSize 
= size
; 
  98     if (newSize
.x 
== -1) newSize
.x 
= 100; 
  99     if (newSize
.y 
== -1) newSize
.y 
= 110; 
 100     SetSize( newSize
.x
, newSize
.y 
); 
 102     for (int i 
= 0; i 
< n
; i
++) 
 104         m_clientDataList
.Append( (wxObject
*) NULL 
); 
 105         m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 107         GtkWidget 
*list_item
; 
 108         list_item 
= gtk_list_item_new_with_label( choices
[i
] ); 
 110         gtk_container_add( GTK_CONTAINER(m_list
), list_item 
); 
 112         gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 113           GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 115         if (style 
& wxLB_MULTIPLE
) 
 116             gtk_signal_connect( GTK_OBJECT(list_item
), "deselect", 
 117               GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 119         ConnectWidget( list_item 
);      
 121         gtk_widget_show( list_item 
); 
 124     m_parent
->AddChild( this ); 
 126     (m_parent
->m_insertCallback
)( m_parent
, this ); 
 130     gtk_widget_realize( GTK_WIDGET(m_list
) ); 
 132     SetBackgroundColour( parent
->GetBackgroundColour() ); 
 133     SetForegroundColour( parent
->GetForegroundColour() ); 
 140 wxListBox::~wxListBox() 
 145 void wxListBox::AppendCommon( const wxString 
&item 
) 
 147     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 149     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( item 
); 
 151     gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 152       GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 154     if (GetWindowStyleFlag() & wxLB_MULTIPLE
) 
 155         gtk_signal_connect( GTK_OBJECT(list_item
), "deselect", 
 156           GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 158     gtk_container_add( GTK_CONTAINER(m_list
), list_item 
); 
 160     if (m_widgetStyle
) ApplyWidgetStyle(); 
 162     gtk_widget_show( list_item 
); 
 164     ConnectWidget( list_item 
); 
 166     if (m_dropTarget
) m_dropTarget
->RegisterWidget( list_item 
); 
 169 void wxListBox::Append( const wxString 
&item 
) 
 171     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 172     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 174     AppendCommon( item 
); 
 177 void wxListBox::Append( const wxString 
&item
, void *clientData 
) 
 179     m_clientDataList
.Append( (wxObject
*) clientData 
); 
 180     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 182     AppendCommon( item 
); 
 185 void wxListBox::Append( const wxString 
&item
, wxClientData 
*clientData 
) 
 187     m_clientObjectList
.Append( (wxObject
*) clientData 
); 
 188     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 190     AppendCommon( item 
); 
 193 void wxListBox::SetClientData( int n
, void* clientData 
) 
 195     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 197     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 200     node
->SetData( (wxObject
*) clientData 
); 
 203 void* wxListBox::GetClientData( int n 
) 
 205     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, "invalid combobox" ); 
 207     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 208     if (!node
) return NULL
; 
 213 void wxListBox::SetClientObject( int n
, wxClientData
* clientData 
) 
 215     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 217     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 220     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 223     node
->SetData( (wxObject
*) clientData 
); 
 226 wxClientData
* wxListBox::GetClientObject( int n 
) 
 228     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, "invalid combobox" ); 
 230     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 231     if (!node
) return (wxClientData
*) NULL
; 
 233     return (wxClientData
*) node
->Data(); 
 236 void wxListBox::Clear() 
 238     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 240     gtk_list_clear_items( m_list
, 0, Number() ); 
 242     wxNode 
*node 
= m_clientObjectList
.First(); 
 245         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 249     m_clientObjectList
.Clear(); 
 251     m_clientDataList
.Clear(); 
 254 void wxListBox::Delete( int n 
) 
 256     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 258     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 262       wxFAIL_MSG("wrong listbox index"); 
 266     GList 
*list 
= g_list_append( NULL
, child
->data 
); 
 267     gtk_list_remove_items( m_list
, list 
); 
 270     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 273         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 275         m_clientObjectList
.DeleteNode( node 
); 
 278     node 
= m_clientDataList
.Nth( n 
); 
 281         m_clientDataList
.DeleteNode( node 
); 
 285 void wxListBox::Deselect( int n 
) 
 287     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 289     gtk_list_unselect_item( m_list
, n 
); 
 292 int wxListBox::FindString( const wxString 
&item 
) const 
 294     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 296     GList 
*child 
= m_list
->children
; 
 300         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 301         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 302         if (item 
== label
->label
) return count
; 
 307   // it's not an error if the string is not found -> no wxCHECK 
 312 int wxListBox::GetSelection() const 
 314     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 316     GList 
*child 
= m_list
->children
; 
 320         if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) return count
; 
 327 int wxListBox::GetSelections( wxArrayInt
& aSelections 
) const 
 329     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 331     // get the number of selected items first 
 332     GList 
*child 
= m_list
->children
; 
 334     for (child 
= m_list
->children
; child 
!= NULL
; child 
= child
->next
) 
 336         if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) 
 345         aSelections
.Alloc(count
); // optimization attempt 
 347         for (child 
= m_list
->children
; child 
!= NULL
; child 
= child
->next
, i
++) 
 349             if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) 
 357 wxString 
wxListBox::GetString( int n 
) const 
 359     wxCHECK_MSG( m_list 
!= NULL
, "", "invalid listbox" ); 
 361     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 364         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 365         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 368     wxFAIL_MSG("wrong listbox index"); 
 372 wxString 
wxListBox::GetStringSelection() const 
 374     wxCHECK_MSG( m_list 
!= NULL
, "", "invalid listbox" ); 
 376     GList 
*selection 
= m_list
->selection
; 
 379         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 380         wxString tmp 
= GTK_LABEL( bin
->child 
)->label
; 
 383     wxFAIL_MSG("no listbox selection available"); 
 387 int wxListBox::Number() 
 389     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 391     GList 
*child 
= m_list
->children
; 
 393     while (child
) { count
++; child 
= child
->next
; } 
 397 bool wxListBox::Selected( int n 
) 
 399     wxCHECK_MSG( m_list 
!= NULL
, FALSE
, "invalid listbox" ); 
 401     GList 
*target 
= g_list_nth( m_list
->children
, n 
); 
 404         GList 
*child 
= m_list
->selection
; 
 407             if (child
->data 
== target
->data
) return TRUE
; 
 411     wxFAIL_MSG("wrong listbox index"); 
 415 void wxListBox::Set( int WXUNUSED(n
), const wxString 
*WXUNUSED(choices
) ) 
 417     wxFAIL_MSG("wxListBox::Set not implemented"); 
 420 void wxListBox::SetFirstItem( int WXUNUSED(n
) ) 
 422     wxFAIL_MSG("wxListBox::SetFirstItem not implemented"); 
 425 void wxListBox::SetFirstItem( const wxString 
&WXUNUSED(item
) ) 
 427     wxFAIL_MSG("wxListBox::SetFirstItem not implemented"); 
 430 void wxListBox::SetSelection( int n
, bool select 
) 
 432     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 435         gtk_list_select_item( m_list
, n 
); 
 437         gtk_list_unselect_item( m_list
, n 
); 
 440 void wxListBox::SetString( int n
, const wxString 
&string 
) 
 442     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 444     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 447         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 448         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 449         gtk_label_set( label
, string 
); 
 453         wxFAIL_MSG("wrong listbox index"); 
 457 void wxListBox::SetStringSelection( const wxString 
&string
, bool select 
) 
 459     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 461     SetSelection( FindString(string
), select 
); 
 464 int wxListBox::GetIndex( GtkWidget 
*item 
) const 
 468         GList 
*child 
= m_list
->children
; 
 472             if (GTK_WIDGET(child
->data
) == item
) return count
; 
 480 void wxListBox::SetDropTarget( wxDropTarget 
*dropTarget 
) 
 482     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 486         GList 
*child 
= m_list
->children
; 
 489 #ifdef NEW_GTK_DND_CODE 
 490             GtkBin 
*item 
= GTK_BIN( child
->data 
); 
 491             m_dropTarget
->UnregisterWidget( item
->child 
); 
 493             m_dropTarget
->UnregisterWidget( GTK_WIDGET( child
->data 
) ); 
 499 #ifndef NEW_GTK_DND_CODE 
 500     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( m_list 
); 
 503     if (m_dropTarget
) delete m_dropTarget
; 
 504     m_dropTarget 
= dropTarget
; 
 506 #ifndef NEW_GTK_DND_CODE 
 507     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
 512         GList 
*child 
= m_list
->children
; 
 515 #ifdef NEW_GTK_DND_CODE 
 516             GtkBin 
*item 
= GTK_BIN( child
->data 
); 
 517             m_dropTarget
->RegisterWidget( item
->child 
); 
 519             m_dropTarget
->RegisterWidget( GTK_WIDGET( child
->data 
) ); 
 526 GtkWidget 
*wxListBox::GetConnectWidget() 
 528     return GTK_WIDGET(m_list
); 
 531 bool wxListBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 533     if (wxWindow::IsOwnGtkWindow( window 
)) return TRUE
; 
 535     GList 
*child 
= m_list
->children
; 
 538         GtkWidget 
*bin 
= GTK_WIDGET( child
->data 
); 
 539         if (bin
->window 
== window
) return TRUE
; 
 546 void wxListBox::ApplyWidgetStyle() 
 550     if (m_backgroundColour
.Ok()) 
 552         GdkWindow 
*window 
= GTK_WIDGET(m_list
)->window
; 
 553         m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
 554         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
 555         gdk_window_clear( window 
); 
 558     GList 
*child 
= m_list
->children
; 
 561         gtk_widget_set_style( GTK_BIN(child
->data
)->child
, m_widgetStyle 
); 
 562         gtk_widget_set_style( GTK_WIDGET(child
->data
), m_widgetStyle 
);