1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/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" 
  20     #include "wx/textctrl.h"    // for wxEVT_COMMAND_TEXT_UPDATED 
  21     #include "wx/arrstr.h" 
  25 #include "wx/gtk/private.h" 
  26 #include "wx/gtk/private/gtk2-compat.h" 
  28 // ---------------------------------------------------------------------------- 
  30 // ---------------------------------------------------------------------------- 
  34 gtkcombobox_text_changed_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  36     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
  37     event
.SetString( combo
->GetValue() ); 
  38     event
.SetEventObject( combo 
); 
  39     combo
->HandleWindowEvent( event 
); 
  43 gtkcombobox_changed_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  45     combo
->SendSelectionChangedEvent(wxEVT_COMMAND_COMBOBOX_SELECTED
); 
  49 gtkcombobox_popupshown_callback(GObject 
*WXUNUSED(gobject
), 
  50                                 GParamSpec 
*WXUNUSED(param_spec
), 
  54     g_object_get( combo
->m_widget
, "popup-shown", &isShown
, NULL 
); 
  55     wxCommandEvent 
event( isShown 
? wxEVT_COMMAND_COMBOBOX_DROPDOWN
 
  56                                   : wxEVT_COMMAND_COMBOBOX_CLOSEUP
, 
  58     event
.SetEventObject( combo 
); 
  59     combo
->HandleWindowEvent( event 
); 
  64 //----------------------------------------------------------------------------- 
  66 //----------------------------------------------------------------------------- 
  68 BEGIN_EVENT_TABLE(wxComboBox
, wxChoice
) 
  69     EVT_CHAR(wxComboBox::OnChar
) 
  71     EVT_MENU(wxID_CUT
, wxComboBox::OnCut
) 
  72     EVT_MENU(wxID_COPY
, wxComboBox::OnCopy
) 
  73     EVT_MENU(wxID_PASTE
, wxComboBox::OnPaste
) 
  74     EVT_MENU(wxID_UNDO
, wxComboBox::OnUndo
) 
  75     EVT_MENU(wxID_REDO
, wxComboBox::OnRedo
) 
  76     EVT_MENU(wxID_CLEAR
, wxComboBox::OnDelete
) 
  77     EVT_MENU(wxID_SELECTALL
, wxComboBox::OnSelectAll
) 
  79     EVT_UPDATE_UI(wxID_CUT
, wxComboBox::OnUpdateCut
) 
  80     EVT_UPDATE_UI(wxID_COPY
, wxComboBox::OnUpdateCopy
) 
  81     EVT_UPDATE_UI(wxID_PASTE
, wxComboBox::OnUpdatePaste
) 
  82     EVT_UPDATE_UI(wxID_UNDO
, wxComboBox::OnUpdateUndo
) 
  83     EVT_UPDATE_UI(wxID_REDO
, wxComboBox::OnUpdateRedo
) 
  84     EVT_UPDATE_UI(wxID_CLEAR
, wxComboBox::OnUpdateDelete
) 
  85     EVT_UPDATE_UI(wxID_SELECTALL
, wxComboBox::OnUpdateSelectAll
) 
  88 wxComboBox::~wxComboBox() 
  91         GTKDisconnect(m_entry
); 
  94 void wxComboBox::Init() 
  99 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, 
 100                          const wxString
& value
, 
 101                          const wxPoint
& pos
, const wxSize
& size
, 
 102                          const wxArrayString
& choices
, 
 103                          long style
, const wxValidator
& validator
, 
 104                          const wxString
& name 
) 
 106     wxCArrayString 
chs(choices
); 
 108     return Create( parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 109                    chs
.GetStrings(), style
, validator
, name 
); 
 112 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, const wxString
& value
, 
 113                          const wxPoint
& pos
, const wxSize
& size
, 
 114                          int n
, const wxString choices
[], 
 115                          long style
, const wxValidator
& validator
, 
 116                          const wxString
& name 
) 
 118     if (!PreCreation( parent
, pos
, size 
) || 
 119         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 121         wxFAIL_MSG( wxT("wxComboBox creation failed") ); 
 125     if (HasFlag(wxCB_SORT
)) 
 126         m_strings 
= new wxGtkCollatedArrayString(); 
 128     GTKCreateComboBoxWidget(); 
 130     if (HasFlag(wxBORDER_NONE
)) 
 132         // Doesn't seem to work 
 133         // g_object_set (m_widget, "has-frame", FALSE, NULL); 
 136     GtkEntry 
* const entry 
= GetEntry(); 
 140         // Set it up to trigger default item on enter key press 
 141         gtk_entry_set_activates_default( entry
, 
 142                                          !HasFlag(wxTE_PROCESS_ENTER
) ); 
 144         gtk_editable_set_editable(GTK_EDITABLE(entry
), true); 
 149     m_parent
->DoAddChild( this ); 
 152         m_focusWidget 
= GTK_WIDGET( entry 
); 
 158         if (style 
& wxCB_READONLY
) 
 160             // this will assert and do nothing if the value is not in our list 
 161             // of strings which is the desired behaviour (for consistency with 
 162             // wxMSW and also because it doesn't make sense to have a string 
 163             // which is not a possible choice in a read-only combobox) 
 164             SetStringSelection(value
); 
 165             gtk_editable_set_editable(GTK_EDITABLE(entry
), false); 
 167         else // editable combobox 
 169             // any value is accepted, even if it's not in our list 
 170             gtk_entry_set_text( entry
, wxGTK_CONV(value
) ); 
 173         g_signal_connect_after (entry
, "changed", 
 174                                 G_CALLBACK (gtkcombobox_text_changed_callback
), this); 
 176         GTKConnectClipboardSignals(GTK_WIDGET(entry
)); 
 179     g_signal_connect_after (m_widget
, "changed", 
 180                         G_CALLBACK (gtkcombobox_changed_callback
), this); 
 183     if ( !gtk_check_version(2,10,0) ) 
 186         g_signal_connect (m_widget
, "notify::popup-shown", 
 187                           G_CALLBACK (gtkcombobox_popupshown_callback
), this); 
 190     SetInitialSize(size
); // need this too because this is a wxControlWithItems 
 195 void wxComboBox::GTKCreateComboBoxWidget() 
 198     m_widget 
= gtk_combo_box_text_new_with_entry(); 
 200     m_widget 
= gtk_combo_box_entry_new_text(); 
 202     g_object_ref(m_widget
); 
 204     m_entry 
= GTK_ENTRY(gtk_bin_get_child(GTK_BIN(m_widget
))); 
 207 GtkEditable 
*wxComboBox::GetEditable() const 
 209     return GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(m_widget
))); 
 212 void wxComboBox::OnChar( wxKeyEvent 
&event 
) 
 214     switch ( event
.GetKeyCode() ) 
 217             if ( HasFlag(wxTE_PROCESS_ENTER
) && GetEntry() ) 
 219                 // GTK automatically selects an item if its in the list 
 220                 wxCommandEvent 
