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         GtkWidget 
*list_item
; 
 105         list_item 
= gtk_list_item_new_with_label( choices
[i
] ); 
 107         gtk_container_add( GTK_CONTAINER(m_list
), list_item 
); 
 109         gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 110           GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 112         if (style 
& wxLB_MULTIPLE
) 
 113             gtk_signal_connect( GTK_OBJECT(list_item
), "deselect", 
 114               GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 116         ConnectWidget( list_item 
);      
 118         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 120         gtk_widget_show( list_item 
); 
 123     m_parent
->AddChild( this ); 
 125     (m_parent
->m_insertCallback
)( m_parent
, this ); 
 129     gtk_widget_realize( GTK_WIDGET(m_list
) ); 
 131     SetBackgroundColour( parent
->GetBackgroundColour() ); 
 132     SetForegroundColour( parent
->GetForegroundColour() ); 
 139 wxListBox::~wxListBox() 
 141     wxNode 
*node 
= m_clientDataList
.First(); 
 144         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 148     m_clientDataList
.Clear(); 
 151 void wxListBox::AppendCommon( const wxString 
&item 
) 
 153     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 155     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( item 
); 
 157     gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 158       GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 160     if (GetWindowStyleFlag() & wxLB_MULTIPLE
) 
 161         gtk_signal_connect( GTK_OBJECT(list_item
), "deselect", 
 162           GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this ); 
 164     gtk_container_add( GTK_CONTAINER(m_list
), list_item 
); 
 166     if (m_widgetStyle
) ApplyWidgetStyle(); 
 168     gtk_widget_show( list_item 
); 
 170     ConnectWidget( list_item 
); 
 172     ConnectDnDWidget( list_item 
); 
 175 void wxListBox::Append( const wxString 
&item 
) 
 177     m_clientDataList
.Append( (wxObject
*)NULL 
); 
 179     AppendCommon( item 
); 
 182 void wxListBox::Append( const wxString 
&item
, void *clientData 
) 
 185         m_clientDataList
.Append( (wxObject
*) new wxVoidClientData( clientData 
) ); 
 187         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 189     AppendCommon( item 
); 
 192 void wxListBox::Append( const wxString 
&item
, wxClientData 
*clientData 
) 
 194     m_clientDataList
.Append( (wxObject
*) clientData 
); 
 196     AppendCommon( item 
); 
 199 void wxListBox::SetClientData( int n
, void* clientData 
) 
 201     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 203     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 206     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 210         node
->SetData( (wxObject
*) new wxVoidClientData(clientData
) ); 
 212         node
->SetData( (wxObject
*) NULL 
); 
 215 void* wxListBox::GetClientData( int n 
) 
 217     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, "invalid combobox" ); 
 219     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 220     if (!node
) return NULL
; 
 222     wxVoidClientData 
*cd 
= (wxVoidClientData
*) node
->Data(); 
 224         return cd
->GetData(); 
 229 void wxListBox::SetClientObject( int n
, wxClientData
* clientData 
) 
 231     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 233     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 236     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 239     node
->SetData( (wxObject
*) clientData 
); 
 242 wxClientData
* wxListBox::GetClientObject( int n 
) 
 244     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, "invalid combobox" ); 
 246     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 247     if (!node
) return (wxClientData
*) NULL
; 
 249     return (wxClientData
*) node
->Data(); 
 252 void wxListBox::Clear() 
 254     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 256     gtk_list_clear_items( m_list
, 0, Number() ); 
 258     wxNode 
*node 
= m_clientDataList
.First(); 
 261         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 265     m_clientDataList
.Clear(); 
 268 void wxListBox::Delete( int n 
) 
 270     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 272     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 276       wxFAIL_MSG("wrong listbox index"); 
 280     GList 
*list 
= g_list_append( NULL
, child
->data 
); 
 281     gtk_list_remove_items( m_list
, list 
); 
 284     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 287         wxFAIL_MSG( "wrong index" ); 
 291         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 293         m_clientDataList
.DeleteNode( node 
); 
 297 void wxListBox::Deselect( int n 
) 
 299     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 301     gtk_list_unselect_item( m_list
, n 
); 
 304 int wxListBox::FindString( const wxString 
&item 
) const 
 306     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 308     GList 
*child 
= m_list
->children
; 
 312         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 313         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 314         if (item 
== label
->label
) return count
; 
 319   // it's not an error if the string is not found -> no wxCHECK 
 324 int wxListBox::GetSelection() const 
 326     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 328     GList 
*child 
= m_list
->children
; 
 332         if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) return count
; 
 339 int wxListBox::GetSelections( wxArrayInt
& aSelections 
) const 
 341     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 343     // get the number of selected items first 
 344     GList 
