1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/combobox.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  15 #include "wx/combobox.h" 
  19     #include "wx/settings.h" 
  22 #include "wx/arrstr.h" 
  24 #include "wx/textctrl.h"    // for wxEVT_COMMAND_TEXT_UPDATED 
  26 #include "wx/gtk1/private.h" 
  28 //----------------------------------------------------------------------------- 
  30 //----------------------------------------------------------------------------- 
  32 extern void wxapp_install_idle_handler(); 
  35 //----------------------------------------------------------------------------- 
  37 //----------------------------------------------------------------------------- 
  39 extern bool   g_blockEventsOnDrag
; 
  40 static int    g_SelectionBeforePopup 
= wxID_NONE
; // this means the popup is hidden 
  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 //----------------------------------------------------------------------------- 
  49 gtk_text_changed_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  51     if (g_isIdle
) wxapp_install_idle_handler(); 
  53     if (combo
->m_ignoreNextUpdate
) 
  55         combo
->m_ignoreNextUpdate 
= false; 
  59     if (!combo
->m_hasVMT
) return; 
  61     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
  62     event
.SetString( combo
->GetValue() ); 
  63     event
.SetEventObject( combo 
); 
  64     combo
->GetEventHandler()->ProcessEvent( event 
); 
  70 gtk_dummy_callback(GtkEntry 
*WXUNUSED(entry
), GtkCombo 
*WXUNUSED(combo
)) 
  77 gtk_popup_hide_callback(GtkCombo 
*WXUNUSED(gtk_combo
), wxComboBox 
*combo
) 
  79     // when the popup is hidden, throw a SELECTED event only if the combobox 
  81     const int curSelection 
= combo
->GetCurrentSelection(); 
  83     const bool hasChanged 
= curSelection 
!= g_SelectionBeforePopup
; 
  85     // reset the selection flag to value meaning that it is hidden and do it 
  86     // now, before generating the events, so that GetSelection() returns the 
  87     // new value from the event handler 
  88     g_SelectionBeforePopup 
= wxID_NONE
; 
  92         wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, combo
->GetId() ); 
  93         event
.SetInt( curSelection 
); 
  94         event
.SetString( combo
->GetStringSelection() ); 
  95         event
.SetEventObject( combo 
); 
  96         combo
->GetEventHandler()->ProcessEvent( event 
); 
  98         // for consistency with the other ports, send TEXT event 
  99         wxCommandEvent 
event2( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
 100         event2
.SetString( combo
->GetStringSelection() ); 
 101         event2
.SetEventObject( combo 
); 
 102         combo
->GetEventHandler()->ProcessEvent( event2 
); 
 109 gtk_popup_show_callback(GtkCombo 
*WXUNUSED(gtk_combo
), wxComboBox 
*combo
) 
 111     // store the combobox selection value before the popup is shown 
 112     g_SelectionBeforePopup 
= combo
->GetCurrentSelection(); 
 116 //----------------------------------------------------------------------------- 
 117 // "select-child" - click/cursor get select-child, changed, select-child 
 118 //----------------------------------------------------------------------------- 
 122 gtk_combo_select_child_callback( GtkList 
*WXUNUSED(list
), GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
 124     if (g_isIdle
) wxapp_install_idle_handler(); 
 126     if (!combo
->m_hasVMT
) return; 
 128     if (g_blockEventsOnDrag
) return; 
 130     int curSelection 
= combo
->GetCurrentSelection(); 
 132     if (combo
->m_prevSelection 
== curSelection
) return; 
 134     GtkWidget 
*list 
= GTK_COMBO(combo
->m_widget
)->list
; 
 135     gtk_list_unselect_item( GTK_LIST(list
), combo
->m_prevSelection 
); 
 137     combo
->m_prevSelection 
= curSelection
; 
 139     // Quickly set the value of the combo box 
 140     // as GTK+ does that only AFTER the event 
 142     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(combo
->GetHandle())->entry
), 
 143       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)combo 
); 
 144     combo