eventEnter(wxEVT_COMMAND_TEXT_ENTER
, GetId()); 
 221                 eventEnter
.SetString( GetValue() ); 
 222                 eventEnter
.SetInt( GetSelection() ); 
 223                 eventEnter
.SetEventObject( this ); 
 225                 if ( HandleWindowEvent(eventEnter
) ) 
 227                     // Catch GTK event so that GTK doesn't open the drop 
 228                     // down list upon RETURN. 
 238 void wxComboBox::EnableTextChangedEvents(bool enable
) 
 245         g_signal_handlers_unblock_by_func(gtk_bin_get_child(GTK_BIN(m_widget
)), 
 246             (gpointer
)gtkcombobox_text_changed_callback
, this); 
 250         g_signal_handlers_block_by_func(gtk_bin_get_child(GTK_BIN(m_widget
)), 
 251             (gpointer
)gtkcombobox_text_changed_callback
, this); 
 255 void wxComboBox::GTKDisableEvents() 
 257     EnableTextChangedEvents(false); 
 259     g_signal_handlers_block_by_func(m_widget
, 
 260         (gpointer
)gtkcombobox_changed_callback
, this); 
 261     g_signal_handlers_block_by_func(m_widget
, 
 262         (gpointer
)gtkcombobox_popupshown_callback
, this); 
 265 void wxComboBox::GTKEnableEvents() 
 267     EnableTextChangedEvents(true); 
 269     g_signal_handlers_unblock_by_func(m_widget
, 
 270         (gpointer
)gtkcombobox_changed_callback
, this); 
 271     g_signal_handlers_unblock_by_func(m_widget
, 
 272         (gpointer
)gtkcombobox_popupshown_callback
, this); 
 275 GtkWidget
