1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "combobox.h" 
  14 #include "wx/combobox.h" 
  17 //----------------------------------------------------------------------------- 
  19 //----------------------------------------------------------------------------- 
  21 extern bool   g_blockEventsOnDrag
; 
  23 //----------------------------------------------------------------------------- 
  25 //----------------------------------------------------------------------------- 
  27 static void gtk_combo_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  29     if (!combo
->HasVMT()) return; 
  30     if (g_blockEventsOnDrag
) return; 
  32     if (combo
->m_alreadySent
) 
  34         combo
->m_alreadySent 
= FALSE
; 
  38     combo
->m_alreadySent 
= TRUE
; 
  40     wxCommandEvent 
event(wxEVT_COMMAND_CHOICE_SELECTED
, combo
->GetId()); 
  41     event
.SetInt( combo
->GetSelection() ); 
  42     wxString 
tmp( combo
->GetStringSelection() ); 
  43     event
.SetString( WXSTRINGCAST(tmp
) ); 
  44     event
.SetEventObject(combo
); 
  45     combo
->GetEventHandler()->ProcessEvent(event
); 
  48 //----------------------------------------------------------------------------- 
  50 //----------------------------------------------------------------------------- 
  52 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
,wxControl
) 
  54 BEGIN_EVENT_TABLE(wxComboBox
, wxControl
) 
  55     EVT_SIZE(wxComboBox::OnSize
) 
  58 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, const wxString
& value
, 
  59                          const wxPoint
& pos
, const wxSize
& size
, 
  60                          int n
, const wxString choices
[], 
  61                          long style
, const wxValidator
& validator
,  
  62                          const wxString
& name 
) 
  64     m_alreadySent 
= FALSE
; 
  67     PreCreation( parent
, id
, pos
, size
, style
, name 
); 
  69     SetValidator( validator 
); 
  71     m_widget 
= gtk_combo_new(); 
  73     wxSize newSize 
= size
; 
  74     if (newSize
.x 
== -1) newSize
.x 
= 100; 
  75     if (newSize
.y 
== -1) newSize
.y 
= 26; 
  76     SetSize( newSize
.x
, newSize
.y 
); 
  78     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
  80     for (int i 
= 0; i 
< n
; i
++) 
  82         GtkWidget 
*list_item 
= gtk_list_item_new_with_label( choices
[i
] );  
  84         m_clientDataList
.Append( (wxObject
*)NULL 
); 
  86         gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
  88         gtk_widget_realize( list_item 
); 
  89         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
  91         gtk_widget_show( list_item 
); 
  93         gtk_signal_connect( GTK_OBJECT(list_item
), "select",  
  94         GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
  97     m_parent
->AddChild( this ); 
  99     (m_parent
->m_insertCallback
)( m_parent
, this ); 
 103     ConnectWidget( GTK_COMBO(m_widget
)->button 
); 
 105     if (!value
.IsNull()) SetValue( value 
); 
 107     gtk_widget_realize( GTK_COMBO(m_widget
)->list 
); 
 108     gtk_widget_realize( GTK_COMBO(m_widget
)->entry 
); 
 109     gtk_widget_realize( GTK_COMBO(m_widget
)->button 
); 
 111     SetBackgroundColour( parent
->GetBackgroundColour() ); 
 112     SetForegroundColour( parent
->GetForegroundColour() ); 
 119 wxComboBox::~wxComboBox() 
 121     wxNode 
*node 
= m_clientDataList
.First(); 
 124         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 128     m_clientDataList
.Clear(); 
 131 void wxComboBox::AppendCommon( const wxString 
&item 
) 
 133     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 135     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 137     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( item 
);  
 139     gtk_signal_connect( GTK_OBJECT(list_item
), "select",  
 140       GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
 142     gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 144     if (m_widgetStyle
) ApplyWidgetStyle(); 
 146     gtk_widget_show( list_item 
); 
 149 void wxComboBox::Append( const wxString 
&item 
) 
 151     m_clientDataList
.Append( (wxObject
*)NULL 
); 
 153     AppendCommon( item 
); 
 156 void wxComboBox::Append( const wxString 
&item
, void *clientData 
) 
 159         m_clientDataList
.Append( (wxObject
*) new wxVoidClientData( clientData 
) ); 
 161         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 163     AppendCommon( item 
); 
 166 void wxComboBox::Append( const wxString 
&item
, wxClientData 
*clientData 
) 
 168     m_clientDataList
.Append( (wxObject
*) clientData 
); 
 170     AppendCommon( item 
); 
 173 void wxComboBox::SetClientData( int n
, void* clientData 
) 
 175     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 177     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 180     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 184         node
->SetData( (wxObject
*) new wxVoidClientData(clientData
) ); 
 186         node
->SetData( (wxObject
*) NULL 
); 
 189 void* wxComboBox::GetClientData( int n 
) 
 191     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, "invalid combobox" ); 
 193     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 194     if (!node
) return NULL
; 
 196     wxVoidClientData 
*cd 
= (wxVoidClientData
*) node
->Data(); 
 198         return cd
->GetData(); 
 203 void wxComboBox::SetClientObject( int n
, wxClientData
* clientData 
) 
 205     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 207     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 210     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 213     node
->SetData( (wxObject
*) clientData 
); 
 216 wxClientData
* wxComboBox::GetClientObject( int n 
) 
 218     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, "invalid combobox" ); 
 220     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 221     if (!node
) return (wxClientData
*) NULL
; 
 223     return (wxClientData
*) node
->Data(); 
 226 void wxComboBox::Clear() 
 228     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 230     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 231     gtk_list_clear_items( GTK_LIST(list
), 0, Number() ); 
 233     wxNode 
