1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/textentry.cpp
3 // Purpose: wxTextEntry implementation for wxGTK
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
29 #include "wx/window.h"
30 #include "wx/textctrl.h"
33 #include "wx/textentry.h"
35 #include "wx/gtk/private.h"
37 // ============================================================================
38 // signal handlers implementation
39 // ============================================================================
44 // "insert_text" handler for GtkEntry
46 wx_gtk_insert_text_callback(GtkEditable
*editable
,
47 const gchar
* WXUNUSED(new_text
),
48 gint
WXUNUSED(new_text_length
),
49 gint
* WXUNUSED(position
),
52 // we should only be called if we have a max len limit at all
53 GtkEntry
*entry
= GTK_ENTRY (editable
);
55 wxCHECK_RET( entry
->text_max_length
, _T("shouldn't be called") );
57 // check that we don't overflow the max length limit
59 // FIXME: this doesn't work when we paste a string which is going to be
61 if ( entry
->text_length
== entry
->text_max_length
)
63 // we don't need to run the base class version at all
64 g_signal_stop_emission_by_name (editable
, "insert_text");
66 text
->SendMaxLenEvent();
72 // ============================================================================
73 // wxTextEntry implementation
74 // ============================================================================
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 void wxTextEntry::WriteText(const wxString
& value
)
82 GtkEditable
* const edit
= GetEditable();
84 // remove the selection if there is one and suppress the text change event
85 // generated by this: we only want to generate one event for this change,
88 EventsSuppressor
noevents(this);
89 gtk_editable_delete_selection(edit
);
92 // insert new text at the cursor position
93 gint len
= gtk_editable_get_position(edit
);
94 gtk_editable_insert_text
97 wxGTK_CONV_FONT(value
, GetEditableWindow()->GetFont()),
98 -1, // text: length: compute it using strlen()
99 &len
// will be updated to position after the text end
102 // and move cursor to the end of new text
103 gtk_editable_set_position(edit
, len
);
106 wxString
wxTextEntry::GetValue() const
108 const wxGtkString
value(gtk_editable_get_chars(GetEditable(), 0, -1));
110 return wxGTK_CONV_BACK_FONT(value
, GetEditableWindow()->GetFont());
113 void wxTextEntry::Remove(long from
, long to
)
115 gtk_editable_delete_text(GetEditable(), from
, to
);
118 // ----------------------------------------------------------------------------
119 // clipboard operations
120 // ----------------------------------------------------------------------------
122 void wxTextEntry::Copy()
124 gtk_editable_copy_clipboard(GetEditable());
127 void wxTextEntry::Cut()
129 gtk_editable_cut_clipboard(GetEditable());
132 void wxTextEntry::Paste()
134 gtk_editable_paste_clipboard(GetEditable());
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
141 void wxTextEntry::Undo()
143 // TODO: not implemented
146 void wxTextEntry::Redo()
148 // TODO: not implemented
151 bool wxTextEntry::CanUndo() const
156 bool wxTextEntry::CanRedo() const
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 void wxTextEntry::SetInsertionPoint(long pos
)
167 gtk_editable_set_position(GetEditable(), pos
);
170 long wxTextEntry::GetInsertionPoint() const
172 return gtk_editable_get_position(GetEditable());
175 long wxTextEntry::GetLastPosition() const
177 // this can't be implemented for arbitrary GtkEditable so only do it for
179 GtkEntry
* const entry
= GTK_ENTRY(GetEditable());
181 return entry
? entry
->text_length
: - 1;
184 // ----------------------------------------------------------------------------
186 // ----------------------------------------------------------------------------
188 void wxTextEntry::SetSelection(long from
, long to
)
190 // in wx convention, (-1, -1) means the entire range but GTK+ translates -1
191 // (or any negative number for that matter) into last position so we need
192 // to translate manually
193 if ( from
== -1 && to
== -1 )
196 // for compatibility with MSW, exchange from and to parameters so that the
197 // insertion point is set to the start of the selection and not its end as
198 // GTK+ does by default
199 gtk_editable_select_region(GetEditable(), to
, from
);
202 void wxTextEntry::GetSelection(long *from
, long *to
) const
205 if ( gtk_editable_get_selection_bounds(GetEditable(), &start
, &end
) )
207 // the output must always be in order, although in GTK+ it isn't
217 // for compatibility with MSW return the empty selection at cursor
219 end
= GetInsertionPoint();
229 // ----------------------------------------------------------------------------
231 // ----------------------------------------------------------------------------
233 bool wxTextEntry::AutoComplete(const wxArrayString
& choices
)
235 GtkEntry
* const entry
= GTK_ENTRY(GetEditable());
236 wxCHECK_MSG(entry
, false, "auto completion doesn't work with this control");
238 GtkListStore
* const store
= gtk_list_store_new(1, G_TYPE_STRING
);
241 for ( wxArrayString::const_iterator i
= choices
.begin();
245 gtk_list_store_append(store
, &iter
);
246 gtk_list_store_set(store
, &iter
,
247 0, (const gchar
*)i
->utf8_str(),
251 GtkEntryCompletion
* const completion
= gtk_entry_completion_new();
252 gtk_entry_completion_set_model(completion
, GTK_TREE_MODEL(store
));
253 gtk_entry_completion_set_text_column(completion
, 0);
254 gtk_entry_set_completion(entry
, completion
);
255 g_object_unref(completion
);
259 // ----------------------------------------------------------------------------
261 // ----------------------------------------------------------------------------
263 bool wxTextEntry::IsEditable() const
265 return gtk_editable_get_editable(GetEditable());
268 void wxTextEntry::SetEditable(bool editable
)
270 gtk_editable_set_editable(GetEditable(), editable
);
273 // ----------------------------------------------------------------------------
275 // ----------------------------------------------------------------------------
277 void wxTextEntry::SetMaxLength(unsigned long len
)
279 GtkEntry
* const entry
= GTK_ENTRY(GetEditable());
283 gtk_entry_set_max_length(entry
, len
);
285 // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if we had
286 // tried to enter more text than allowed by max text length and the text
287 // wasn't really changed
289 // to detect this and generate TEXT_MAXLEN event instead of TEXT_CHANGED
290 // one in this case we also catch "insert_text" signal
292 // when max len is set to 0 we disconnect our handler as it means that we
293 // shouldn't check anything any more
300 G_CALLBACK(wx_gtk_insert_text_callback
),
304 else // no max length
306 g_signal_handlers_disconnect_by_func
309 (gpointer
)wx_gtk_insert_text_callback
,
315 void wxTextEntry::SendMaxLenEvent()
317 // remember that the next changed signal is to be ignored to avoid
318 // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event
319 //IgnoreNextTextUpdate();
321 wxWindow
* const win
= const_cast<wxWindow
*>(GetEditableWindow());
322 wxCommandEvent
event(wxEVT_COMMAND_TEXT_MAXLEN
, win
->GetId());
323 event
.SetEventObject(win
);
324 event
.SetString(GetValue());
325 win
->HandleWindowEvent(event
);
328 #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX