]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/textentry.cpp
Remove obsolete header used only with CodeWarrior MetroWerks compiler.
[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
385e8575
PC
55 const int text_length = gtk_entry_get_text_length(entry);
56#if GTK_CHECK_VERSION(3,0,0) || defined(GSEAL_ENABLE)
57 const int text_max_length = gtk_entry_buffer_get_max_length(gtk_entry_get_buffer(entry));
58#else
59 const int text_max_length = entry->text_max_length;
60#endif
61 wxCHECK_RET(text_max_length, "shouldn't be called");
0ec1179b
VZ
62
63 // check that we don't overflow the max length limit
64 //
65 // FIXME: this doesn't work when we paste a string which is going to be
66 // truncated
385e8575 67 if (text_length == text_max_length)
0ec1179b
VZ
68 {
69 // we don't need to run the base class version at all
70 g_signal_stop_emission_by_name (editable, "insert_text");
71
72 text->SendMaxLenEvent();
73 }
74}
75
76} // extern "C"
77
78// ============================================================================
79// wxTextEntry implementation
80// ============================================================================
81
82// ----------------------------------------------------------------------------
83// text operations
84// ----------------------------------------------------------------------------
85
86void wxTextEntry::WriteText(const wxString& value)
87{
88 GtkEditable * const edit = GetEditable();
89
90 // remove the selection if there is one and suppress the text change event
91 // generated by this: we only want to generate one event for this change,
92 // not two
93 {
94 EventsSuppressor noevents(this);
95 gtk_editable_delete_selection(edit);
96 }
97
98 // insert new text at the cursor position
99 gint len = gtk_editable_get_position(edit);
100 gtk_editable_insert_text
101 (
102 edit,
103 wxGTK_CONV_FONT(value, GetEditableWindow()->GetFont()),
104 -1, // text: length: compute it using strlen()
105 &len // will be updated to position after the text end
106 );
107
108 // and move cursor to the end of new text
109 gtk_editable_set_position(edit, len);
110}
111
135b23b2 112wxString wxTextEntry::DoGetValue() const
0ec1179b
VZ
113{
114 const wxGtkString value(gtk_editable_get_chars(GetEditable(), 0, -1));
115
ec592d7f
VZ
116 return wxGTK_CONV_BACK_FONT(value,
117 const_cast<wxTextEntry *>(this)->GetEditableWindow()->GetFont());
0ec1179b
VZ
118}
119
120void wxTextEntry::Remove(long from, long to)
121{
122 gtk_editable_delete_text(GetEditable(), from, to);
123}
124
125// ----------------------------------------------------------------------------
126// clipboard operations
127// ----------------------------------------------------------------------------
128
129void wxTextEntry::Copy()
130{
131 gtk_editable_copy_clipboard(GetEditable());
132}
133
134void wxTextEntry::Cut()
135{
136 gtk_editable_cut_clipboard(GetEditable());
137}
138
139void wxTextEntry::Paste()
140{
141 gtk_editable_paste_clipboard(GetEditable());
142}
143
144// ----------------------------------------------------------------------------
145// undo/redo
146// ----------------------------------------------------------------------------
147
148void wxTextEntry::Undo()
149{
150 // TODO: not implemented
151}
152
153void wxTextEntry::Redo()
154{
155 // TODO: not implemented
156}
157
158bool wxTextEntry::CanUndo() const
159{
160 return false;
161}
162
163bool wxTextEntry::CanRedo() const
164{
165 return false;
166}
167
168// ----------------------------------------------------------------------------
169// insertion point
170// ----------------------------------------------------------------------------
171
172void wxTextEntry::SetInsertionPoint(long pos)
173{
174 gtk_editable_set_position(GetEditable(), pos);
175}
176
177long wxTextEntry::GetInsertionPoint() const
178{
179 return gtk_editable_get_position(GetEditable());
180}
181
182long wxTextEntry::GetLastPosition() const
183{
184 // this can't be implemented for arbitrary GtkEditable so only do it for
185 // GtkEntries
186 GtkEntry * const entry = GTK_ENTRY(GetEditable());
187
385e8575 188 return entry ? gtk_entry_get_text_length(entry) : -1;
0ec1179b
VZ
189}
190
191// ----------------------------------------------------------------------------
192// selection
193// ----------------------------------------------------------------------------
194
195void wxTextEntry::SetSelection(long from, long to)
196{
e0721133
VZ
197 // in wx convention, (-1, -1) means the entire range but GTK+ translates -1
198 // (or any negative number for that matter) into last position so we need
199 // to translate manually
200 if ( from == -1 && to == -1 )
201 from = 0;
202
8b2e0e6d
VZ
203 // for compatibility with MSW, exchange from and to parameters so that the
204 // insertion point is set to the start of the selection and not its end as
205 // GTK+ does by default
206 gtk_editable_select_region(GetEditable(), to, from);
3f6439ae
PC
207
208 // avoid reported problem with RHEL 5 GTK+ 2.10 where selection is reset by
209 // a clipboard callback, see #13277
210 if (gtk_check_version(2,12,0))
211 {
212 GtkEntry* entry = GTK_ENTRY(GetEditable());
213 if (to < 0)
214 to = entry->text_length;
215 entry->selection_bound = to;
216 }
0ec1179b
VZ
217}
218
219void wxTextEntry::GetSelection(long *from, long *to) const
220{
221 gint start, end;
222 if ( gtk_editable_get_selection_bounds(GetEditable(), &start, &end) )
223 {
224 // the output must always be in order, although in GTK+ it isn't
225 if ( start > end )
226 {
227 gint tmp = start;
228 start = end;
229 end = tmp;
230 }
231 }
232 else // no selection
233 {
234 // for compatibility with MSW return the empty selection at cursor
235 start =
236 end = GetInsertionPoint();
237 }
238
239 if ( from )
240 *from = start;
241
242 if ( to )
243 *to = end;
244}
245
246// ----------------------------------------------------------------------------
ecaed0bc
VZ
247// auto completion
248// ----------------------------------------------------------------------------
249
574479e8 250bool wxTextEntry::DoAutoCompleteStrings(const wxArrayString& choices)
ecaed0bc
VZ
251{
252 GtkEntry * const entry = GTK_ENTRY(GetEditable());
0c3d1aa7 253 wxCHECK_MSG(entry, false, "auto completion doesn't work with this control");
ecaed0bc
VZ
254
255 GtkListStore * const store = gtk_list_store_new(1, G_TYPE_STRING);
256 GtkTreeIter iter;
257
258 for ( wxArrayString::const_iterator i = choices.begin();
259 i != choices.end();
260 ++i )
261 {
262 gtk_list_store_append(store, &iter);
263 gtk_list_store_set(store, &iter,
264 0, (const gchar *)i->utf8_str(),
265 -1);
266 }
267
268 GtkEntryCompletion * const completion = gtk_entry_completion_new();
269 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
270 gtk_entry_completion_set_text_column(completion, 0);
271 gtk_entry_set_completion(entry, completion);
272 g_object_unref(completion);
0c3d1aa7 273 return true;
ecaed0bc
VZ
274}
275
276// ----------------------------------------------------------------------------
0ec1179b
VZ
277// editable status
278// ----------------------------------------------------------------------------
279
280bool wxTextEntry::IsEditable() const
281{
282 return gtk_editable_get_editable(GetEditable());
283}
284
285void wxTextEntry::SetEditable(bool editable)
286{
287 gtk_editable_set_editable(GetEditable(), editable);
288}
289
290// ----------------------------------------------------------------------------
291// max text length
292// ----------------------------------------------------------------------------
293
294void wxTextEntry::SetMaxLength(unsigned long len)
295{
296 GtkEntry * const entry = GTK_ENTRY(GetEditable());
297 if ( !entry )
298 return;
299
300 gtk_entry_set_max_length(entry, len);
301
302 // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if we had
303 // tried to enter more text than allowed by max text length and the text
304 // wasn't really changed
305 //
306 // to detect this and generate TEXT_MAXLEN event instead of TEXT_CHANGED
307 // one in this case we also catch "insert_text" signal
308 //
309 // when max len is set to 0 we disconnect our handler as it means that we
310 // shouldn't check anything any more
311 if ( len )
312 {
313 g_signal_connect
314 (
315 entry,
316 "insert_text",
317 G_CALLBACK(wx_gtk_insert_text_callback),
318 this
319 );
320 }
321 else // no max length
322 {
323 g_signal_handlers_disconnect_by_func
324 (
325 entry,
326 (gpointer)wx_gtk_insert_text_callback,
327 this
328 );
329 }
330}
331
332void wxTextEntry::SendMaxLenEvent()
333{
334 // remember that the next changed signal is to be ignored to avoid
335 // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event
336 //IgnoreNextTextUpdate();
337
ec592d7f 338 wxWindow * const win = GetEditableWindow();
0ec1179b
VZ
339 wxCommandEvent event(wxEVT_COMMAND_TEXT_MAXLEN, win->GetId());
340 event.SetEventObject(win);
341 event.SetString(GetValue());
937013e0 342 win->HandleWindowEvent(event);
0ec1179b
VZ
343}
344
0847e36e
JS
345// ----------------------------------------------------------------------------
346// margins support
347// ----------------------------------------------------------------------------
348
349bool wxTextEntry::DoSetMargins(const wxPoint& margins)
350{
351#if GTK_CHECK_VERSION(2,10,0)
352 GtkEntry* entry = GetEntry();
353
354 if ( !entry )
355 return false;
356
357 const GtkBorder* oldBorder = gtk_entry_get_inner_border(entry);
358 GtkBorder* newBorder;
359
360 if ( oldBorder )
361 {
362 newBorder = gtk_border_copy(oldBorder);
363 }
364 else
365 {
366 #if GTK_CHECK_VERSION(2,14,0)
367 newBorder = gtk_border_new();
368 #else
c39b6e1e 369 newBorder = g_slice_new0(GtkBorder);
0847e36e
JS
370 #endif
371 // Use some reasonable defaults for initial margins
372 newBorder->left = 2;
373 newBorder->right = 2;
374
375 // These numbers seem to let the text remain vertically centered
376 // in common use scenarios when margins.y == -1.
377 newBorder->top = 3;
378 newBorder->bottom = 3;
379 }
380
381 if ( margins.x != -1 )
382 newBorder->left = (gint) margins.x;
383
384 if ( margins.y != -1 )
385 newBorder->top = (gint) margins.y;
386
387 gtk_entry_set_inner_border(entry, newBorder);
388
c39b6e1e
JS
389#if GTK_CHECK_VERSION(2,14,0)
390 gtk_border_free(newBorder);
391#else
392 g_slice_free(GtkBorder, newBorder);
393#endif
394
0847e36e
JS
395 return true;
396#else
397 wxUnusedVar(margins);
398 return false;
399#endif
400}
401
402wxPoint wxTextEntry::DoGetMargins() const
403{
404#if GTK_CHECK_VERSION(2,10,0)
405 GtkEntry* entry = GetEntry();
406
407 if ( !entry )
408 return wxPoint(-1, -1);
409
410 const GtkBorder* border = gtk_entry_get_inner_border(entry);
411
412 if ( !border )
413 return wxPoint(-1, -1);
414
415 return wxPoint((wxCoord) border->left, (wxCoord) border->top);
416#else
417 return wxPoint(-1, -1);
418#endif
419}
420
96a4cdeb 421#endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX