]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/textentry.cpp
Update from Hartwig for OS X implementation
[wxWidgets.git] / src / gtk / textentry.cpp
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
26 #ifndef WX_PRECOMP
27 #include "wx/window.h"
28 #include "wx/textctrl.h"
29 #endif //WX_PRECOMP
30
31 #include "wx/textentry.h"
32
33 #include "wx/gtk/private.h"
34
35 // ============================================================================
36 // signal handlers implementation
37 // ============================================================================
38
39 extern "C"
40 {
41
42 // "insert_text" handler for GtkEntry
43 static void
44 wx_gtk_insert_text_callback(GtkEditable *editable,
45 const gchar *new_text,
46 gint new_text_length,
47 gint *position,
48 wxTextEntry *text)
49 {
50 // we should only be called if we have a max len limit at all
51 GtkEntry *entry = GTK_ENTRY (editable);
52
53 wxCHECK_RET( entry->text_max_length, _T("shouldn't be called") );
54
55 // check that we don't overflow the max length limit
56 //
57 // FIXME: this doesn't work when we paste a string which is going to be
58 // truncated
59 if ( entry->text_length == entry->text_max_length )
60 {
61 // we don't need to run the base class version at all
62 g_signal_stop_emission_by_name (editable, "insert_text");
63
64 text->SendMaxLenEvent();
65 }
66 }
67
68 } // extern "C"
69
70 // ============================================================================
71 // wxTextEntry implementation
72 // ============================================================================
73
74 // ----------------------------------------------------------------------------
75 // text operations
76 // ----------------------------------------------------------------------------
77
78 void wxTextEntry::WriteText(const wxString& value)
79 {
80 GtkEditable * const edit = GetEditable();
81
82 // remove the selection if there is one and suppress the text change event
83 // generated by this: we only want to generate one event for this change,
84 // not two
85 {
86 EventsSuppressor noevents(this);
87 gtk_editable_delete_selection(edit);
88 }
89
90 // insert new text at the cursor position
91 gint len = gtk_editable_get_position(edit);
92 gtk_editable_insert_text
93 (
94 edit,
95 wxGTK_CONV_FONT(value, GetEditableWindow()->GetFont()),
96 -1, // text: length: compute it using strlen()
97 &len // will be updated to position after the text end
98 );
99
100 // and move cursor to the end of new text
101 gtk_editable_set_position(edit, len);
102 }
103
104 wxString wxTextEntry::GetValue() const
105 {
106 const wxGtkString value(gtk_editable_get_chars(GetEditable(), 0, -1));
107
108 return wxGTK_CONV_BACK_FONT(value, GetEditableWindow()->GetFont());
109 }
110
111 void wxTextEntry::Remove(long from, long to)
112 {
113 gtk_editable_delete_text(GetEditable(), from, to);
114 }
115
116 // ----------------------------------------------------------------------------
117 // clipboard operations
118 // ----------------------------------------------------------------------------
119
120 void wxTextEntry::Copy()
121 {
122 gtk_editable_copy_clipboard(GetEditable());
123 }
124
125 void wxTextEntry::Cut()
126 {
127 gtk_editable_cut_clipboard(GetEditable());
128 }
129
130 void wxTextEntry::Paste()
131 {
132 gtk_editable_paste_clipboard(GetEditable());
133 }
134
135 // ----------------------------------------------------------------------------
136 // undo/redo
137 // ----------------------------------------------------------------------------
138
139 void wxTextEntry::Undo()
140 {
141 // TODO: not implemented
142 }
143
144 void wxTextEntry::Redo()
145 {
146 // TODO: not implemented
147 }
148
149 bool wxTextEntry::CanUndo() const
150 {
151 return false;
152 }
153
154 bool wxTextEntry::CanRedo() const
155 {
156 return false;
157 }
158
159 // ----------------------------------------------------------------------------
160 // insertion point
161 // ----------------------------------------------------------------------------
162
163 void wxTextEntry::SetInsertionPoint(long pos)
164 {
165 gtk_editable_set_position(GetEditable(), pos);
166 }
167
168 long wxTextEntry::GetInsertionPoint() const
169 {
170 return gtk_editable_get_position(GetEditable());
171 }
172
173 long wxTextEntry::GetLastPosition() const
174 {
175 // this can't be implemented for arbitrary GtkEditable so only do it for
176 // GtkEntries
177 GtkEntry * const entry = GTK_ENTRY(GetEditable());
178
179 return entry ? entry->text_length : - 1;
180 }
181
182 // ----------------------------------------------------------------------------
183 // selection
184 // ----------------------------------------------------------------------------
185
186 void wxTextEntry::SetSelection(long from, long to)
187 {
188 gtk_editable_select_region(GetEditable(), from, to);
189 }
190
191 void wxTextEntry::GetSelection(long *from, long *to) const
192 {
193 gint start, end;
194 if ( gtk_editable_get_selection_bounds(GetEditable(), &start, &end) )
195 {
196 // the output must always be in order, although in GTK+ it isn't
197 if ( start > end )
198 {
199 gint tmp = start;
200 start = end;
201 end = tmp;
202 }
203 }
204 else // no selection
205 {
206 // for compatibility with MSW return the empty selection at cursor
207 start =
208 end = GetInsertionPoint();
209 }
210
211 if ( from )
212 *from = start;
213
214 if ( to )
215 *to = end;
216 }
217
218 // ----------------------------------------------------------------------------
219 // editable status
220 // ----------------------------------------------------------------------------
221
222 bool wxTextEntry::IsEditable() const
223 {
224 return gtk_editable_get_editable(GetEditable());
225 }
226
227 void wxTextEntry::SetEditable(bool editable)
228 {
229 gtk_editable_set_editable(GetEditable(), editable);
230 }
231
232 // ----------------------------------------------------------------------------
233 // max text length
234 // ----------------------------------------------------------------------------
235
236 void wxTextEntry::SetMaxLength(unsigned long len)
237 {
238 GtkEntry * const entry = GTK_ENTRY(GetEditable());
239 if ( !entry )
240 return;
241
242 gtk_entry_set_max_length(entry, len);
243
244 // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if we had
245 // tried to enter more text than allowed by max text length and the text
246 // wasn't really changed
247 //
248 // to detect this and generate TEXT_MAXLEN event instead of TEXT_CHANGED
249 // one in this case we also catch "insert_text" signal
250 //
251 // when max len is set to 0 we disconnect our handler as it means that we
252 // shouldn't check anything any more
253 if ( len )
254 {
255 g_signal_connect
256 (
257 entry,
258 "insert_text",
259 G_CALLBACK(wx_gtk_insert_text_callback),
260 this
261 );
262 }
263 else // no max length
264 {
265 g_signal_handlers_disconnect_by_func
266 (
267 entry,
268 (gpointer)wx_gtk_insert_text_callback,
269 this
270 );
271 }
272 }
273
274 void wxTextEntry::SendMaxLenEvent()
275 {
276 // remember that the next changed signal is to be ignored to avoid
277 // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event
278 //IgnoreNextTextUpdate();
279
280 wxWindow * const win = const_cast<wxWindow *>(GetEditableWindow());
281 wxCommandEvent event(wxEVT_COMMAND_TEXT_MAXLEN, win->GetId());
282 event.SetEventObject(win);
283 event.SetString(GetValue());
284 win->GetEventHandler()->ProcessEvent(event);
285 }
286