]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/textentry.cpp
streamlining slider, scroller, spinbutton for osx carbon and cocoa
[wxWidgets.git] / src / gtk / textentry.cpp
CommitLineData
0ec1179b
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/textentry.cpp
3// Purpose: wxTextEntry implementation for wxGTK
4// Author: Vadim Zeitlin
5// Created: 2007-09-24
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
96a4cdeb
VZ
26#if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
27
0ec1179b 28#ifndef WX_PRECOMP
d290d2fe
RR
29 #include "wx/window.h"
30 #include "wx/textctrl.h"
0ec1179b
VZ
31#endif //WX_PRECOMP
32
33#include "wx/textentry.h"
34
35#include "wx/gtk/private.h"
36
37// ============================================================================
38// signal handlers implementation
39// ============================================================================
40
41extern "C"
42{
43
44// "insert_text" handler for GtkEntry
45static void
46wx_gtk_insert_text_callback(GtkEditable *editable,
e4161a2a
VZ
47 const gchar * WXUNUSED(new_text),
48 gint WXUNUSED(new_text_length),
49 gint * WXUNUSED(position),
0ec1179b
VZ
50 wxTextEntry *text)
51{
52 // we should only be called if we have a max len limit at all
53 GtkEntry *entry = GTK_ENTRY (editable);
54
55 wxCHECK_RET( entry->text_max_length, _T("shouldn't be called") );
56
57 // check that we don't overflow the max length limit
58 //
59 // FIXME: this doesn't work when we paste a string which is going to be
60 // truncated
61 if ( entry->text_length == entry->text_max_length )
62 {
63 // we don't need to run the base class version at all
64 g_signal_stop_emission_by_name (editable, "insert_text");
65
66 text->SendMaxLenEvent();
67 }
68}
69
70} // extern "C"
71
72// ============================================================================
73// wxTextEntry implementation
74// ============================================================================
75
76// ----------------------------------------------------------------------------
77// text operations
78// ----------------------------------------------------------------------------
79
80void wxTextEntry::WriteText(const wxString& value)
81{
82 GtkEditable * const edit = GetEditable();
83
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,
86 // not two
87 {
88 EventsSuppressor noevents(this);
89 gtk_editable_delete_selection(edit);
90 }
91
92 // insert new text at the cursor position
93 gint len = gtk_editable_get_position(edit);
94 gtk_editable_insert_text
95 (
96 edit,
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
100 );
101
102 // and move cursor to the end of new text
103 gtk_editable_set_position(edit, len);
104}
105
106wxString wxTextEntry::GetValue() const
107{
108 const wxGtkString value(gtk_editable_get_chars(GetEditable(), 0, -1));
109
110 return wxGTK_CONV_BACK_FONT(value, GetEditableWindow()->GetFont());
111}
112
113void wxTextEntry::Remove(long from, long to)
114{
115 gtk_editable_delete_text(GetEditable(), from, to);
116}
117
118// ----------------------------------------------------------------------------
119// clipboard operations
120// ----------------------------------------------------------------------------
121
122void wxTextEntry::Copy()
123{
124 gtk_editable_copy_clipboard(GetEditable());
125}
126
127void wxTextEntry::Cut()
128{
129 gtk_editable_cut_clipboard(GetEditable());
130}
131
132void wxTextEntry::Paste()
133{
134 gtk_editable_paste_clipboard(GetEditable());
135}
136
137// ----------------------------------------------------------------------------
138// undo/redo
139// ----------------------------------------------------------------------------
140
141void wxTextEntry::Undo()
142{
143 // TODO: not implemented
144}
145
146void wxTextEntry::Redo()
147{
148 // TODO: not implemented
149}
150
151bool wxTextEntry::CanUndo() const
152{
153 return false;
154}
155
156bool wxTextEntry::CanRedo() const
157{
158 return false;
159}
160
161// ----------------------------------------------------------------------------
162// insertion point
163// ----------------------------------------------------------------------------
164
165void wxTextEntry::SetInsertionPoint(long pos)
166{
167 gtk_editable_set_position(GetEditable(), pos);
168}
169
170long wxTextEntry::GetInsertionPoint() const
171{
172 return gtk_editable_get_position(GetEditable());
173}
174
175long wxTextEntry::GetLastPosition() const
176{
177 // this can't be implemented for arbitrary GtkEditable so only do it for
178 // GtkEntries
179 GtkEntry * const entry = GTK_ENTRY(GetEditable());
180
181 return entry ? entry->text_length : - 1;
182}
183
184// ----------------------------------------------------------------------------
185// selection
186// ----------------------------------------------------------------------------
187
188void wxTextEntry::SetSelection(long from, long to)
189{
e0721133
VZ
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 )
194 from = 0;
195
8b2e0e6d
VZ
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);
0ec1179b
VZ
200}
201
202void wxTextEntry::GetSelection(long *from, long *to) const
203{
204 gint start, end;
205 if ( gtk_editable_get_selection_bounds(GetEditable(), &start, &end) )
206 {
207 // the output must always be in order, although in GTK+ it isn't
208 if ( start > end )
209 {
210 gint tmp = start;
211 start = end;
212 end = tmp;
213 }
214 }
215 else // no selection
216 {
217 // for compatibility with MSW return the empty selection at cursor
218 start =
219 end = GetInsertionPoint();
220 }
221
222 if ( from )
223 *from = start;
224
225 if ( to )
226 *to = end;
227}
228
229// ----------------------------------------------------------------------------
ecaed0bc
VZ
230// auto completion
231// ----------------------------------------------------------------------------
232
0c3d1aa7 233bool wxTextEntry::AutoComplete(const wxArrayString& choices)
ecaed0bc
VZ
234{
235 GtkEntry * const entry = GTK_ENTRY(GetEditable());
0c3d1aa7 236 wxCHECK_MSG(entry, false, "auto completion doesn't work with this control");
ecaed0bc
VZ
237
238 GtkListStore * const store = gtk_list_store_new(1, G_TYPE_STRING);
239 GtkTreeIter iter;
240
241 for ( wxArrayString::const_iterator i = choices.begin();
242 i != choices.end();
243 ++i )
244 {
245 gtk_list_store_append(store, &iter);
246 gtk_list_store_set(store, &iter,
247 0, (const gchar *)i->utf8_str(),
248 -1);
249 }
250
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);
0c3d1aa7 256 return true;
ecaed0bc
VZ
257}
258
259// ----------------------------------------------------------------------------
0ec1179b
VZ
260// editable status
261// ----------------------------------------------------------------------------
262
263bool wxTextEntry::IsEditable() const
264{
265 return gtk_editable_get_editable(GetEditable());
266}
267
268void wxTextEntry::SetEditable(bool editable)
269{
270 gtk_editable_set_editable(GetEditable(), editable);
271}
272
273// ----------------------------------------------------------------------------
274// max text length
275// ----------------------------------------------------------------------------
276
277void wxTextEntry::SetMaxLength(unsigned long len)
278{
279 GtkEntry * const entry = GTK_ENTRY(GetEditable());
280 if ( !entry )
281 return;
282
283 gtk_entry_set_max_length(entry, len);
284
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
288 //
289 // to detect this and generate TEXT_MAXLEN event instead of TEXT_CHANGED
290 // one in this case we also catch "insert_text" signal
291 //
292 // when max len is set to 0 we disconnect our handler as it means that we
293 // shouldn't check anything any more
294 if ( len )
295 {
296 g_signal_connect
297 (
298 entry,
299 "insert_text",
300 G_CALLBACK(wx_gtk_insert_text_callback),
301 this
302 );
303 }
304 else // no max length
305 {
306 g_signal_handlers_disconnect_by_func
307 (
308 entry,
309 (gpointer)wx_gtk_insert_text_callback,
310 this
311 );
312 }
313}
314
315void wxTextEntry::SendMaxLenEvent()
316{
317 // remember that the next changed signal is to be ignored to avoid
318 // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event
319 //IgnoreNextTextUpdate();
320
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());
937013e0 325 win->HandleWindowEvent(event);
0ec1179b
VZ
326}
327
96a4cdeb 328#endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX