1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  11 #pragma implementation "combobox.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  17 #include "wx/combobox.h" 
  21 #include "wx/settings.h" 
  22 #include "wx/arrstr.h" 
  25 #include "wx/textctrl.h"    // for wxEVT_COMMAND_TEXT_UPDATED 
  27 #include "wx/gtk/private.h" 
  29 //----------------------------------------------------------------------------- 
  31 //----------------------------------------------------------------------------- 
  33 extern void wxapp_install_idle_handler(); 
  36 //----------------------------------------------------------------------------- 
  38 //----------------------------------------------------------------------------- 
  40 extern bool   g_blockEventsOnDrag
; 
  42 //----------------------------------------------------------------------------- 
  43 //  "changed" - typing and list item matches get changed, select-child 
  44 //              if it doesn't match an item then just get a single changed 
  45 //----------------------------------------------------------------------------- 
  48 gtk_text_changed_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  50     if (g_isIdle
) wxapp_install_idle_handler(); 
  52     if (combo
->m_ignoreNextUpdate
) 
  54         combo
->m_ignoreNextUpdate 
= FALSE
; 
  58     if (!combo
->m_hasVMT
) return; 
  60     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
  61     event
.SetString( combo
->GetValue() ); 
  62     event
.SetEventObject( combo 
); 
  63     combo
->GetEventHandler()->ProcessEvent( event 
); 
  67 gtk_dummy_callback(GtkEntry 
*WXUNUSED(entry
), GtkCombo 
*WXUNUSED(combo
)) 
  71 //----------------------------------------------------------------------------- 
  72 // "select-child" - click/cursor get select-child, changed, select-child 
  73 //----------------------------------------------------------------------------- 
  76 gtk_combo_select_child_callback( GtkList 
*WXUNUSED(list
), GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  78     if (g_isIdle
) wxapp_install_idle_handler(); 
  80     if (!combo
->m_hasVMT
) return; 
  82     if (g_blockEventsOnDrag
) return; 
  84     int curSelection 
= combo
->GetSelection(); 
  86     if (combo
->m_prevSelection 
== curSelection
) return; 
  88     GtkWidget 
*list 
= GTK_COMBO(combo
->m_widget
)->list
; 
  89     gtk_list_unselect_item( GTK_LIST(list
), combo
->m_prevSelection 
); 
  91     combo
->m_prevSelection 
= curSelection
; 
  93     // Quickly set the value of the combo box 
  94     // as GTK+ does that only AFTER the event 
  96     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(combo
->GetHandle())->entry
), 
  97       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)combo 
); 
  98     combo
->SetValue( combo
->GetStringSelection() ); 
  99     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(combo
->GetHandle())->entry
), "changed", 
 100       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)combo 
); 
 102     wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, combo
->GetId() ); 
 103     event
.SetInt( curSelection 
); 
 104     event
.SetString( combo
->GetStringSelection() ); 
 105     event
.SetEventObject( combo 
); 
 107     combo
->GetEventHandler()->ProcessEvent( event 
); 
 109     // Now send the event ourselves 
 110     wxCommandEvent 
event2( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
 111     event2
.SetString( combo
->GetValue() ); 
 112     event2
.SetEventObject( combo 
); 
 113     combo
->GetEventHandler()->ProcessEvent( event2 
); 
 116 //----------------------------------------------------------------------------- 
 118 //----------------------------------------------------------------------------- 
 120 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
,wxControl
) 
 122 BEGIN_EVENT_TABLE(wxComboBox
, wxControl
) 
 123     EVT_SIZE(wxComboBox::OnSize
) 
 124     EVT_CHAR(wxComboBox::OnChar
) 
 126     EVT_MENU(wxID_CUT
, wxComboBox::OnCut
) 
 127     EVT_MENU(wxID_COPY
, wxComboBox::OnCopy
) 
 128     EVT_MENU(wxID_PASTE
, wxComboBox::OnPaste
) 
 129     EVT_MENU(wxID_UNDO
, wxComboBox::OnUndo
) 
 130     EVT_MENU(wxID_REDO
, wxComboBox::OnRedo
) 
 131     EVT_MENU(wxID_CLEAR
, wxComboBox::OnDelete
) 
 132     EVT_MENU(wxID_SELECTALL
, wxComboBox::OnSelectAll
) 
 134     EVT_UPDATE_UI(wxID_CUT
, wxComboBox::OnUpdateCut
) 
 135     EVT_UPDATE_UI(wxID_COPY
, wxComboBox::OnUpdateCopy
) 
 136     EVT_UPDATE_UI(wxID_PASTE
, wxComboBox::OnUpdatePaste
) 
 137     EVT_UPDATE_UI(wxID_UNDO
, wxComboBox::OnUpdateUndo
) 
 138     EVT_UPDATE_UI(wxID_REDO
, wxComboBox::OnUpdateRedo
) 
 139     EVT_UPDATE_UI(wxID_CLEAR
, wxComboBox::OnUpdateDelete
) 
 140     EVT_UPDATE_UI(wxID_SELECTALL
, wxComboBox::OnUpdateSelectAll
) 
 143 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, 
 144                          const wxString