->SetValue( combo
->GetStringSelection() ); 
 145     gtk_signal_connect_after( GTK_OBJECT(GTK_COMBO(combo
->GetHandle())->entry
), "changed", 
 146       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)combo 
); 
 148     // throw a SELECTED event only if the combobox popup is hidden (wxID_NONE) 
 149     // because when combobox popup is shown, gtk_combo_select_child_callback is 
 150     // called each times the mouse is over an item with a pressed button so a lot 
 151     // of SELECTED event could be generated if the user keep the mouse button down 
 152     // and select other items ... 
 153     if (g_SelectionBeforePopup 
== wxID_NONE
) 
 155         wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, combo
->GetId() ); 
 156         event
.SetInt( curSelection 
); 
 157         event
.SetString( combo
->GetStringSelection() ); 
 158         event
.SetEventObject( combo 
); 
 159         combo
->GetEventHandler()->ProcessEvent( event 
); 
 161         // for consistency with the other ports, don't generate text update 
 162         // events while the user is browsing the combobox neither 
 163         wxCommandEvent 
event2( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
 164         event2
.SetString( combo
->GetValue() ); 
 165         event2
.SetEventObject( combo 
); 
 166         combo
->GetEventHandler()->ProcessEvent( event2 
); 
 171 //----------------------------------------------------------------------------- 
 173 //----------------------------------------------------------------------------- 
 175 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
,wxControl
) 
 177 BEGIN_EVENT_TABLE(wxComboBox
, wxControl
) 
 178     EVT_SIZE(wxComboBox::OnSize
) 
 179     EVT_CHAR(wxComboBox::OnChar
) 
 181     EVT_MENU(wxID_CUT
, wxComboBox::OnCut
) 
 182     EVT_MENU(wxID_COPY
, wxComboBox::OnCopy
) 
 183     EVT_MENU(wxID_PASTE
, wxComboBox::OnPaste
) 
 184     EVT_MENU(wxID_UNDO
, wxComboBox::OnUndo
) 
 185     EVT_MENU(wxID_REDO
, wxComboBox::OnRedo
) 
 186     EVT_MENU(wxID_CLEAR
, wxComboBox::OnDelete
) 
 187     EVT_MENU(wxID_SELECTALL
, wxComboBox::OnSelectAll
) 
 189     EVT_UPDATE_UI(wxID_CUT
, wxComboBox::OnUpdateCut
) 
 190     EVT_UPDATE_UI(wxID_COPY
, wxComboBox::OnUpdateCopy
) 
 191     EVT_UPDATE_UI(wxID_PASTE
, wxComboBox::OnUpdatePaste
) 
 192     EVT_UPDATE_UI(wxID_UNDO
, wxComboBox::OnUpdateUndo
) 
 193     EVT_UPDATE_UI(wxID_REDO
, wxComboBox::OnUpdateRedo
) 
 194     EVT_UPDATE_UI(wxID_CLEAR
, wxComboBox::OnUpdateDelete
) 
 195     EVT_UPDATE_UI(wxID_SELECTALL
, wxComboBox::OnUpdateSelectAll
) 
 198 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, 
 199                          const wxString
& value
, 
 200                          const wxPoint
& pos
, const wxSize
& size
, 
 201                          const wxArrayString
& choices
, 
 202                          long style
, const wxValidator
& validator
, 
 203                          const wxString
& name 
) 
 205     wxCArrayString 
chs(choices
); 
 207     return Create( parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 208                    chs
.GetStrings(), style
, validator
, name 
); 
 211 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, const wxString
& value
, 
 212                          const wxPoint
& pos
, const wxSize
& size
, 
 213                          int n
, const wxString choices
[], 
 214                          long style
, const wxValidator
& validator
, 
 215                          const wxString
& name 
) 
 217     m_ignoreNextUpdate 
= false; 
 219     m_acceptsFocus 