*node 
= m_clientDataList
.First(); 
 236         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 240     m_clientDataList
.Clear(); 
 243 void wxComboBox::Delete( int n 
) 
 245     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 247     GtkList 
*listbox 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 249     GList 
*child 
= g_list_nth( listbox
->children
, n 
); 
 253         wxFAIL_MSG("wrong index"); 
 257     GList 
*list 
= g_list_append( NULL
, child
->data 
); 
 258     gtk_list_remove_items( listbox
, list 
); 
 261     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 264         wxFAIL_MSG( "wrong index" ); 
 268         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 270         m_clientDataList
.DeleteNode( node 
); 
 274 int wxComboBox::FindString( const wxString 
&item 
) 
 276     wxCHECK_MSG( m_widget 
!= NULL
, -1, "invalid combobox" ); 
 278     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 280     GList 
*child 
= GTK_LIST(list
)->children
; 
 284         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 285         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 286         if (item 
== label
->label
) return count
; 
 291     wxFAIL_MSG( "wxComboBox: string not found" ); 
 296 int wxComboBox::GetSelection() const 
 298     wxCHECK_MSG( m_widget 
!= NULL
, -1, "invalid combobox" ); 
 300     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 302     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 305         GList 
*child 
= GTK_LIST(list
)->children
; 
 309             if (child
->data 
== selection
->data
) return count
; 
 315     wxFAIL_MSG( "wxComboBox: no selection" ); 
 320 wxString 
wxComboBox::GetString( int n 
) const 
 322     wxCHECK_MSG( m_widget 
!= NULL
, "", "invalid combobox" ); 
 324     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 326     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 329         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 330         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 334     wxFAIL_MSG( "wxComboBox: wrong index" ); 
 339 wxString 
wxComboBox::GetStringSelection() const 
 341     wxCHECK_MSG( m_widget 
!= NULL
, "", "invalid combobox" ); 
 343     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 345     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 348         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 349         wxString tmp 
= GTK_LABEL( bin
->child 
)->label
; 
 353     wxFAIL_MSG( "wxComboBox: no selection" ); 
 358 int wxComboBox::Number() const 
 360     wxCHECK_MSG( m_widget 
!= NULL
, 0, "invalid combobox" ); 
 362     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 364     GList 
*child 
= GTK_LIST(list
)->children
; 
 366     while (child
) { count
++; child 
= child
->next
; } 
 370 void wxComboBox::SetSelection( int n 
) 
 372     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 374     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 375     gtk_list_select_item( GTK_LIST(list
), n 
); 
 378 void wxComboBox::SetStringSelection( const wxString 
&string 
) 
 380     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 382     int res 
= FindString( string 
); 
 383     if (res 
== -1) return; 
 387 wxString 
wxComboBox::GetValue() const 
 389     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 390     wxString tmp 