& value
, 
 145                          const wxPoint
& pos
, const wxSize
& size
, 
 146                          const wxArrayString
& choices
, 
 147                          long style
, const wxValidator
& validator
, 
 148                          const wxString
& name 
) 
 150     wxCArrayString 
chs(choices
); 
 152     return Create( parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 153                    chs
.GetStrings(), style
, validator
, name 
); 
 156 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, const wxString
& value
, 
 157                          const wxPoint
& pos
, const wxSize
& size
, 
 158                          int n
, const wxString choices
[], 
 159                          long style
, const wxValidator
& validator
, 
 160                          const wxString
& name 
) 
 162     m_ignoreNextUpdate 
= FALSE
; 
 164     m_acceptsFocus 
= TRUE
; 
 167     if (!PreCreation( parent
, pos
, size 
) || 
 168         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 170         wxFAIL_MSG( wxT("wxComboBox creation failed") ); 
 174     m_widget 
= gtk_combo_new(); 
 175     GtkCombo 
*combo 
= GTK_COMBO(m_widget
); 
 177     // Disable GTK's broken events ... 
 178     gtk_signal_disconnect( GTK_OBJECT(combo
->entry
), combo
->entry_change_id 
); 
 179     // ... and add surogate handler. 
 180     combo
->entry_change_id 
= gtk_signal_connect (GTK_OBJECT (combo
->entry
), "changed", 
 181                               (GtkSignalFunc
) gtk_dummy_callback
, combo
); 
 183     // make it more useable 
 184     gtk_combo_set_use_arrows_always( GTK_COMBO(m_widget
), TRUE 
); 
 186     // and case-sensitive 
 187     gtk_combo_set_case_sensitive( GTK_COMBO(m_widget
), TRUE 
); 
 189     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 192     // gtk_list_set_selection_mode( GTK_LIST(list), GTK_SELECTION_MULTIPLE ); 
 195     for (int i 
= 0; i 
< n
; i
++) 
 197         GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( choices
[i
] ) ); 
 199         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 200         m_clientObjectList
.Append( (wxObject
*)NULL 
); 
 202         gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 204         gtk_widget_show( list_item 
); 
 207     m_parent
->DoAddChild( this ); 
 209     m_focusWidget 