= true; 
 222     if (!PreCreation( parent
, pos
, size 
) || 
 223         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 225         wxFAIL_MSG( wxT("wxComboBox creation failed") ); 
 229     m_widget 
= gtk_combo_new(); 
 230     GtkCombo 
*combo 
= GTK_COMBO(m_widget
); 
 232     // Disable GTK's broken events ... 
 233     gtk_signal_disconnect( GTK_OBJECT(combo
->entry
), combo
->entry_change_id 
); 
 234     // ... and add surrogate handler. 
 235     combo
->entry_change_id 
= gtk_signal_connect (GTK_OBJECT (combo
->entry
), "changed", 
 236                   (GtkSignalFunc
) gtk_dummy_callback
, combo
); 
 238     // make it more useable 
 239     gtk_combo_set_use_arrows_always( GTK_COMBO(m_widget
), TRUE 
); 
 241     // and case-sensitive 
 242     gtk_combo_set_case_sensitive( GTK_COMBO(m_widget
), TRUE 
); 
 244     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 246     // gtk_list_set_selection_mode( GTK_LIST(list), GTK_SELECTION_MULTIPLE ); 
 248     for (int i 
= 0; i 
< n
; i
++) 
 250         GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( choices
[i
] ) ); 
 252         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 253         m_clientObjectList
.Append( (wxObject
*)NULL 
); 
 255         gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 257         gtk_widget_show( list_item 
); 
 260     m_parent
->DoAddChild( this ); 
 262     m_focusWidget 
= combo
->entry
; 
 266     ConnectWidget( combo
->button 
); 
 268     // MSW's combo box shows the value and the selection is -1 
 269     gtk_entry_set_text( GTK_ENTRY(combo
->entry
), wxGTK_CONV(value
) ); 
 270     gtk_list_unselect_all( GTK_LIST(combo
->list
) ); 
 272     if (style 
& wxCB_READONLY
) 
 273         gtk_entry_set_editable( GTK_ENTRY( combo
->entry 
), FALSE 
); 
 275     // "show" and "hide" events are generated when user click on the combobox button which popups a list 
 276     // this list is the "popwin" gtk widget 
 277     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(combo
)->popwin
), "hide", 
 278                         GTK_SIGNAL_FUNC(gtk_popup_hide_callback
), (gpointer
)this ); 
 279     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(combo
)->popwin
), "show", 
 280                         GTK_SIGNAL_FUNC(gtk_popup_show_callback
), (gpointer
)this ); 
 282     gtk_signal_connect_after( GTK_OBJECT(combo
->entry
), "changed", 
 283       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 285     gtk_signal_connect_after( GTK_OBJECT(combo
->list
), "select-child", 
 286       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 288     SetBestSize(size
); // need this too because this is a wxControlWithItems 
 290     // This is required for tool bar support 
 291 //    wxSize setsize = GetSize(); 
 292 //    gtk_widget_set_usize( m_widget, setsize.x, setsize.y ); 
 297 wxComboBox::~wxComboBox() 
 299     wxList::compatibility_iterator node 
= m_clientObjectList
.GetFirst(); 
 302         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 304         node 
= node
->GetNext(); 
 306     m_clientObjectList
.Clear(); 
 308     m_clientDataList
.Clear(); 
 311 void wxComboBox::SetFocus() 
 315         // don't do anything if we already have focus 
 319     gtk_widget_grab_focus( m_focusWidget 
); 
 322 int wxComboBox::DoAppend( const wxString 
&item 
) 
 324     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 328     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 330     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( item 
) ); 
 332     gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 334     if (GTK_WIDGET_REALIZED(m_widget
)) 
 336         gtk_widget_realize( list_item 
); 
 337         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
 340     // Apply current widget style to the new list_item 
 341     GtkRcStyle 
*style 
= CreateWidgetStyle(); 
 344         gtk_widget_modify_style( GTK_WIDGET( list_item 
), style 
); 
 345         GtkBin 
*bin 
= GTK_BIN( list_item 
); 
 346         GtkWidget 
*label 
= GTK_WIDGET( bin
->child 
); 
 347         gtk_widget_modify_style( label
, style 
); 
 348         gtk_rc_style_unref( style 
); 
 351     gtk_widget_show( list_item 
); 
 353     const unsigned int count 
= GetCount(); 
 355     if ( m_clientDataList
.GetCount() < count 
) 
 356         m_clientDataList
.Append( (wxObject
*) NULL 
); 
 357     if ( m_clientObjectList
.GetCount() < count 
) 
 358         m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 362     InvalidateBestSize(); 
 367 int wxComboBox::DoInsert( const wxString 
&item
, unsigned int pos 
) 
 369     wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT
), -1, 
 370                     wxT("can't insert into sorted list")); 
 372     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 374     wxCHECK_MSG( IsValidInsert(pos
), -1, wxT("invalid index") ); 
 376     if (pos 
== GetCount()) 
 381     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 383     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( item 
) ); 
 385     GList 