* wxComboBox::GetConnectWidget() 
 277     return GTK_WIDGET( GetEntry() ); 
 280 GdkWindow
* wxComboBox::GTKGetWindow(wxArrayGdkWindows
& /* windows */) const 
 283     // no access to internal GdkWindows 
 286     return gtk_entry_get_text_window(GetEntry()); 
 292 wxComboBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 295     return GetDefaultAttributesFromGTKWidget(gtk_combo_box_new_with_entry
, true); 
 297     return GetDefaultAttributesFromGTKWidget(gtk_combo_box_entry_new
, true); 
 301 void wxComboBox::SetValue(const wxString
& value
) 
 303     if ( HasFlag(wxCB_READONLY
) ) 
 304         SetStringSelection(value
); 
 306         wxTextEntry::SetValue(value
); 
 309 void wxComboBox::SetString(unsigned int n
, const wxString
& text
) 
 311     wxChoice::SetString(n
, text
); 
 313     if ( static_cast<int>(n
) == GetSelection() ) 
 315         // We also need to update the currently shown text, for consistency 
 316         // with wxMSW and also because it makes sense as leaving the old string 
 317         // in the text but not in the list would be confusing to the user. 
 320         // And we need to keep the selection unchanged, modifying the item is 
 321         // not supposed to deselect it. 
 326 // ---------------------------------------------------------------------------- 
 327 // standard event handling 
 328 // ---------------------------------------------------------------------------- 
 330 void wxComboBox::OnCut(wxCommandEvent
& WXUNUSED(event
)) 
 335 void wxComboBox::OnCopy(wxCommandEvent
& WXUNUSED(event
)) 
 340 void wxComboBox::OnPaste(wxCommandEvent
& WXUNUSED(event
)) 
 345 void wxComboBox::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
 350 void wxComboBox::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
 355 void wxComboBox::OnDelete(wxCommandEvent
& WXUNUSED(event
)) 
 360 void wxComboBox::OnSelectAll(wxCommandEvent
& WXUNUSED(event
)) 
 365 void wxComboBox::OnUpdateCut(wxUpdateUIEvent
& event
) 
 367     event
.Enable( CanCut() ); 
 370 void wxComboBox::OnUpdateCopy(wxUpdateUIEvent
& event
) 
 372     event
.Enable( CanCopy() ); 
 375 void wxComboBox::OnUpdatePaste(wxUpdateUIEvent
& event
) 
 377     event
.Enable( CanPaste() ); 
 380 void wxComboBox::OnUpdateUndo(wxUpdateUIEvent
& event
) 
 382     event
.Enable( CanUndo() ); 
 385 void wxComboBox::OnUpdateRedo(wxUpdateUIEvent
& event
) 
 387     event
.Enable( CanRedo() ); 
 390 void wxComboBox::OnUpdateDelete(wxUpdateUIEvent
& event
) 
 392     event
.Enable(HasSelection() && IsEditable()) ; 
 395 void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent
& event
) 
 397     event
.Enable(!wxTextEntry::IsEmpty()); 
 400 void wxComboBox::Popup() 
 402      gtk_combo_box_popup( GTK_COMBO_BOX(m_widget
) ); 
 405 void wxComboBox::Dismiss() 
 407     gtk_combo_box_popdown( GTK_COMBO_BOX(m_widget
) ); 
 409 #endif // wxUSE_COMBOBOX