= combo
->entry
; 
 213     ConnectWidget( combo
->button 
); 
 215     // MSW's combo box shows the value and the selection is -1 
 216     gtk_entry_set_text( GTK_ENTRY(combo
->entry
), wxGTK_CONV(value
) ); 
 217     gtk_list_unselect_all( GTK_LIST(combo
->list
) ); 
 219     if (style 
& wxCB_READONLY
) 
 220         gtk_entry_set_editable( GTK_ENTRY( combo
->entry 
), FALSE 
); 
 222     gtk_signal_connect( GTK_OBJECT(combo
->entry
), "changed", 
 223       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 225     gtk_signal_connect( GTK_OBJECT(combo
->list
), "select-child", 
 226       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 228     SetBestSize(size
); // need this too because this is a wxControlWithItems 
 230     // This is required for tool bar support 
 231     wxSize setsize 
= GetSize(); 
 232     gtk_widget_set_usize( m_widget
, setsize
.x
, setsize
.y 
); 
 237 wxComboBox::~wxComboBox() 
 239     wxList::compatibility_iterator node 
= m_clientObjectList
.GetFirst(); 
 242         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 244         node 
= node
->GetNext(); 
 246     m_clientObjectList
.Clear(); 
 248     m_clientDataList
.Clear(); 
 251 void wxComboBox::SetFocus() 
 255         // don't do anything if we already have focus 
 259     gtk_widget_grab_focus( m_focusWidget 
); 
 262 int wxComboBox::DoAppend( const wxString 
&item 
) 
 264     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 268     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 270     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( item 
) ); 
 272     gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 274     if (GTK_WIDGET_REALIZED(m_widget
)) 
 276         gtk_widget_realize( list_item 
); 
 277         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
 280     // Apply current widget style to the new list_item 
 281     GtkRcStyle 
*style 
= CreateWidgetStyle(); 
 284         gtk_widget_modify_style( GTK_WIDGET( list_item 
), style 
); 
 285         GtkBin 
*bin 
= GTK_BIN( list_item 
); 
 286         GtkWidget 
*label 
= GTK_WIDGET( bin
->child 
); 
 287         gtk_widget_modify_style( label
, style 
); 
 288         gtk_rc_style_unref( style 
); 
 291     gtk_widget_show( list_item 
); 
 293     const int count 
= GetCount(); 
 295     if ( (int)m_clientDataList
.GetCount() < count 
) 
 296     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 297     if ( (int)m_clientObjectList
.GetCount() < count 
) 
 298     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 302     InvalidateBestSize(); 
 307 int wxComboBox::DoInsert( const wxString 
&item
, int pos 
) 
 309     wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT
), -1, 
 310                     wxT("can't insert into sorted list")); 
 312     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 314     int count 
= GetCount(); 
 315     wxCHECK_MSG( (pos 
>= 0) && (pos 
<= count
), -1, wxT("invalid index") ); 
 322     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 324     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( item 
) ); 
 326     GList 
*gitem_list 
= g_list_alloc (); 
 327     gitem_list
->data 
= list_item
; 
 328     gtk_list_insert_items( GTK_LIST (list
), gitem_list
, pos 
); 
 330     if (GTK_WIDGET_REALIZED(m_widget
)) 
 332         gtk_widget_realize( list_item 
); 
 333         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
 338     gtk_widget_show( list_item 
); 
 342     if ( (int)m_clientDataList
.GetCount() < count 
) 
 343     m_clientDataList
.Insert( pos
, (wxObject
*) NULL 
); 
 344     if ( (int)m_clientObjectList
.GetCount() < count 
) 
 345     m_clientObjectList
.Insert( pos
, (wxObject
*) NULL 
); 
 349     InvalidateBestSize(); 
 354 void wxComboBox::DoSetItemClientData( int n
, void* clientData 
) 
 356     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 358     wxList::compatibility_iterator node 
= m_clientDataList
.Item( n 
); 
 361     node
->SetData( (wxObject
*) clientData 
); 
 364 void* wxComboBox::DoGetItemClientData( int n 
) const 
 366     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, wxT("invalid combobox") ); 
 368     wxList::compatibility_iterator node 
= m_clientDataList
.Item( n 
); 
 370     return node 
? node
->GetData() : NULL
; 
 373 void wxComboBox::DoSetItemClientObject( int n
, wxClientData
* clientData 
) 
 375     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 377     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 380     // wxItemContainer already deletes data for us 
 382     node
->SetData( (wxObject
*) clientData 
); 
 385 wxClientData
* wxComboBox::DoGetItemClientObject( int n 
) const 
 387     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, wxT("invalid combobox") ); 
 389     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 391     return node 
? (wxClientData
*) node
->GetData() : NULL
; 
 394 void wxComboBox::Clear() 
 396     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 400     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 401     gtk_list_clear_items( GTK_LIST(list
), 0, GetCount() ); 
 403     wxList::compatibility_iterator node 
= m_clientObjectList
.GetFirst(); 
 406         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 408         node 