*gitem_list 
= g_list_alloc (); 
 386     gitem_list
->data 
= list_item
; 
 387     gtk_list_insert_items( GTK_LIST (list
), gitem_list
, pos 
); 
 389     if (GTK_WIDGET_REALIZED(m_widget
)) 
 391         gtk_widget_realize( list_item 
); 
 392         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
 397     gtk_widget_show( list_item 
); 
 399     const unsigned int count 
= GetCount(); 
 401     if ( m_clientDataList
.GetCount() < count 
) 
 402         m_clientDataList
.Insert( pos
, (wxObject
*) NULL 
); 
 403     if ( m_clientObjectList
.GetCount() < count 
) 
 404         m_clientObjectList
.Insert( pos
, (wxObject
*) NULL 
); 
 408     InvalidateBestSize(); 
 413 void wxComboBox::DoSetItemClientData(unsigned int n
, void* clientData
) 
 415     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 417     wxList::compatibility_iterator node 
= m_clientDataList
.Item( n 
); 
 420     node
->SetData( (wxObject
*) clientData 
); 
 423 void* wxComboBox::DoGetItemClientData(unsigned int n
) const 
 425     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, wxT("invalid combobox") ); 
 427     wxList::compatibility_iterator node 
= m_clientDataList
.Item( n 
); 
 429     return node 
? node
->GetData() : NULL
; 
 432 void wxComboBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
) 
 434     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 436     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 439     // wxItemContainer already deletes data for us 
 441     node
->SetData( (wxObject
*) clientData 
); 
 444 wxClientData
* wxComboBox::DoGetItemClientObject(unsigned int n
) const 
 446     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, wxT("invalid combobox") ); 
 448     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 450     return node 
? (wxClientData
*) node
->GetData() : NULL
; 
 453 void wxComboBox::Clear() 
 455     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 459     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 460     gtk_list_clear_items( GTK_LIST(list
), 0, (int)GetCount() ); 
 462     wxList::compatibility_iterator node 
= m_clientObjectList
.GetFirst(); 
 465         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 467         node 
= node
->GetNext(); 
 469     m_clientObjectList
.Clear(); 
 471     m_clientDataList
.Clear(); 
 475     InvalidateBestSize(); 
 478 void wxComboBox::Delete(unsigned int n
) 
 480     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 482     GtkList 
*listbox 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 484     GList 
*child 
= g_list_nth( listbox
->children
, n 
); 
 488         wxFAIL_MSG(wxT("wrong index")); 
 494     GList 
*list 
= g_list_append( (GList
*) NULL
, child
->data 
); 
 495     gtk_list_remove_items( listbox
, list 
); 
 498     wxList::compatibility_iterator node 
= m_clientObjectList
.Item( n 
); 
 501         wxClientData 
*cd 
= (wxClientData
*)node
->GetData(); 
 503         m_clientObjectList
.Erase( node 
); 
 506     node 
= m_clientDataList
.Item( n 
); 
 508         m_clientDataList