*child 
= m_list
->children
; 
 346     for (child 
= m_list
->children
; child 
!= NULL
; child 
= child
->next
) 
 348         if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) 
 357         aSelections
.Alloc(count
); // optimization attempt 
 359         for (child 
= m_list
->children
; child 
!= NULL
; child 
= child
->next
, i
++) 
 361             if (GTK_WIDGET(child
->data
)->state 
== GTK_STATE_SELECTED
) 
 369 wxString 
wxListBox::GetString( int n 
) const 
 371     wxCHECK_MSG( m_list 
!= NULL
, "", "invalid listbox" ); 
 373     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 376         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 377         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 380     wxFAIL_MSG("wrong listbox index"); 
 384 wxString 
wxListBox::GetStringSelection() const 
 386     wxCHECK_MSG( m_list 
!= NULL
, "", "invalid listbox" ); 
 388     GList 
*selection 
= m_list
->selection
; 
 391         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 392         wxString tmp 
= GTK_LABEL( bin
->child 
)->label
; 
 395     wxFAIL_MSG("no listbox selection available"); 
 399 int wxListBox::Number() 
 401     wxCHECK_MSG( m_list 
!= NULL
, -1, "invalid listbox" ); 
 403     GList 
*child 
= m_list
->children
; 
 405     while (child
) { count
++; child 
= child
->next
; } 
 409 bool wxListBox::Selected( int n 
) 
 411     wxCHECK_MSG( m_list 
!= NULL
, FALSE
, "invalid listbox" ); 
 413     GList 
*target 
= g_list_nth( m_list
->children
, n 
); 
 416         GList 
*child 
= m_list
->selection
; 
 419             if (child
->data 
== target
->data
) return TRUE
; 
 423     wxFAIL_MSG("wrong listbox index"); 
 427 void wxListBox::Set( int WXUNUSED(n
), const wxString 
*WXUNUSED(choices
) ) 
 429     wxFAIL_MSG("wxListBox::Set not implemented"); 
 432 void wxListBox::SetFirstItem( int WXUNUSED(n
) ) 
 434     wxFAIL_MSG("wxListBox::SetFirstItem not implemented"); 
 437 void wxListBox::SetFirstItem( const wxString 
&WXUNUSED(item
) ) 
 439     wxFAIL_MSG("wxListBox::SetFirstItem not implemented"); 
 442 void wxListBox::SetSelection( int n
, bool select 
) 
 444     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 447         gtk_list_select_item( m_list
, n 
); 
 449         gtk_list_unselect_item( m_list
, n 
); 
 452 void wxListBox::SetString( int n
, const wxString 
&string 
) 
 454     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 456     GList 
*child 
= g_list_nth( m_list
->children
, n 
); 
 459         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 460         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 461         gtk_label_set( label
, string 
); 
 465         wxFAIL_MSG("wrong listbox index"); 
 469 void wxListBox::SetStringSelection( const wxString 
&string
, bool select 
) 
 471     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 473     SetSelection( FindString(string
), select 
); 
 476 int wxListBox::GetIndex( GtkWidget 
*item 
) const 
 480         GList 
*child 
= m_list
->children
; 
 484             if (GTK_WIDGET(child
->data
) == item
) return count
; 
 492 void wxListBox::SetDropTarget( wxDropTarget 
*dropTarget 
) 
 494     wxCHECK_RET( m_list 
!= NULL
, "invalid listbox" ); 
 496     GList 
*child 
= m_list
->children
; 
 499         DisconnectDnDWidget( GTK_WIDGET( child
->data 
) ); 
 503     wxWindow::SetDropTarget( dropTarget  
); 
 505     child 
= m_list
->children
; 
 508         ConnectDnDWidget( GTK_WIDGET( child
->data 
) ); 
 513 GtkWidget 
*wxListBox::GetConnectWidget() 
 515     return GTK_WIDGET(m_list
); 
 518 bool wxListBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 520     if (wxWindow::IsOwnGtkWindow( window 
)) return TRUE
; 
 522     GList 
*child 
= m_list
->children
; 
 525         GtkWidget 
*bin 
= GTK_WIDGET( child
->data 
); 
 526         if (bin
->window 
== window
) return TRUE
; 
 533 void wxListBox::ApplyWidgetStyle() 
 537     GdkWindow 
*window 
= GTK_WIDGET(m_list
)->window
; 
 538     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
 539     gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
 540     gdk_window_clear( window 
); 
 542     GList 
*child 
= m_list
->children
; 
 545         gtk_widget_set_style( GTK_BIN(child
->data
)->child
, m_widgetStyle 
); 
 546         gtk_widget_set_style( GTK_WIDGET(child
->data
), m_widgetStyle 
);