= node
->GetNext(); 
 410     m_clientObjectList
.Clear(); 
 412     m_clientDataList
.Clear(); 
 416     InvalidateBestSize(); 
 419 void wxComboBox::Delete( int n 
) 
 421     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 423     GtkList 
*listbox 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 425     GList 
*child 
= g_list_nth( listbox
->children
, n 
); 
 429         wxFAIL_MSG(wxT("wrong index")); 
 435     GList 
*list 
= g_list_append( (GList
*) NULL
, child
->data 
); 
 436     gtk_list_remove_items( listbox
, list 
); 
 439     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 442         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 444         m_clientObjectList
.Erase( node 
); 
 447     node 
= m_clientDataList
.Item( n 
); 
 449         m_clientDataList
.Erase( node 
); 
 453     InvalidateBestSize(); 
 456 void wxComboBox::SetString(int n
, const wxString 
&text
) 
 458     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 460     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 462     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 465         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 466         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 467         gtk_label_set_text(label
, wxGTK_CONV(text
)); 
 471         wxFAIL_MSG( wxT("wxComboBox: wrong index") ); 
 474     InvalidateBestSize(); 
 477 int wxComboBox::FindString( const wxString 
&item 
) const 
 479     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 481     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 483     GList 
*child 
= GTK_LIST(list
)->children
; 
 487         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 488         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 490         wxString 
str( wxGTK_CONV_BACK( gtk_label_get_text(label
) ) ); 
 492         wxString 
str( label
->label 
); 
 504 int wxComboBox::GetSelection() const 
 506     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 508     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 510     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 513         GList 
*child 
= GTK_LIST(list
)->children
; 
 517             if (child
->data 
== selection
->data
) return count
; 
 526 wxString 
wxComboBox::GetString( int n 
) const 
 528     wxCHECK_MSG( m_widget 
!= NULL
, wxT(""), wxT("invalid combobox") ); 
 530     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 533     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 536         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 537         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 539         str 
= wxGTK_CONV_BACK( gtk_label_get_text(label
) ); 
 541         str 
= wxString( label
->label 
); 
 546         wxFAIL_MSG( wxT("wxComboBox: wrong index") ); 
 552 wxString 
wxComboBox::GetStringSelection() const 
 554     wxCHECK_MSG( m_widget 
!= NULL
, wxT(""), wxT("invalid combobox") ); 
 556     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 558     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 561         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 562         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 564         wxString 
tmp( wxGTK_CONV_BACK( gtk_label_get_text(label
) ) ); 
 566         wxString 
tmp( label
->label 
); 
 571     wxFAIL_MSG( wxT("wxComboBox: no selection") ); 
 576 int wxComboBox::GetCount() const 
 578     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid combobox") ); 
 580     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 582     GList 
*child 
= GTK_LIST(list
)->children
; 
 584     while (child
) { count
++; child 
= child
->next
; } 
 588 void wxComboBox::SetSelection( int n 
) 
 590     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 594     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 595     gtk_list_unselect_item( GTK_LIST(list
), m_prevSelection 
); 
 596     gtk_list_select_item( GTK_LIST(list
), n 
); 
 602 bool wxComboBox::SetStringSelection( const wxString 
&string 
) 
 604     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid combobox") ); 
 606     int res 
= FindString( string 
); 
 607     if (res 
== -1) return false; 
 612 wxString 
wxComboBox::GetValue() const 
 614     GtkEntry 
*entry 
= GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
); 
 615     wxString 
tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry 
) ) ); 
 618     for (int i 
= 0; i 
< wxStrlen(tmp
.c_str()) +1; i
++) 
 621         printf( "%d ", (int) (c
) ); 
 629 void wxComboBox::SetValue( const wxString
& value 
) 
 631     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 633     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 634     wxString tmp 