.Erase( node 
); 
 512     InvalidateBestSize(); 
 515 void wxComboBox::SetString(unsigned int n
, const wxString 
&text
) 
 517     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 519     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 521     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 524         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 525         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 526         gtk_label_set_text(label
, wxGTK_CONV(text
)); 
 530         wxFAIL_MSG( wxT("wxComboBox: wrong index") ); 
 533     InvalidateBestSize(); 
 536 int wxComboBox::FindString( const wxString 
&item
, bool bCase 
) const 
 538     wxCHECK_MSG( m_widget 
!= NULL
, wxNOT_FOUND
, wxT("invalid combobox") ); 
 540     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 542     GList 
*child 
= GTK_LIST(list
)->children
; 
 546         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 547         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 548         wxString 
str( label
->label 
); 
 549         if (item
.IsSameAs( str 
, bCase 
) ) 
 559 int wxComboBox::GetSelection() const 
 561     // if the popup is currently opened, use the selection as it had been 
 562     // before it dropped down 
 563     return g_SelectionBeforePopup 
== wxID_NONE 
? GetCurrentSelection() 
 564                                                : g_SelectionBeforePopup
; 
 567 int wxComboBox::GetCurrentSelection() const 
 569     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 571     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 573     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 576         GList 
*child 
= GTK_LIST(list
)->children
; 
 580             if (child
->data 
== selection
->data
) return count
; 
 589 wxString 
wxComboBox::GetString(unsigned int n
) const 
 591     wxCHECK_MSG( m_widget 
!= NULL
, wxEmptyString
, wxT("invalid combobox") ); 
 593     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 596     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 599         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 600         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 601         str 
= wxString( label
->label 
); 
 605         wxFAIL_MSG( wxT("wxComboBox: wrong index") ); 
 611 wxString 
wxComboBox::GetStringSelection() const 
 613     wxCHECK_MSG( m_widget 
!= NULL
, wxEmptyString
, wxT("invalid combobox") ); 
 615     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 617     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 620         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 621         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 622         wxString 
tmp( label
->label 
); 
 626     wxFAIL_MSG( wxT("wxComboBox: no selection") ); 
 628     return wxEmptyString
; 
 631 unsigned int wxComboBox::GetCount() const 
 633     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid combobox") ); 
 635     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 637     GList 
*child 
= GTK_LIST(list
)->children
; 
 638     unsigned int count 
= 0; 
 639     while (child
) { count
++; child 
= child
->next
; } 
 643 void wxComboBox::SetSelection( int n 
) 
 645     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 649     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 650     gtk_list_unselect_item( GTK_LIST(list
), m_prevSelection 
); 
 651     gtk_list_select_item( GTK_LIST(list
), n 
); 
 657 wxString 
wxComboBox::GetValue() const 
 659     GtkEntry 
*entry 
= GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
); 
 660     wxString 
tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry 
) ) ); 
 663     for (int i 
= 0; i 
< wxStrlen(tmp
.c_str()) +1; i
++) 
 666         printf( "%d ", (int) (c
) ); 
 674 void wxComboBox::SetValue( const wxString
& value 
) 
 676     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 678     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 680     if (!value
.IsNull()) tmp 
= value
; 
 681     gtk_entry_set_text( GTK_ENTRY(entry
), wxGTK_CONV( tmp 
) ); 
 683     InvalidateBestSize(); 
 686 void wxComboBox::Copy() 
 688     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 690     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 691     gtk_editable_copy_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 694 void wxComboBox::Cut() 
 696     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 698     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 699     gtk_editable_cut_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 702 void wxComboBox::Paste() 
 704     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 706     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 707     gtk_editable_paste_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG
); 
 710 void wxComboBox::Undo() 
 715 void wxComboBox::Redo() 
 720 void wxComboBox::SelectAll() 
 722     SetSelection(0, GetLastPosition()); 
 725 bool wxComboBox::CanUndo() const 
 731 bool wxComboBox::CanRedo() const 
 737 bool wxComboBox::HasSelection() const 
 740     GetSelection(&from
, &to
); 
 744 bool wxComboBox::CanCopy() const 
 746     // Can copy if there's a selection 
 747     return HasSelection(); 
 750 bool wxComboBox::CanCut() const 
 752     return CanCopy() && IsEditable(); 
 755 bool wxComboBox::CanPaste() const 
 757     // TODO: check for text on the clipboard 
 758     return IsEditable() ; 
 761 bool wxComboBox::IsEditable() const 
 763     return !HasFlag(wxCB_READONLY
); 
 767 void wxComboBox::SetInsertionPoint( long pos 
) 
 769     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 771     if ( pos 
== GetLastPosition() ) 
 774     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 775     gtk_entry_set_position( GTK_ENTRY(entry
), (int)pos 
); 
 778 long wxComboBox::GetInsertionPoint() const 
 780     return (long) GET_EDITABLE_POS( GTK_COMBO(m_widget
)->entry 
); 
 783 wxTextPos 
