1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/gtk/combobox.cpp
4
// Author: Robert Roebling
5
// Copyright: (c) 1998 Robert Roebling
6
// Licence: wxWindows licence
7
/////////////////////////////////////////////////////////////////////////////
9
// For compilers that support precompilation, includes "wx.h".
10
#include "wx/wxprec.h"
14
#include "wx/combobox.h"
18
#include "wx/settings.h"
19
#include "wx/textctrl.h" // for wxEVT_TEXT
20
#include "wx/arrstr.h"
24
#include "wx/gtk/private.h"
25
#include "wx/gtk/private/gtk2-compat.h"
27
// ----------------------------------------------------------------------------
29
// ----------------------------------------------------------------------------
33
gtkcombobox_text_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
35
wxCommandEvent event( wxEVT_TEXT, combo->GetId() );
36
event.SetString( combo->GetValue() );
37
event.SetEventObject( combo );
38
combo->HandleWindowEvent( event );
42
gtkcombobox_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
44
combo->SendSelectionChangedEvent(wxEVT_COMBOBOX);
48
gtkcombobox_popupshown_callback(GObject *WXUNUSED(gobject),
49
GParamSpec *WXUNUSED(param_spec),
53
g_object_get( combo->m_widget, "popup-shown", &isShown, NULL );
54
wxCommandEvent event( isShown ? wxEVT_COMBOBOX_DROPDOWN
55
: wxEVT_COMBOBOX_CLOSEUP,
57
event.SetEventObject( combo );
58
combo->HandleWindowEvent( event );
63
//-----------------------------------------------------------------------------
65
//-----------------------------------------------------------------------------
67
BEGIN_EVENT_TABLE(wxComboBox, wxChoice)
68
EVT_CHAR(wxComboBox::OnChar)
70
EVT_MENU(wxID_CUT, wxComboBox::OnCut)
71
EVT_MENU(wxID_COPY, wxComboBox::OnCopy)
72
EVT_MENU(wxID_PASTE, wxComboBox::OnPaste)
73
EVT_MENU(wxID_UNDO, wxComboBox::OnUndo)
74
EVT_MENU(wxID_REDO, wxComboBox::OnRedo)
75
EVT_MENU(wxID_CLEAR, wxComboBox::OnDelete)
76
EVT_MENU(wxID_SELECTALL, wxComboBox::OnSelectAll)
78
EVT_UPDATE_UI(wxID_CUT, wxComboBox::OnUpdateCut)
79
EVT_UPDATE_UI(wxID_COPY, wxComboBox::OnUpdateCopy)
80
EVT_UPDATE_UI(wxID_PASTE, wxComboBox::OnUpdatePaste)
81
EVT_UPDATE_UI(wxID_UNDO, wxComboBox::OnUpdateUndo)
82
EVT_UPDATE_UI(wxID_REDO, wxComboBox::OnUpdateRedo)
83
EVT_UPDATE_UI(wxID_CLEAR, wxComboBox::OnUpdateDelete)
84
EVT_UPDATE_UI(wxID_SELECTALL, wxComboBox::OnUpdateSelectAll)
87
wxComboBox::~wxComboBox()
90
GTKDisconnect(m_entry);
93
void wxComboBox::Init()
98
bool wxComboBox::Create( wxWindow *parent, wxWindowID id,
99
const wxString& value,
100
const wxPoint& pos, const wxSize& size,
101
const wxArrayString& choices,
102
long style, const wxValidator& validator,
103
const wxString& name )
105
wxCArrayString chs(choices);
107
return Create( parent, id, value, pos, size, chs.GetCount(),
108
chs.GetStrings(), style, validator, name );
111
bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value,
112
const wxPoint& pos, const wxSize& size,
113
int n, const wxString choices[],
114
long style, const wxValidator& validator,
115
const wxString& name )
117
if (!PreCreation( parent, pos, size ) ||
118
!CreateBase( parent, id, pos, size, style, validator, name ))
120
wxFAIL_MSG( wxT("wxComboBox creation failed") );
124
if (HasFlag(wxCB_SORT))
125
m_strings = new wxGtkCollatedArrayString();
127
GTKCreateComboBoxWidget();
129
if (HasFlag(wxBORDER_NONE))
131
// Doesn't seem to work
132
// g_object_set (m_widget, "has-frame", FALSE, NULL);
135
GtkEntry * const entry = GetEntry();
139
// Set it up to trigger default item on enter key press
140
gtk_entry_set_activates_default( entry,
141
!HasFlag(wxTE_PROCESS_ENTER) );
143
gtk_editable_set_editable(GTK_EDITABLE(entry), true);
148
m_parent->DoAddChild( this );
151
m_focusWidget = GTK_WIDGET( entry );
157
if (style & wxCB_READONLY)
159
// this will assert and do nothing if the value is not in our list
160
// of strings which is the desired behaviour (for consistency with
161
// wxMSW and also because it doesn't make sense to have a string
162
// which is not a possible choice in a read-only combobox)
163
SetStringSelection(value);
164
gtk_editable_set_editable(GTK_EDITABLE(entry), false);
166
else // editable combobox
168
// any value is accepted, even if it's not in our list
169
gtk_entry_set_text( entry, wxGTK_CONV(value) );
172
g_signal_connect_after (entry, "changed",
173
G_CALLBACK (gtkcombobox_text_changed_callback), this);
175
GTKConnectInsertTextSignal(entry);
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);
193
void wxComboBox::GTKCreateComboBoxWidget()
196
m_widget = gtk_combo_box_text_new_with_entry();
198
m_widget = gtk_combo_box_entry_new_text();
200
g_object_ref(m_widget);
202
m_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(m_widget)));
205
GtkEditable *wxComboBox::GetEditable() const
207
return GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(m_widget)));
210
void wxComboBox::OnChar( wxKeyEvent &event )
212
switch ( event.GetKeyCode() )
215
if ( HasFlag(wxTE_PROCESS_ENTER) && GetEntry() )
217
// GTK automatically selects an item if its in the list
218
wxCommandEvent eventEnter(wxEVT_TEXT_ENTER, GetId());
219
eventEnter.SetString( GetValue() );
220
eventEnter.SetInt( GetSelection() );
221
eventEnter.SetEventObject( this );
223
if ( HandleWindowEvent(eventEnter) )
225
// Catch GTK event so that GTK doesn't open the drop
226
// down list upon RETURN.
236
void wxComboBox::EnableTextChangedEvents(bool enable)
243
g_signal_handlers_unblock_by_func(gtk_bin_get_child(GTK_BIN(m_widget)),
244
(gpointer)gtkcombobox_text_changed_callback, this);
248
g_signal_handlers_block_by_func(gtk_bin_get_child(GTK_BIN(m_widget)),
249
(gpointer)gtkcombobox_text_changed_callback, this);
253
void wxComboBox::GTKDisableEvents()
255
EnableTextChangedEvents(false);
257
g_signal_handlers_block_by_func(m_widget,
258
(gpointer)gtkcombobox_changed_callback, this);
259
g_signal_handlers_block_by_func(m_widget,
260
(gpointer)gtkcombobox_popupshown_callback, this);
263
void wxComboBox::GTKEnableEvents()
265
EnableTextChangedEvents(true);
267
g_signal_handlers_unblock_by_func(m_widget,
268
(gpointer)gtkcombobox_changed_callback, this);
269
g_signal_handlers_unblock_by_func(m_widget,
270
(gpointer)gtkcombobox_popupshown_callback, this);
273
GtkWidget* wxComboBox::GetConnectWidget()
275
return GTK_WIDGET( GetEntry() );
278
GdkWindow* wxComboBox::GTKGetWindow(wxArrayGdkWindows& /* windows */) const
281
// no access to internal GdkWindows
284
return gtk_entry_get_text_window(GetEntry());
290
wxComboBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
293
return GetDefaultAttributesFromGTKWidget(gtk_combo_box_new_with_entry(), true);
295
return GetDefaultAttributesFromGTKWidget(gtk_combo_box_entry_new(), true);
299
void wxComboBox::SetValue(const wxString& value)
301
if ( HasFlag(wxCB_READONLY) )
302
SetStringSelection(value);
304
wxTextEntry::SetValue(value);
307
void wxComboBox::SetString(unsigned int n, const wxString& text)
309
wxChoice::SetString(n, text);
311
if ( static_cast<int>(n) == GetSelection() )
313
// We also need to update the currently shown text, for consistency
314
// with wxMSW and also because it makes sense as leaving the old string
315
// in the text but not in the list would be confusing to the user.
318
// And we need to keep the selection unchanged, modifying the item is
319
// not supposed to deselect it.
324
// ----------------------------------------------------------------------------
325
// standard event handling
326
// ----------------------------------------------------------------------------
328
void wxComboBox::OnCut(wxCommandEvent& WXUNUSED(event))
333
void wxComboBox::OnCopy(wxCommandEvent& WXUNUSED(event))
338
void wxComboBox::OnPaste(wxCommandEvent& WXUNUSED(event))
343
void wxComboBox::OnUndo(wxCommandEvent& WXUNUSED(event))
348
void wxComboBox::OnRedo(wxCommandEvent& WXUNUSED(event))
353
void wxComboBox::OnDelete(wxCommandEvent& WXUNUSED(event))
358
void wxComboBox::OnSelectAll(wxCommandEvent& WXUNUSED(event))
363
void wxComboBox::OnUpdateCut(wxUpdateUIEvent& event)
365
event.Enable( CanCut() );
368
void wxComboBox::OnUpdateCopy(wxUpdateUIEvent& event)
370
event.Enable( CanCopy() );
373
void wxComboBox::OnUpdatePaste(wxUpdateUIEvent& event)
375
event.Enable( CanPaste() );
378
void wxComboBox::OnUpdateUndo(wxUpdateUIEvent& event)
380
event.Enable( CanUndo() );
383
void wxComboBox::OnUpdateRedo(wxUpdateUIEvent& event)
385
event.Enable( CanRedo() );
388
void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event)
390
event.Enable(HasSelection() && IsEditable()) ;
393
void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event)
395
event.Enable(!wxTextEntry::IsEmpty());
398
void wxComboBox::Popup()
400
gtk_combo_box_popup( GTK_COMBO_BOX(m_widget) );
403
void wxComboBox::Dismiss()
405
gtk_combo_box_popdown( GTK_COMBO_BOX(m_widget) );
408
wxSize wxComboBox::DoGetSizeFromTextSize(int xlen, int ylen) const
410
wxSize tsize( wxChoice::DoGetSizeFromTextSize(xlen, ylen) );
412
GtkEntry* entry = GetEntry();
415
// Add the margins we have previously set, but only the horizontal border
416
// as vertical one has been taken account in the previous call.
417
// Also get other GTK+ margins.
418
tsize.IncBy(GTKGetEntryMargins(entry).x, 0);
424
#endif // wxUSE_COMBOBOX