= wxT(""); 
 635     if (!value
.IsNull()) tmp 
= value
; 
 636     gtk_entry_set_text( GTK_ENTRY(entry
), wxGTK_CONV( tmp 
) ); 
 638     InvalidateBestSize(); 
 641 void wxComboBox::Copy() 
 643     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 645     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 646     gtk_editable_copy_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 649 void wxComboBox::Cut() 
 651     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 653     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 654     gtk_editable_cut_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 657 void wxComboBox::Paste() 
 659     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 661     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 662     gtk_editable_paste_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG
); 
 665 void wxComboBox::Undo() 
 670 void wxComboBox::Redo() 
 675 void wxComboBox::SelectAll() 
 677     SetSelection(0, GetLastPosition()); 
 680 bool wxComboBox::CanUndo() const 
 686 bool wxComboBox::CanRedo() const 
 692 bool wxComboBox::HasSelection() const 
 695     GetSelection(&from
, &to
); 
 699 bool wxComboBox::CanCopy() const 
 701     // Can copy if there's a selection 
 702     return HasSelection(); 
 705 bool wxComboBox::CanCut() const 
 707     return CanCopy() && IsEditable(); 
 710 bool wxComboBox::CanPaste() const 
 712     // TODO: check for text on the clipboard 
 713     return IsEditable() ; 
 716 bool wxComboBox::IsEditable() const 
 718     return !HasFlag(wxCB_READONLY
); 
 722 void wxComboBox::SetInsertionPoint( long pos 
) 
 724     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 726     if ( pos 
== GetLastPosition() ) 
 729     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 730     gtk_entry_set_position( GTK_ENTRY(entry
), (int)pos 
); 
 733 long wxComboBox::GetInsertionPoint() const 
 735     return (long) GET_EDITABLE_POS( GTK_COMBO(m_widget
)->entry 
); 
 738 long wxComboBox::GetLastPosition() const 
 740     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 741     int pos 
= GTK_ENTRY(entry
)->text_length
; 
 745 void wxComboBox::Replace( long from
, long to
, const wxString
& value 
) 
 747     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 749     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 750     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 751     if (value
.IsNull()) return; 
 755     wxCharBuffer buffer 
= wxConvUTF8
.cWX2MB( value 
); 
 756     gtk_editable_insert_text( GTK_EDITABLE(entry
), (const char*) buffer
, strlen( (const char*) buffer 
), &pos 
); 
 758     gtk_editable_insert_text( GTK_EDITABLE(entry
), value
.c_str(), value
.Length(), &pos 
); 
 762 void wxComboBox::SetSelection( long from
, long to 
) 
 764     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 765     gtk_editable_select_region( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 768 void wxComboBox::GetSelection( long* from
, long* to 
) const 
 773         GtkEditable 
*editable 
= GTK_EDITABLE(GTK_COMBO(m_widget
)->entry
); 
 775         gtk_editable_get_selection_bounds(editable
, & start
, & end
); 
 779         *from 
= (long) editable
->selection_start_pos
; 
 780         *to 
= (long) editable
->selection_end_pos
; 
 785 void wxComboBox::SetEditable( bool editable 
) 
 787     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 788     gtk_entry_set_editable( GTK_ENTRY(entry
), editable 
); 
 791 void wxComboBox::OnChar( wxKeyEvent 
&event 
) 
 793     if ( event
.GetKeyCode() == WXK_RETURN 
) 
 795         // GTK automatically selects an item if its in the list 
 796         wxCommandEvent 
event(wxEVT_COMMAND_TEXT_ENTER
, GetId()); 
 797         event
.SetString( GetValue() ); 
 798         event
.SetInt( GetSelection() ); 
 799         event
.SetEventObject( this ); 
 801         if (!GetEventHandler()->ProcessEvent( event 
)) 
 803             // This will invoke the dialog default action, such 
 804             // as the clicking the default button. 
 806             wxWindow 
*top_frame 
= m_parent
; 
 807             while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 808                 top_frame 
= top_frame
->GetParent(); 
 810             if (top_frame 
&& GTK_IS_WINDOW(top_frame
->m_widget
)) 
 812                 GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 814                 if (window
->default_widget
) 
 815                         gtk_widget_activate (window
->default_widget
); 
 819         // Catch GTK event so that GTK doesn't open the drop 
 820         // down list upon RETURN. 
 827 void wxComboBox::DisableEvents() 
 829     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget
)->list
), 
 830       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 831     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget
)->entry
), 
 832       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 835 void wxComboBox::EnableEvents() 
 837     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(m_widget
)->list
), "select-child", 
 838       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 839     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(m_widget
)->entry
), "changed", 
 840       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 843 void wxComboBox::OnSize( wxSizeEvent 
&event 
) 
 845     // NB: In some situations (e.g. on non-first page of a wizard, if the 
 846     //     size used is default size), GtkCombo widget is resized correctly, 
 847     //     but it's look is not updated, it's rendered as if it was much wider. 
 848     //     No other widgets are affected, so it looks like a bug in GTK+. 
 849     //     Manually requesting resize calculation (as gtk_pizza_set_size does) 
 851     if (GTK_WIDGET_VISIBLE(m_widget
)) 
 852         gtk_widget_queue_resize(m_widget
); 
 857 void wxComboBox::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 859 //    gtk_widget_modify_style( GTK_COMBO(m_widget)->button, syle ); 
 861     gtk_widget_modify_style( GTK_COMBO(m_widget
)->entry
, style 
); 
 862     gtk_widget_modify_style( GTK_COMBO(m_widget
)->list
, style 
); 
 864     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 865     GList 