wxComboBox::GetLastPosition() const 
 785     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 786     int pos 
= GTK_ENTRY(entry
)->text_length
; 
 790 void wxComboBox::Replace( long from
, long to
, const wxString
& value 
) 
 792     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 794     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 795     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 796     if (value
.IsNull()) return; 
 800     wxCharBuffer buffer 
= wxConvUTF8
.cWX2MB( value 
); 
 801     gtk_editable_insert_text( GTK_EDITABLE(entry
), (const char*) buffer
, strlen( (const char*) buffer 
), &pos 
); 
 803     gtk_editable_insert_text( GTK_EDITABLE(entry
), value
.c_str(), value
.length(), &pos 
); 
 807 void wxComboBox::SetSelection( long from
, long to 
) 
 809     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 810     gtk_editable_select_region( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 813 void wxComboBox::GetSelection( long* from
, long* to 
) const 
 817         GtkEditable 
*editable 
= GTK_EDITABLE(GTK_COMBO(m_widget
)->entry
); 
 818         *from 
= (long) editable
->selection_start_pos
; 
 819         *to 
= (long) editable
->selection_end_pos
; 
 823 void wxComboBox::SetEditable( bool editable 
) 
 825     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 826     gtk_entry_set_editable( GTK_ENTRY(entry
), editable 
); 
 829 void wxComboBox::OnChar( wxKeyEvent 
&event 
) 
 831     if ( event
.GetKeyCode() == WXK_RETURN 
) 
 833         // GTK automatically selects an item if its in the list 
 834         wxCommandEvent 
eventEnter(wxEVT_COMMAND_TEXT_ENTER
, GetId()); 
 835         eventEnter
.SetString( GetValue() ); 
 836         eventEnter
.SetInt( GetSelection() ); 
 837         eventEnter
.SetEventObject( this ); 
 839         if (!GetEventHandler()->ProcessEvent( eventEnter 
)) 
 841             // This will invoke the dialog default action, such 
 842             // as the clicking the default button. 
 844             wxWindow 
*top_frame 
= m_parent
; 
 845             while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 846                 top_frame 
= top_frame
->GetParent(); 
 848             if (top_frame 
&& GTK_IS_WINDOW(top_frame
->m_widget
)) 
 850                 GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 852                 if (window
->default_widget
) 
 853                         gtk_widget_activate (window
->default_widget
); 
 857         // Catch GTK event so that GTK doesn't open the drop 
 858         // down list upon RETURN. 
 865 void wxComboBox::DisableEvents() 
 867     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget
)->list
), 
 868       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 869     gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget
)->entry
), 
 870       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 873 void wxComboBox::EnableEvents() 
 875     gtk_signal_connect_after( GTK_OBJECT(GTK_COMBO(m_widget
)->list
), "select-child", 
 876       GTK_SIGNAL_FUNC(gtk_combo_select_child_callback
), (gpointer
)this ); 
 877     gtk_signal_connect_after( GTK_OBJECT(GTK_COMBO(m_widget
)->entry
), "changed", 
 878       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this ); 
 881 void wxComboBox::OnSize( wxSizeEvent 
&event 
) 
 883     // NB: In some situations (e.g. on non-first page of a wizard, if the 
 884     //     size used is default size), GtkCombo widget is resized correctly, 
 885     //     but it's look is not updated, it's rendered as if it was much wider. 
 886     //     No other widgets are affected, so it looks like a bug in GTK+. 
 887     //     Manually requesting resize calculation (as gtk_pizza_set_size does) 
 889     if (GTK_WIDGET_VISIBLE(m_widget
)) 
 890         gtk_widget_queue_resize(m_widget
); 
 895 void wxComboBox::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 897 //    gtk_widget_modify_style( GTK_COMBO(m_widget)->button, syle ); 
 899     gtk_widget_modify_style( GTK_COMBO(m_widget
)->entry
, style 
); 
 900     gtk_widget_modify_style( GTK_COMBO(m_widget
)->list
, style 
); 
 902     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 903     GList 