= gtk_entry_get_text( GTK_ENTRY(entry
) ); 
 394 void wxComboBox::SetValue( const wxString
& value 
) 
 396     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 398     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 400     if (!value
.IsNull()) tmp 
= value
; 
 401     gtk_entry_set_text( GTK_ENTRY(entry
), tmp 
); 
 404 void wxComboBox::Copy() 
 406     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 408     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 409 #if (GTK_MINOR_VERSION == 1) 
 410     gtk_editable_copy_clipboard( GTK_EDITABLE(entry
) ); 
 412     gtk_editable_copy_clipboard( GTK_EDITABLE(entry
), 0 ); 
 416 void wxComboBox::Cut() 
 418     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 420     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 421 #if (GTK_MINOR_VERSION == 1) 
 422     gtk_editable_cut_clipboard( GTK_EDITABLE(entry
) ); 
 424     gtk_editable_cut_clipboard( GTK_EDITABLE(entry
), 0 ); 
 428 void wxComboBox::Paste() 
 430     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 432     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 433 #if (GTK_MINOR_VERSION == 1) 
 434     gtk_editable_paste_clipboard( GTK_EDITABLE(entry
) ); 
 436     gtk_editable_paste_clipboard( GTK_EDITABLE(entry
), 0 ); 
 440 void wxComboBox::SetInsertionPoint( long pos 
) 
 442     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 444     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 446     gtk_entry_set_position( GTK_ENTRY(entry
), tmp 
); 
 449 void wxComboBox::SetInsertionPointEnd() 
 451     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 453     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 454     int pos 
= GTK_ENTRY(entry
)->text_length
; 
 455     SetInsertionPoint( pos
-1 ); 
 458 long wxComboBox::GetInsertionPoint() const 
 460     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 461     return (long) GTK_EDITABLE(entry
)->current_pos
; 
 464 long wxComboBox::GetLastPosition() const 
 466     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 467     int pos 
= GTK_ENTRY(entry
)->text_length
; 
 471 void wxComboBox::Replace( long from
, long to
, const wxString
& value 
) 
 473     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 475     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 476     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 477     if (value
.IsNull()) return; 
 479     gtk_editable_insert_text( GTK_EDITABLE(entry
), value
, value
.Length(), &pos 
); 
 482 void wxComboBox::Remove(long from
, long to
) 
 484     wxCHECK_RET( m_widget 
!= NULL
, "invalid combobox" ); 
 486     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 487     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 490 void wxComboBox::SetSelection( long WXUNUSED(from
), long WXUNUSED(to
) ) 
 492     wxFAIL_MSG( "wxComboBox::SetSelection not implemented" ); 
 495 void wxComboBox::SetEditable( bool WXUNUSED(editable
) ) 
 497     wxFAIL_MSG( "wxComboBox::SetEditable not implemented" ); 
 500 void wxComboBox::OnSize( wxSizeEvent 
&event 
) 
 502     wxControl::OnSize( event 
); 
 505     gtk_widget_set_usize( GTK_COMBO(m_widget
)->entry
, m_width
-w
-1, m_height 
); 
 507     gtk_widget_set_uposition( GTK_COMBO(m_widget
)->button
, m_x
+m_width
-w
, m_y 
); 
 508     gtk_widget_set_usize( GTK_COMBO(m_widget
)->button
, w
, m_height 
); 
 511 void wxComboBox::ApplyWidgetStyle() 
 515     gtk_widget_set_style( GTK_COMBO(m_widget
)->button
, m_widgetStyle 
); 
 516     gtk_widget_set_style( GTK_COMBO(m_widget
)->entry
, m_widgetStyle 
); 
 517     gtk_widget_set_style( GTK_COMBO(m_widget
)->list
, m_widgetStyle 
); 
 519     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 520     GList 
*child 
= list
->children
; 
 523         gtk_widget_set_style( GTK_WIDGET(child
->data
), m_widgetStyle 
); 
 525         GtkBin 
*bin 
= GTK_BIN(child
->data
); 
 526         gtk_widget_set_style( bin
->child
, m_widgetStyle 
); 
 532 GtkWidget
* wxComboBox::GetConnectWidget() 
 534     return GTK_COMBO(m_widget
)->entry
; 
 537 bool wxComboBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 539     return ( (window 
== GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
)->text_area
) || 
 540              (window 
== GTK_COMBO(m_widget
)->button
->window 
) );