*child 
= list
->children
; 
 868         gtk_widget_modify_style( GTK_WIDGET(child
->data
), style 
); 
 870         GtkBin 
*bin 
= GTK_BIN(child
->data
); 
 871         gtk_widget_modify_style( bin
->child
, style 
); 
 877 GtkWidget
* wxComboBox::GetConnectWidget() 
 879     return GTK_COMBO(m_widget
)->entry
; 
 882 bool wxComboBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 884     return ( (window 
== GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
)->text_area
) || 
 885              (window 
== GTK_COMBO(m_widget
)->button
->window 
) ); 
 888 wxSize 
wxComboBox::DoGetBestSize() const 
 890     wxSize 
ret( wxControl::DoGetBestSize() ); 
 892     // we know better our horizontal extent: it depends on the longest string 
 897         size_t count 
= GetCount(); 
 898         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 900             GetTextExtent( GetString(n
), &width
, NULL
, NULL
, NULL 
); 
 906     // empty combobox should have some reasonable default size too 
 916 wxComboBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 918     return GetDefaultAttributesFromGTKWidget(gtk_combo_new
, true); 
 921 // ---------------------------------------------------------------------------- 
 922 // standard event handling 
 923 // ---------------------------------------------------------------------------- 
 925 void wxComboBox::OnCut(wxCommandEvent
& WXUNUSED(event
)) 
 930 void wxComboBox::OnCopy(wxCommandEvent
& WXUNUSED(event
)) 
 935 void wxComboBox::OnPaste(wxCommandEvent
& WXUNUSED(event
)) 
 940 void wxComboBox::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
 945 void wxComboBox::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
 950 void wxComboBox::OnDelete(wxCommandEvent
& WXUNUSED(event
)) 
 953     GetSelection(& from
, & to
); 
 954     if (from 
!= -1 && to 
!= -1) 
 958 void wxComboBox::OnSelectAll(wxCommandEvent
& WXUNUSED(event
)) 
 960     SetSelection(-1, -1); 
 963 void wxComboBox::OnUpdateCut(wxUpdateUIEvent
& event
) 
 965     event
.Enable( CanCut() ); 
 968 void wxComboBox::OnUpdateCopy(wxUpdateUIEvent
& event
) 
 970     event
.Enable( CanCopy() ); 
 973 void wxComboBox::OnUpdatePaste(wxUpdateUIEvent
& event
) 
 975     event
.Enable( CanPaste() ); 
 978 void wxComboBox::OnUpdateUndo(wxUpdateUIEvent
& event
) 
 980     event
.Enable( CanUndo() ); 
 983 void wxComboBox::OnUpdateRedo(wxUpdateUIEvent
& event
) 
 985     event
.Enable( CanRedo() ); 
 988 void wxComboBox::OnUpdateDelete(wxUpdateUIEvent
& event
) 
 990     event
.Enable(HasSelection() && IsEditable()) ; 
 993 void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent
& event
) 
 995     event
.Enable(GetLastPosition() > 0);