*child 
= list
->children
; 
 906         gtk_widget_modify_style( GTK_WIDGET(child
->data
), style 
); 
 908         GtkBin 
*bin 
= GTK_BIN(child
->data
); 
 909         gtk_widget_modify_style( bin
->child
, style 
); 
 915 GtkWidget
* wxComboBox::GetConnectWidget() 
 917     return GTK_COMBO(m_widget
)->entry
; 
 920 bool wxComboBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 922     return ( (window 
== GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
)->text_area
) || 
 923              (window 
== GTK_COMBO(m_widget
)->button
->window 
) ); 
 926 wxSize 
wxComboBox::DoGetBestSize() const 
 928     wxSize 
ret( wxControl::DoGetBestSize() ); 
 930     // we know better our horizontal extent: it depends on the longest string 
 935         unsigned int count 
= GetCount(); 
 936         for ( unsigned int n 
= 0; n 
< count
; n
++ ) 
 938             GetTextExtent(GetString(n
), &width
, NULL
, NULL
, NULL 
); 
 944     // empty combobox should have some reasonable default size too 
 954 wxComboBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 956     return GetDefaultAttributesFromGTKWidget(gtk_combo_new
, true); 
 959 // ---------------------------------------------------------------------------- 
 960 // standard event handling 
 961 // ---------------------------------------------------------------------------- 
 963 void wxComboBox::OnCut(wxCommandEvent
& WXUNUSED(event
)) 
 968 void wxComboBox::OnCopy(wxCommandEvent
& WXUNUSED(event
)) 
 973 void wxComboBox::OnPaste(wxCommandEvent
& WXUNUSED(event
)) 
 978 void wxComboBox::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
 983 void wxComboBox::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
 988 void wxComboBox::OnDelete(wxCommandEvent
& WXUNUSED(event
)) 
 991     GetSelection(& from
, & to
); 
 992     if (from 
!= -1 && to 
!= -1) 
 996 void wxComboBox::OnSelectAll(wxCommandEvent
& WXUNUSED(event
)) 
 998     SetSelection(-1, -1); 
1001 void wxComboBox::OnUpdateCut(wxUpdateUIEvent
& event
) 
1003     event
.Enable( CanCut() ); 
1006 void wxComboBox::OnUpdateCopy(wxUpdateUIEvent
& event
) 
1008     event
.Enable( CanCopy() ); 
1011 void wxComboBox::OnUpdatePaste(wxUpdateUIEvent
& event
) 
1013     event
.Enable( CanPaste() ); 
1016 void wxComboBox::OnUpdateUndo(wxUpdateUIEvent
& event
) 
1018     event
.Enable( CanUndo() ); 
1021 void wxComboBox::OnUpdateRedo(wxUpdateUIEvent
& event
) 
1023     event
.Enable( CanRedo() ); 
1026 void wxComboBox::OnUpdateDelete(wxUpdateUIEvent
& event
) 
1028     event
.Enable(HasSelection() && IsEditable()) ; 
1031 void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent
& event
) 
1033     event
.Enable(GetLastPosition() > 0);