25
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Port to the D programming language:
|
|
11 * Frank Benoit <benoit@tionex.de>
|
|
12 *******************************************************************************/
|
|
13 module org.eclipse.swt.widgets.Text;
|
|
14
|
|
15 import java.lang.all;
|
|
16
|
|
17
|
|
18 import org.eclipse.swt.SWT;
|
|
19 import org.eclipse.swt.internal.gtk.OS;
|
|
20 import org.eclipse.swt.graphics.Rectangle;
|
|
21 import org.eclipse.swt.events.ModifyListener;
|
|
22 import org.eclipse.swt.widgets.TypedListener;
|
|
23 import org.eclipse.swt.events.SelectionListener;
|
|
24 import org.eclipse.swt.events.SelectionEvent;
|
|
25 import org.eclipse.swt.events.VerifyListener;
|
|
26 import org.eclipse.swt.widgets.Event;
|
|
27 import org.eclipse.swt.widgets.Scrollable;
|
|
28 import org.eclipse.swt.widgets.Composite;
|
|
29
|
48
|
30 version(Tango){
|
25
|
31 static import tango.stdc.string;
|
48
|
32 } else { // Phobos
|
|
33 }
|
25
|
34
|
|
35 /**
|
|
36 * Instances of this class are selectable user interface
|
|
37 * objects that allow the user to enter and modify text.
|
|
38 * Text controls can be either single or multi-line.
|
|
39 * When a text control is created with a border, the
|
|
40 * operating system includes a platform specific inset
|
|
41 * around the contents of the control. When created
|
|
42 * without a border, an effort is made to remove the
|
|
43 * inset such that the preferred size of the control
|
|
44 * is the same size as the contents.
|
|
45 * <p>
|
|
46 * <dl>
|
|
47 * <dt><b>Styles:</b></dt>
|
|
48 * <dd>CANCEL, CENTER, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
|
|
49 * <dt><b>Events:</b></dt>
|
|
50 * <dd>DefaultSelection, Modify, Verify</dd>
|
|
51 * </dl>
|
|
52 * <p>
|
|
53 * Note: Only one of the styles MULTI and SINGLE may be specified,
|
|
54 * and only one of the styles LEFT, CENTER, and RIGHT may be specified.
|
|
55 * </p><p>
|
|
56 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
|
|
57 * </p>
|
|
58 *
|
|
59 * @see <a href="http://www.eclipse.org/swt/snippets/#text">Text snippets</a>
|
|
60 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
|
|
61 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
|
|
62 */
|
|
63 public class Text : Scrollable {
|
|
64
|
|
65 alias Scrollable.computeSize computeSize;
|
|
66 alias Scrollable.dragDetect dragDetect;
|
|
67 alias Scrollable.setBackgroundColor setBackgroundColor;
|
|
68 alias Scrollable.setCursor setCursor;
|
|
69 alias Scrollable.setOrientation setOrientation;
|
|
70 alias Scrollable.translateTraversal translateTraversal;
|
|
71
|
|
72 GtkTextBuffer* bufferHandle;
|
|
73 int tabs = 8, lastEventTime = 0;
|
|
74 GdkEventKey* gdkEventKey;
|
|
75 int fixStart = -1, fixEnd = -1;
|
|
76 bool doubleClick;
|
|
77 String message = "";
|
|
78
|
|
79 static const int INNER_BORDER = 2;
|
|
80 //static const int ITER_SIZEOF = GtkTextIter.sizeof;
|
|
81
|
|
82 /**
|
|
83 * The maximum number of characters that can be entered
|
|
84 * into a text widget.
|
|
85 * <p>
|
|
86 * Note that this value is platform dependent, based upon
|
|
87 * the native widget implementation.
|
|
88 * </p>
|
|
89 */
|
|
90 public const static int LIMIT = 0x7FFFFFFF;
|
|
91 /**
|
|
92 * The delimiter used by multi-line text widgets. When text
|
|
93 * is queried and from the widget, it will be delimited using
|
|
94 * this delimiter.
|
|
95 */
|
|
96 public const static String DELIMITER = "\n";
|
|
97 /*
|
|
98 * These values can be different on different platforms.
|
|
99 * Therefore they are not initialized in the declaration
|
|
100 * to stop the compiler from inlining.
|
|
101 */
|
|
102 // <keinfarbton> avoid static ctor
|
|
103 //static {
|
|
104 // LIMIT = 0x7FFFFFFF;
|
|
105 // DELIMITER = "\n";
|
|
106 //}
|
|
107
|
|
108 /**
|
|
109 * Constructs a new instance of this class given its parent
|
|
110 * and a style value describing its behavior and appearance.
|
|
111 * <p>
|
|
112 * The style value is either one of the style constants defined in
|
|
113 * class <code>SWT</code> which is applicable to instances of this
|
|
114 * class, or must be built by <em>bitwise OR</em>'ing together
|
|
115 * (that is, using the <code>int</code> "|" operator) two or more
|
|
116 * of those <code>SWT</code> style constants. The class description
|
|
117 * lists the style constants that are applicable to the class.
|
|
118 * Style bits are also inherited from superclasses.
|
|
119 * </p>
|
|
120 *
|
|
121 * @param parent a composite control which will be the parent of the new instance (cannot be null)
|
|
122 * @param style the style of control to construct
|
|
123 *
|
|
124 * @exception IllegalArgumentException <ul>
|
|
125 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
|
|
126 * </ul>
|
|
127 * @exception SWTException <ul>
|
|
128 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
|
|
129 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
|
|
130 * </ul>
|
|
131 *
|
|
132 * @see SWT#SINGLE
|
|
133 * @see SWT#MULTI
|
|
134 * @see SWT#READ_ONLY
|
|
135 * @see SWT#WRAP
|
|
136 * @see Widget#checkSubclass
|
|
137 * @see Widget#getStyle
|
|
138 */
|
|
139 public this (Composite parent, int style) {
|
|
140 super (parent, checkStyle (style));
|
|
141 }
|
|
142
|
|
143 static int checkStyle (int style) {
|
|
144 if ((style & SWT.SEARCH) !is 0) {
|
|
145 style |= SWT.SINGLE | SWT.BORDER;
|
|
146 style &= ~SWT.PASSWORD;
|
|
147 }
|
|
148 style &= ~SWT.SEARCH;
|
|
149 if ((style & SWT.SINGLE) !is 0 && (style & SWT.MULTI) !is 0) {
|
|
150 style &= ~SWT.MULTI;
|
|
151 }
|
|
152 style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
|
|
153 if ((style & SWT.SINGLE) !is 0) style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
|
|
154 if ((style & SWT.WRAP) !is 0) {
|
|
155 style |= SWT.MULTI;
|
|
156 style &= ~SWT.H_SCROLL;
|
|
157 }
|
|
158 if ((style & SWT.MULTI) !is 0) style &= ~SWT.PASSWORD;
|
|
159 if ((style & (SWT.SINGLE | SWT.MULTI)) !is 0) return style;
|
|
160 if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) !is 0) return style | SWT.MULTI;
|
|
161 return style | SWT.SINGLE;
|
|
162 }
|
|
163
|
|
164 override void createHandle (int index) {
|
|
165 state |= HANDLE | MENU;
|
|
166 fixedHandle = cast(GtkWidget*) OS.g_object_new (display.gtk_fixed_get_type (), null);
|
|
167 if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
168 OS.gtk_fixed_set_has_window (cast(GtkFixed*)fixedHandle, true);
|
|
169 if ((style & SWT.SINGLE) !is 0) {
|
|
170 handle = OS.gtk_entry_new ();
|
|
171 if (handle is null) error (SWT.ERROR_NO_HANDLES);
|
|
172 OS.gtk_container_add (cast(GtkContainer*)fixedHandle, handle);
|
|
173 OS.gtk_editable_set_editable (cast(GtkEditable*)handle, (style & SWT.READ_ONLY) is 0);
|
|
174 OS.gtk_entry_set_has_frame (cast(GtkEntry*)handle, (style & SWT.BORDER) !is 0);
|
|
175 OS.gtk_entry_set_visibility (cast(GtkEntry*)handle, (style & SWT.PASSWORD) is 0);
|
|
176 float alignment = 0.0f;
|
|
177 if ((style & SWT.CENTER) !is 0) alignment = 0.5f;
|
|
178 if ((style & SWT.RIGHT) !is 0) alignment = 1.0f;
|
|
179 if (alignment > 0.0f) {
|
|
180 OS.gtk_entry_set_alignment (cast(GtkEntry*)handle, alignment);
|
|
181 }
|
|
182 } else {
|
|
183 scrolledHandle = cast(GtkWidget*) OS.gtk_scrolled_window_new (null, null);
|
|
184 if (scrolledHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
185 handle = OS.gtk_text_view_new ();
|
|
186 if (handle is null) error (SWT.ERROR_NO_HANDLES);
|
|
187 bufferHandle = OS.gtk_text_view_get_buffer (cast(GtkTextView*)handle);
|
|
188 if (bufferHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
189 OS.gtk_container_add (cast(GtkContainer*)fixedHandle, scrolledHandle);
|
|
190 OS.gtk_container_add (cast(GtkContainer*)scrolledHandle, handle);
|
|
191 OS.gtk_text_view_set_editable (cast(GtkTextView*)handle, (style & SWT.READ_ONLY) is 0);
|
|
192 if ((style & SWT.WRAP) !is 0) OS.gtk_text_view_set_wrap_mode (cast(GtkTextView*)handle, OS.GTK_WRAP_WORD_CHAR);
|
|
193 int hsp = (style & SWT.H_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
|
|
194 int vsp = (style & SWT.V_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
|
|
195 OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp);
|
|
196 if ((style & SWT.BORDER) !is 0) {
|
|
197 OS.gtk_scrolled_window_set_shadow_type (cast(GtkScrolledWindow*)scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
|
|
198 }
|
|
199 int just = OS.GTK_JUSTIFY_LEFT;
|
|
200 if ((style & SWT.CENTER) !is 0) just = OS.GTK_JUSTIFY_CENTER;
|
|
201 if ((style & SWT.RIGHT) !is 0) just = OS.GTK_JUSTIFY_RIGHT;
|
|
202 OS.gtk_text_view_set_justification (cast(GtkTextView*)handle, just);
|
|
203 }
|
|
204 }
|
|
205
|
|
206 override void createWidget (int index) {
|
|
207 super.createWidget (index);
|
|
208 doubleClick = true;
|
|
209 }
|
|
210
|
|
211 /**
|
|
212 * Adds the listener to the collection of listeners who will
|
|
213 * be notified when the receiver's text is modified, by sending
|
|
214 * it one of the messages defined in the <code>ModifyListener</code>
|
|
215 * interface.
|
|
216 *
|
|
217 * @param listener the listener which should be notified
|
|
218 *
|
|
219 * @exception IllegalArgumentException <ul>
|
|
220 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
221 * </ul>
|
|
222 * @exception SWTException <ul>
|
|
223 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
224 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
225 * </ul>
|
|
226 *
|
|
227 * @see ModifyListener
|
|
228 * @see #removeModifyListener
|
|
229 */
|
|
230 public void addModifyListener (ModifyListener listener) {
|
|
231 checkWidget ();
|
|
232 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
233 TypedListener typedListener = new TypedListener (listener);
|
|
234 addListener (SWT.Modify, typedListener);
|
|
235 }
|
|
236
|
|
237 /**
|
|
238 * Adds the listener to the collection of listeners who will
|
|
239 * be notified when the control is selected by the user, by sending
|
|
240 * it one of the messages defined in the <code>SelectionListener</code>
|
|
241 * interface.
|
|
242 * <p>
|
|
243 * <code>widgetSelected</code> is not called for texts.
|
|
244 * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text,
|
|
245 * or when ENTER is pressed in a search text. If the receiver has the <code>SWT.SEARCH | SWT.CANCEL</code> style
|
|
246 * and the user cancels the search, the event object detail field contains the value <code>SWT.CANCEL</code>.
|
|
247 * </p>
|
|
248 *
|
|
249 * @param listener the listener which should be notified when the control is selected by the user
|
|
250 *
|
|
251 * @exception IllegalArgumentException <ul>
|
|
252 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
253 * </ul>
|
|
254 * @exception SWTException <ul>
|
|
255 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
256 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
257 * </ul>
|
|
258 *
|
|
259 * @see SelectionListener
|
|
260 * @see #removeSelectionListener
|
|
261 * @see SelectionEvent
|
|
262 */
|
|
263 public void addSelectionListener(SelectionListener listener) {
|
|
264 checkWidget ();
|
|
265 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
266 TypedListener typedListener = new TypedListener(listener);
|
|
267 addListener(SWT.Selection,typedListener);
|
|
268 addListener(SWT.DefaultSelection,typedListener);
|
|
269 }
|
|
270
|
|
271 /**
|
|
272 * Adds the listener to the collection of listeners who will
|
|
273 * be notified when the receiver's text is verified, by sending
|
|
274 * it one of the messages defined in the <code>VerifyListener</code>
|
|
275 * interface.
|
|
276 *
|
|
277 * @param listener the listener which should be notified
|
|
278 *
|
|
279 * @exception IllegalArgumentException <ul>
|
|
280 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
281 * </ul>
|
|
282 * @exception SWTException <ul>
|
|
283 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
284 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
285 * </ul>
|
|
286 *
|
|
287 * @see VerifyListener
|
|
288 * @see #removeVerifyListener
|
|
289 */
|
|
290 public void addVerifyListener (VerifyListener listener) {
|
|
291 checkWidget();
|
|
292 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
293 TypedListener typedListener = new TypedListener (listener);
|
|
294 addListener (SWT.Verify, typedListener);
|
|
295 }
|
|
296
|
|
297 /**
|
|
298 * Appends a string.
|
|
299 * <p>
|
|
300 * The new text is appended to the text at
|
|
301 * the end of the widget.
|
|
302 * </p>
|
|
303 *
|
|
304 * @param string the string to be appended
|
|
305 *
|
|
306 * @exception SWTException <ul>
|
|
307 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
308 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
309 * </ul>
|
|
310 */
|
|
311 public void append (String string) {
|
|
312 checkWidget ();
|
|
313 // SWT extension: allow null for zero length string
|
|
314 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
315 if ((style & SWT.SINGLE) !is 0) {
|
|
316 int dummy = -1;
|
|
317 OS.gtk_editable_insert_text (cast(GtkEditable*)handle, string.ptr, string.length, &dummy );
|
|
318 OS.gtk_editable_set_position (cast(GtkEditable*)handle, -1);
|
|
319 } else {
|
|
320 GtkTextIter position;
|
|
321 OS.gtk_text_buffer_get_end_iter (bufferHandle, &position);
|
|
322 OS.gtk_text_buffer_insert (bufferHandle, &position, string.ptr, string.length);
|
|
323 OS.gtk_text_buffer_place_cursor (bufferHandle, &position);
|
|
324 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
325 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
326 }
|
|
327 }
|
|
328
|
|
329 /**
|
|
330 * Clears the selection.
|
|
331 *
|
|
332 * @exception SWTException <ul>
|
|
333 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
334 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
335 * </ul>
|
|
336 */
|
|
337 public void clearSelection () {
|
|
338 checkWidget ();
|
|
339 if ((style & SWT.SINGLE) !is 0) {
|
|
340 int position = OS.gtk_editable_get_position (cast(GtkEditable*)handle);
|
|
341 OS.gtk_editable_select_region (cast(GtkEditable*)handle, position, position);
|
|
342 } else {
|
|
343 GtkTextIter position;
|
|
344 auto insertMark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
345 auto selectionMark = OS.gtk_text_buffer_get_selection_bound (bufferHandle);
|
|
346 OS.gtk_text_buffer_get_iter_at_mark (bufferHandle, &position, insertMark);
|
|
347 OS.gtk_text_buffer_move_mark (bufferHandle, selectionMark, &position);
|
|
348 OS.gtk_text_buffer_move_mark (bufferHandle, insertMark, &position);
|
|
349 }
|
|
350 }
|
|
351
|
|
352 override public Point computeSize (int wHint, int hHint, bool changed) {
|
|
353 checkWidget ();
|
|
354 if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0;
|
|
355 if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0;
|
|
356 int w , h;
|
|
357 if ((style & SWT.SINGLE) !is 0) {
|
|
358 OS.gtk_widget_realize (handle);
|
|
359 auto layout = OS.gtk_entry_get_layout (cast(GtkEntry*)handle);
|
|
360 OS.pango_layout_get_size (layout, &w, &h);
|
|
361 } else {
|
|
362 GtkTextIter start;
|
|
363 GtkTextIter end;
|
|
364 OS.gtk_text_buffer_get_bounds (bufferHandle, &start, &end);
|
|
365 auto text = OS.gtk_text_buffer_get_text (bufferHandle, &start, &end, true);
|
|
366 auto layout = OS.gtk_widget_create_pango_layout (handle, text);
|
|
367 OS.g_free (text);
|
|
368 OS.pango_layout_set_width (layout, wHint * OS.PANGO_SCALE);
|
|
369 OS.pango_layout_get_size (layout, &w, &h);
|
|
370 OS.g_object_unref (layout);
|
|
371 }
|
|
372 int width = OS.PANGO_PIXELS (w);
|
|
373 int height = OS.PANGO_PIXELS (h);
|
|
374 //This code is intentionally commented
|
|
375 // if ((style & SWT.SEARCH) !is 0 && message.length () !is 0) {
|
|
376 // GC gc = new GC (this);
|
|
377 // Point size = gc.stringExtent (message);
|
|
378 // width = Math.max (width, size.x);
|
|
379 // gc.dispose ();
|
|
380 // }
|
|
381 if (width is 0) width = DEFAULT_WIDTH;
|
|
382 if (height is 0) height = DEFAULT_HEIGHT;
|
|
383 width = wHint is SWT.DEFAULT ? width : wHint;
|
|
384 height = hHint is SWT.DEFAULT ? height : hHint;
|
|
385 Rectangle trim = computeTrim (0, 0, width, height);
|
|
386 return new Point (trim.width, trim.height);
|
|
387 }
|
|
388
|
|
389 override public Rectangle computeTrim (int x, int y, int width, int height) {
|
|
390 checkWidget ();
|
|
391 Rectangle trim = super.computeTrim (x, y, width, height);
|
|
392 int xborder = 0, yborder = 0;
|
|
393 if ((style & SWT.SINGLE) !is 0) {
|
|
394 if ((style & SWT.BORDER) !is 0) {
|
|
395 auto style = OS.gtk_widget_get_style (handle);
|
|
396 xborder += OS.gtk_style_get_xthickness (style);
|
|
397 yborder += OS.gtk_style_get_ythickness (style);
|
|
398 }
|
|
399 xborder += INNER_BORDER;
|
|
400 yborder += INNER_BORDER;
|
|
401 } else {
|
|
402 int borderWidth = OS.gtk_container_get_border_width (cast(GtkContainer*)handle);
|
|
403 xborder += borderWidth;
|
|
404 yborder += borderWidth;
|
|
405 }
|
|
406 int property;
|
|
407 OS.gtk_widget_style_get1 (handle, OS.interior_focus.ptr, &property);
|
|
408 if (property is 0) {
|
|
409 OS.gtk_widget_style_get1 (handle, OS.focus_line_width.ptr, &property);
|
|
410 xborder += property;
|
|
411 yborder += property;
|
|
412 }
|
|
413 trim.x -= xborder;
|
|
414 trim.y -= yborder;
|
|
415 trim.width += 2 * xborder;
|
|
416 trim.height += 2 * yborder;
|
|
417 return new Rectangle (trim.x, trim.y, trim.width, trim.height);
|
|
418 }
|
|
419
|
|
420 /**
|
|
421 * Copies the selected text.
|
|
422 * <p>
|
|
423 * The current selection is copied to the clipboard.
|
|
424 * </p>
|
|
425 *
|
|
426 * @exception SWTException <ul>
|
|
427 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
428 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
429 * </ul>
|
|
430 */
|
|
431 public void copy () {
|
|
432 checkWidget ();
|
|
433 if ((style & SWT.SINGLE) !is 0) {
|
|
434 OS.gtk_editable_copy_clipboard (cast(GtkEditable*)handle);
|
|
435 } else {
|
|
436 auto clipboard = OS.gtk_clipboard_get (cast(void*)OS.GDK_NONE);
|
|
437 OS.gtk_text_buffer_copy_clipboard (bufferHandle, clipboard);
|
|
438 }
|
|
439 }
|
|
440
|
|
441 /**
|
|
442 * Cuts the selected text.
|
|
443 * <p>
|
|
444 * The current selection is first copied to the
|
|
445 * clipboard and then deleted from the widget.
|
|
446 * </p>
|
|
447 *
|
|
448 * @exception SWTException <ul>
|
|
449 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
450 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
451 * </ul>
|
|
452 */
|
|
453 public void cut () {
|
|
454 checkWidget ();
|
|
455 if ((style & SWT.SINGLE) !is 0) {
|
|
456 OS.gtk_editable_cut_clipboard (cast(GtkEditable*)handle);
|
|
457 } else {
|
|
458 auto clipboard = OS.gtk_clipboard_get (cast(void*)OS.GDK_NONE);
|
|
459 OS.gtk_text_buffer_cut_clipboard (bufferHandle, clipboard, OS.gtk_text_view_get_editable (cast(GtkTextView*)handle));
|
|
460 }
|
|
461 }
|
|
462
|
|
463 override void deregister () {
|
|
464 super.deregister ();
|
|
465 if (bufferHandle !is null) display.removeWidget (cast(GtkWidget*)bufferHandle);
|
|
466 auto imContext = imContext ();
|
|
467 if (imContext !is null) display.removeWidget (cast(GtkWidget*)imContext);
|
|
468 }
|
|
469
|
|
470 override bool dragDetect (int x, int y, bool filter, bool* consume) {
|
|
471 if (filter) {
|
|
472 int start = 0, end = 0;
|
|
473 if ((style & SWT.SINGLE) !is 0) {
|
|
474 int s, e;
|
|
475 OS.gtk_editable_get_selection_bounds (cast(GtkEditable*)handle, &s, &e);
|
|
476 start = s;
|
|
477 end = e;
|
|
478 } else {
|
|
479 GtkTextIter s;
|
|
480 GtkTextIter e;
|
|
481 OS.gtk_text_buffer_get_selection_bounds (bufferHandle, &s, &e);
|
|
482 start = OS.gtk_text_iter_get_offset (&s);
|
|
483 end = OS.gtk_text_iter_get_offset (&e);
|
|
484 }
|
|
485 if (start !is end) {
|
|
486 if (end < start) {
|
|
487 int temp = end;
|
|
488 end = start;
|
|
489 start = temp;
|
|
490 }
|
|
491 int position = -1;
|
|
492 if ((style & SWT.SINGLE) !is 0) {
|
|
493 int index;
|
|
494 int trailing;
|
|
495 auto layout = OS.gtk_entry_get_layout (cast(GtkEntry*)handle);
|
|
496 OS.pango_layout_xy_to_index (layout, x * OS.PANGO_SCALE, y * OS.PANGO_SCALE, &index, &trailing);
|
|
497 auto ptr = OS.pango_layout_get_text (layout);
|
|
498 position = cast(int)/*64*/OS.g_utf8_pointer_to_offset (ptr, ptr + index) + trailing;
|
|
499 } else {
|
|
500 GtkTextIter p;
|
|
501 OS.gtk_text_view_get_iter_at_location (cast(GtkTextView*)handle, &p, x, y);
|
|
502 position = OS.gtk_text_iter_get_offset (&p);
|
|
503 }
|
|
504 if (start <= position && position < end) {
|
|
505 if (super.dragDetect (x, y, filter, consume)) {
|
|
506 if (consume !is null) consume [0] = true;
|
|
507 return true;
|
|
508 }
|
|
509 }
|
|
510 }
|
|
511 return false;
|
|
512 }
|
|
513 return super.dragDetect (x, y, filter, consume);
|
|
514 }
|
|
515
|
|
516 override GdkDrawable* eventWindow () {
|
|
517 return paintWindow ();
|
|
518 }
|
|
519
|
|
520 override bool filterKey (int keyval, GdkEventKey* event) {
|
|
521 int time = OS.gdk_event_get_time (cast(GdkEvent*)event);
|
|
522 if (time !is lastEventTime) {
|
|
523 lastEventTime = time;
|
|
524 auto imContext = imContext ();
|
|
525 if (imContext !is null) {
|
|
526 return cast(bool)OS.gtk_im_context_filter_keypress (imContext, event);
|
|
527 }
|
|
528 }
|
|
529 gdkEventKey = event;
|
|
530 return false;
|
|
531 }
|
|
532
|
|
533 void fixIM () {
|
|
534 /*
|
|
535 * The IM filter has to be called one time for each key press event.
|
|
536 * When the IM is open the key events are duplicated. The first event
|
|
537 * is filtered by SWT and the second event is filtered by GTK. In some
|
|
538 * cases the GTK handler does not run (the widget is destroyed, the
|
|
539 * application code consumes the event, etc), for these cases the IM
|
|
540 * filter has to be called by SWT.
|
|
541 */
|
|
542 if (gdkEventKey !is null && gdkEventKey !is cast(GdkEventKey*)-1) {
|
|
543 auto imContext = imContext ();
|
|
544 if (imContext !is null) {
|
|
545 OS.gtk_im_context_filter_keypress (imContext, gdkEventKey);
|
|
546 gdkEventKey = cast(GdkEventKey*)-1;
|
|
547 return;
|
|
548 }
|
|
549 }
|
|
550 gdkEventKey = null;
|
|
551 }
|
|
552
|
|
553 override GdkColor* getBackgroundColor () {
|
|
554 return getBaseColor ();
|
|
555 }
|
|
556
|
|
557 public override int getBorderWidth () {
|
|
558 checkWidget();
|
|
559 if ((style & SWT.MULTI) !is 0) return super.getBorderWidth ();
|
|
560 auto style = OS.gtk_widget_get_style (handle);
|
|
561 if ((this.style & SWT.BORDER) !is 0) {
|
|
562 return OS.gtk_style_get_xthickness (style);
|
|
563 }
|
|
564 return 0;
|
|
565 }
|
|
566
|
|
567 /**
|
|
568 * Returns the line number of the caret.
|
|
569 * <p>
|
|
570 * The line number of the caret is returned.
|
|
571 * </p>
|
|
572 *
|
|
573 * @return the line number
|
|
574 *
|
|
575 * @exception SWTException <ul>
|
|
576 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
577 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
578 * </ul>
|
|
579 */
|
|
580 public int getCaretLineNumber () {
|
|
581 checkWidget ();
|
|
582 if ((style & SWT.SINGLE) !is 0) return 1;
|
|
583 GtkTextIter position;
|
|
584 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
585 OS.gtk_text_buffer_get_iter_at_mark (bufferHandle, &position, mark);
|
|
586 return OS.gtk_text_iter_get_line (&position);
|
|
587 }
|
|
588
|
|
589 /**
|
|
590 * Returns a point describing the receiver's location relative
|
|
591 * to its parent (or its display if its parent is null).
|
|
592 * <p>
|
|
593 * The location of the caret is returned.
|
|
594 * </p>
|
|
595 *
|
|
596 * @return a point, the location of the caret
|
|
597 *
|
|
598 * @exception SWTException <ul>
|
|
599 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
600 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
601 * </ul>
|
|
602 */
|
|
603 public Point getCaretLocation () {
|
|
604 checkWidget ();
|
|
605 if ((style & SWT.SINGLE) !is 0) {
|
|
606 int index = OS.gtk_editable_get_position (cast(GtkEditable*)handle);
|
|
607 if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 0)) {
|
|
608 index = OS.gtk_entry_text_index_to_layout_index (cast(GtkEntry*)handle, index);
|
|
609 }
|
|
610 int offset_x, offset_y;
|
|
611 OS.gtk_entry_get_layout_offsets (cast(GtkEntry*)handle, &offset_x, &offset_y);
|
|
612 auto layout = OS.gtk_entry_get_layout (cast(GtkEntry*)handle);
|
|
613 PangoRectangle pos;
|
|
614 OS.pango_layout_index_to_pos (layout, index, &pos);
|
|
615 int x = offset_x + OS.PANGO_PIXELS (pos.x) - getBorderWidth ();
|
|
616 int y = offset_y + OS.PANGO_PIXELS (pos.y);
|
|
617 return new Point (x, y);
|
|
618 }
|
|
619 GtkTextIter position;
|
|
620 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
621 OS.gtk_text_buffer_get_iter_at_mark (bufferHandle, &position, mark);
|
|
622 GdkRectangle rect;
|
|
623 OS.gtk_text_view_get_iter_location (cast(GtkTextView*)handle, &position, &rect);
|
|
624 int x;
|
|
625 int y;
|
|
626 OS.gtk_text_view_buffer_to_window_coords (cast(GtkTextView*)handle, OS.GTK_TEXT_WINDOW_TEXT, rect.x, rect.y, &x, &y);
|
|
627 return new Point (x, y);
|
|
628 }
|
|
629
|
|
630 /**
|
|
631 * Returns the character position of the caret.
|
|
632 * <p>
|
|
633 * Indexing is zero based.
|
|
634 * </p>
|
|
635 *
|
|
636 * @return the position of the caret
|
|
637 *
|
|
638 * @exception SWTException <ul>
|
|
639 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
640 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
641 * </ul>
|
|
642 */
|
|
643 public int getCaretPosition () {
|
|
644 checkWidget ();
|
|
645 if ((style & SWT.SINGLE) !is 0) {
|
|
646 return OS.gtk_editable_get_position (cast(GtkEditable*)handle);
|
|
647 }
|
|
648 GtkTextIter position;
|
|
649 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
650 OS.gtk_text_buffer_get_iter_at_mark (bufferHandle, &position, mark);
|
|
651 return OS.gtk_text_iter_get_offset (&position);
|
|
652 }
|
|
653
|
|
654 /**
|
|
655 * Returns the number of characters.
|
|
656 *
|
|
657 * @return number of characters in the widget
|
|
658 *
|
|
659 * @exception SWTException <ul>
|
|
660 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
661 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
662 * </ul>
|
|
663 */
|
|
664 public int getCharCount () {
|
|
665 checkWidget ();
|
|
666 if ((style & SWT.SINGLE) !is 0) {
|
|
667 auto ptr = OS.gtk_entry_get_text (cast(GtkEntry*)handle);
|
|
668 return cast(int)/*64*/OS.g_utf8_strlen (ptr, -1);
|
|
669 }
|
|
670 return OS.gtk_text_buffer_get_char_count (bufferHandle);
|
|
671 }
|
|
672
|
|
673 /**
|
|
674 * Returns the double click enabled flag.
|
|
675 * <p>
|
|
676 * The double click flag enables or disables the
|
|
677 * default action of the text widget when the user
|
|
678 * double clicks.
|
|
679 * </p>
|
|
680 *
|
|
681 * @return whether or not double click is enabled
|
|
682 *
|
|
683 * @exception SWTException <ul>
|
|
684 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
685 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
686 * </ul>
|
|
687 */
|
|
688 public bool getDoubleClickEnabled () {
|
|
689 checkWidget ();
|
|
690 return doubleClick;
|
|
691 }
|
|
692
|
|
693 /**
|
|
694 * Returns the echo character.
|
|
695 * <p>
|
|
696 * The echo character is the character that is
|
|
697 * displayed when the user enters text or the
|
|
698 * text is changed by the programmer.
|
|
699 * </p>
|
|
700 *
|
|
701 * @return the echo character
|
|
702 *
|
|
703 * @exception SWTException <ul>
|
|
704 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
705 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
706 * </ul>
|
|
707 *
|
|
708 * @see #setEchoChar
|
|
709 */
|
|
710 public char getEchoChar () {
|
|
711 checkWidget ();
|
|
712 if ((style & SWT.SINGLE) !is 0) {
|
|
713 if (!OS.gtk_entry_get_visibility (cast(GtkEntry*)handle)) {
|
|
714 return OS.gtk_entry_get_invisible_char (cast(GtkEntry*)handle);
|
|
715 }
|
|
716 }
|
|
717 return '\0';
|
|
718 }
|
|
719
|
|
720 /**
|
|
721 * Returns the editable state.
|
|
722 *
|
|
723 * @return whether or not the receiver is editable
|
|
724 *
|
|
725 * @exception SWTException <ul>
|
|
726 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
727 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
728 * </ul>
|
|
729 */
|
|
730 public bool getEditable () {
|
|
731 checkWidget ();
|
|
732 if ((style & SWT.SINGLE) !is 0) {
|
|
733 return cast(bool)OS.gtk_editable_get_editable (cast(GtkEditable*)handle);
|
|
734 }
|
|
735 return cast(bool)OS.gtk_text_view_get_editable (cast(GtkTextView*)handle);
|
|
736 }
|
|
737
|
|
738 override GdkColor* getForegroundColor () {
|
|
739 return getTextColor ();
|
|
740 }
|
|
741
|
|
742 /**
|
|
743 * Returns the number of lines.
|
|
744 *
|
|
745 * @return the number of lines in the widget
|
|
746 *
|
|
747 * @exception SWTException <ul>
|
|
748 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
749 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
750 * </ul>
|
|
751 */
|
|
752 public int getLineCount () {
|
|
753 checkWidget ();
|
|
754 if ((style & SWT.SINGLE) !is 0) return 1;
|
|
755 return OS.gtk_text_buffer_get_line_count (bufferHandle);
|
|
756 }
|
|
757
|
|
758 /**
|
|
759 * Returns the line delimiter.
|
|
760 *
|
|
761 * @return a string that is the line delimiter
|
|
762 *
|
|
763 * @exception SWTException <ul>
|
|
764 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
765 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
766 * </ul>
|
|
767 *
|
|
768 * @see #DELIMITER
|
|
769 */
|
|
770 public String getLineDelimiter () {
|
|
771 checkWidget ();
|
|
772 return "\n";
|
|
773 }
|
|
774
|
|
775 /**
|
|
776 * Returns the height of a line.
|
|
777 *
|
|
778 * @return the height of a row of text
|
|
779 *
|
|
780 * @exception SWTException <ul>
|
|
781 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
782 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
783 * </ul>
|
|
784 */
|
|
785 public int getLineHeight () {
|
|
786 checkWidget ();
|
|
787 return fontHeight (getFontDescription (), handle);
|
|
788 }
|
|
789
|
|
790 /**
|
|
791 * Returns the widget message. When the widget is created
|
|
792 * with the style <code>SWT.SEARCH</code>, the message text
|
|
793 * is displayed as a hint for the user, indicating the
|
|
794 * purpose of the field.
|
|
795 * <p>
|
|
796 * Note: This operation is a <em>HINT</em> and is not
|
|
797 * supported on platforms that do not have this concept.
|
|
798 * </p>
|
|
799 *
|
|
800 * @return the widget message
|
|
801 *
|
|
802 * @exception SWTException <ul>
|
|
803 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
804 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
805 * </ul>
|
|
806 *
|
|
807 * @since 3.3
|
|
808 */
|
|
809 public String getMessage () {
|
|
810 checkWidget ();
|
|
811 return message;
|
|
812 }
|
|
813
|
|
814 /**
|
|
815 * Returns the orientation of the receiver, which will be one of the
|
|
816 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
|
|
817 *
|
|
818 * @return the orientation style
|
|
819 *
|
|
820 * @exception SWTException <ul>
|
|
821 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
822 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
823 * </ul>
|
|
824 *
|
|
825 * @since 2.1.2
|
|
826 */
|
|
827 public int getOrientation () {
|
|
828 checkWidget();
|
|
829 return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
|
|
830 }
|
|
831
|
|
832 /*public*/ int getPosition (Point point) {
|
|
833 checkWidget ();
|
|
834 if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
835 int position = -1;
|
|
836 if ((style & SWT.SINGLE) !is 0) {
|
|
837 int index;
|
|
838 int trailing;
|
|
839 auto layout = OS.gtk_entry_get_layout (cast(GtkEntry*)handle);
|
|
840 OS.pango_layout_xy_to_index (layout, point.x * OS.PANGO_SCALE, point.y * OS.PANGO_SCALE, &index, &trailing);
|
|
841 auto ptr = OS.pango_layout_get_text (layout);
|
|
842 position = cast(int)/*64*/OS.g_utf8_pointer_to_offset (ptr, ptr + index) + trailing;
|
|
843 } else {
|
|
844 GtkTextIter p;
|
|
845 OS.gtk_text_view_get_iter_at_location (cast(GtkTextView*)handle, &p, point.x, point.y);
|
|
846 position = OS.gtk_text_iter_get_offset (&p);
|
|
847 }
|
|
848 return position;
|
|
849 }
|
|
850
|
|
851 /**
|
|
852 * Returns a <code>Point</code> whose x coordinate is the
|
|
853 * character position representing the start of the selected
|
|
854 * text, and whose y coordinate is the character position
|
|
855 * representing the end of the selection. An "empty" selection
|
|
856 * is indicated by the x and y coordinates having the same value.
|
|
857 * <p>
|
|
858 * Indexing is zero based. The range of a selection is from
|
|
859 * 0..N where N is the number of characters in the widget.
|
|
860 * </p>
|
|
861 *
|
|
862 * @return a point representing the selection start and end
|
|
863 *
|
|
864 * @exception SWTException <ul>
|
|
865 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
866 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
867 * </ul>
|
|
868 */
|
|
869 public Point getSelection () {
|
|
870 checkWidget ();
|
|
871 if ((style & SWT.SINGLE) !is 0) {
|
|
872 int start;
|
|
873 int end;
|
|
874 OS.gtk_editable_get_selection_bounds (cast(GtkEditable*)handle, &start, &end);
|
|
875 return new Point (start, end);
|
|
876 }
|
|
877 GtkTextIter start;
|
|
878 GtkTextIter end;
|
|
879 OS.gtk_text_buffer_get_selection_bounds (bufferHandle, &start, &end);
|
|
880 return new Point (OS.gtk_text_iter_get_offset (&start), OS.gtk_text_iter_get_offset (&end));
|
|
881 }
|
|
882
|
|
883 /**
|
|
884 * Returns the number of selected characters.
|
|
885 *
|
|
886 * @return the number of selected characters.
|
|
887 *
|
|
888 * @exception SWTException <ul>
|
|
889 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
890 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
891 * </ul>
|
|
892 */
|
|
893 public int getSelectionCount () {
|
|
894 checkWidget ();
|
|
895 Point selection = getSelection ();
|
|
896 return Math.abs (selection.y - selection.x);
|
|
897 }
|
|
898
|
|
899 /**
|
|
900 * Gets the selected text, or an empty string if there is no current selection.
|
|
901 *
|
|
902 * @return the selected text
|
|
903 *
|
|
904 * @exception SWTException <ul>
|
|
905 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
906 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
907 * </ul>
|
|
908 */
|
|
909 public String getSelectionText () {
|
|
910 checkWidget ();
|
|
911 Point selection = getSelection ();
|
|
912 return getText ()[ selection.x .. selection.y ];
|
|
913 }
|
|
914
|
|
915 /**
|
|
916 * Returns the number of tabs.
|
|
917 * <p>
|
|
918 * Tab stop spacing is specified in terms of the
|
|
919 * space (' ') character. The width of a single
|
|
920 * tab stop is the pixel width of the spaces.
|
|
921 * </p>
|
|
922 *
|
|
923 * @return the number of tab characters
|
|
924 *
|
|
925 * @exception SWTException <ul>
|
|
926 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
927 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
928 * </ul>
|
|
929 */
|
|
930 public int getTabs () {
|
|
931 checkWidget ();
|
|
932 return tabs;
|
|
933 }
|
|
934
|
|
935 int getTabWidth (int tabs) {
|
|
936 auto layout = OS.gtk_widget_create_pango_layout (handle, " ".ptr );
|
|
937 int width;
|
|
938 int height;
|
|
939 OS.pango_layout_get_size (layout, &width, &height);
|
|
940 OS.g_object_unref (layout);
|
|
941 return width * tabs;
|
|
942 }
|
|
943
|
|
944 /**
|
|
945 * Returns the widget text.
|
|
946 * <p>
|
|
947 * The text for a text widget is the characters in the widget, or
|
|
948 * an empty string if this has never been set.
|
|
949 * </p>
|
|
950 *
|
|
951 * @return the widget text
|
|
952 *
|
|
953 * @exception SWTException <ul>
|
|
954 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
955 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
956 * </ul>
|
|
957 */
|
|
958 public String getText () {
|
|
959 checkWidget ();
|
|
960 char* address;
|
|
961 if ((style & SWT.SINGLE) !is 0) {
|
|
962 address = OS.gtk_entry_get_text (cast(GtkEntry*)handle);
|
|
963 } else {
|
|
964 GtkTextIter start;
|
|
965 GtkTextIter end;
|
|
966 OS.gtk_text_buffer_get_bounds (bufferHandle, &start, &end);
|
|
967 address = OS.gtk_text_buffer_get_text (bufferHandle, &start, &end, true);
|
|
968 }
|
|
969 if (address is null) return "";
|
51
|
970 String res = fromStringz( address )._idup();
|
25
|
971 if ((style & SWT.MULTI) !is 0) OS.g_free (address);
|
|
972 return res;
|
|
973 }
|
|
974
|
|
975 /**
|
|
976 * Returns a range of text. Returns an empty string if the
|
|
977 * start of the range is greater than the end.
|
|
978 * <p>
|
|
979 * Indexing is zero based. The range of
|
|
980 * a selection is from 0..N-1 where N is
|
|
981 * the number of characters in the widget.
|
|
982 * </p>
|
|
983 *
|
|
984 * @param start the start of the range
|
|
985 * @param end the end of the range
|
|
986 * @return the range of text
|
|
987 *
|
|
988 * @exception SWTException <ul>
|
|
989 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
990 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
991 * </ul>
|
|
992 */
|
|
993 public String getText (int start, int end) {
|
|
994 checkWidget ();
|
|
995 if (!(start <= end && 0 <= end)) return "";
|
|
996 start = Math.max (0, start);
|
|
997 char* address;
|
|
998 if ((style & SWT.SINGLE) !is 0) {
|
|
999 address = OS.gtk_editable_get_chars (cast(GtkEditable*)handle, start, end + 1);
|
|
1000 } else {
|
|
1001 int length = OS.gtk_text_buffer_get_char_count (bufferHandle);
|
|
1002 end = Math.min (end, length - 1);
|
|
1003 GtkTextIter startIter;
|
|
1004 GtkTextIter endIter;
|
|
1005 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &startIter, start);
|
|
1006 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &endIter, end + 1);
|
|
1007 address = OS.gtk_text_buffer_get_text (bufferHandle, &startIter, &endIter, true);
|
|
1008 }
|
|
1009 if (address is null) error (SWT.ERROR_CANNOT_GET_TEXT);
|
51
|
1010 String res = fromStringz( address )._idup();
|
25
|
1011 OS.g_free (address);
|
|
1012 return res;
|
|
1013 }
|
|
1014
|
|
1015 /**
|
|
1016 * Returns the maximum number of characters that the receiver is capable of holding.
|
|
1017 * <p>
|
|
1018 * If this has not been changed by <code>setTextLimit()</code>,
|
|
1019 * it will be the constant <code>Text.LIMIT</code>.
|
|
1020 * </p>
|
|
1021 *
|
|
1022 * @return the text limit
|
|
1023 *
|
|
1024 * @exception SWTException <ul>
|
|
1025 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1026 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1027 * </ul>
|
|
1028 *
|
|
1029 * @see #LIMIT
|
|
1030 */
|
|
1031 public int getTextLimit () {
|
|
1032 checkWidget ();
|
|
1033 if ((style & SWT.MULTI) !is 0) return LIMIT;
|
|
1034 int limit = OS.gtk_entry_get_max_length (cast(GtkEntry*)handle);
|
|
1035 return limit is 0 ? 0xFFFF : limit;
|
|
1036 }
|
|
1037
|
|
1038 /**
|
|
1039 * Returns the zero-relative index of the line which is currently
|
|
1040 * at the top of the receiver.
|
|
1041 * <p>
|
|
1042 * This index can change when lines are scrolled or new lines are added or removed.
|
|
1043 * </p>
|
|
1044 *
|
|
1045 * @return the index of the top line
|
|
1046 *
|
|
1047 * @exception SWTException <ul>
|
|
1048 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1049 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1050 * </ul>
|
|
1051 */
|
|
1052 public int getTopIndex () {
|
|
1053 checkWidget ();
|
|
1054 if ((style & SWT.SINGLE) !is 0) return 0;
|
|
1055 GtkTextIter position;
|
|
1056 GdkRectangle rect;
|
|
1057 OS.gtk_text_view_get_visible_rect (cast(GtkTextView*)handle, &rect);
|
|
1058 OS.gtk_text_view_get_line_at_y (cast(GtkTextView*)handle, &position, rect.y, null);
|
|
1059 return OS.gtk_text_iter_get_line (&position);
|
|
1060 }
|
|
1061
|
|
1062 /**
|
|
1063 * Returns the top pixel.
|
|
1064 * <p>
|
|
1065 * The top pixel is the pixel position of the line
|
|
1066 * that is currently at the top of the widget. On
|
|
1067 * some platforms, a text widget can be scrolled by
|
|
1068 * pixels instead of lines so that a partial line
|
|
1069 * is displayed at the top of the widget.
|
|
1070 * </p><p>
|
|
1071 * The top pixel changes when the widget is scrolled.
|
|
1072 * The top pixel does not include the widget trimming.
|
|
1073 * </p>
|
|
1074 *
|
|
1075 * @return the pixel position of the top line
|
|
1076 *
|
|
1077 * @exception SWTException <ul>
|
|
1078 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1079 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1080 * </ul>
|
|
1081 */
|
|
1082 public int getTopPixel () {
|
|
1083 checkWidget ();
|
|
1084 if ((style & SWT.SINGLE) !is 0) return 0;
|
|
1085 GtkTextIter position;
|
|
1086 GdkRectangle rect;
|
|
1087 OS.gtk_text_view_get_visible_rect (cast(GtkTextView*)handle, &rect);
|
|
1088 int lineTop;
|
|
1089 OS.gtk_text_view_get_line_at_y (cast(GtkTextView*)handle, &position, rect.y, &lineTop);
|
|
1090 return lineTop;
|
|
1091 }
|
|
1092
|
|
1093 override int /*long*/ gtk_activate (GtkWidget* widget) {
|
|
1094 postEvent (SWT.DefaultSelection);
|
|
1095 return 0;
|
|
1096 }
|
|
1097
|
|
1098 override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* gdkEvent) {
|
|
1099 auto result = super.gtk_button_press_event (widget, gdkEvent);
|
|
1100 if (result !is 0) return result;
|
|
1101 if (!doubleClick) {
|
|
1102 switch (gdkEvent.type) {
|
|
1103 case OS.GDK_2BUTTON_PRESS:
|
|
1104 case OS.GDK_3BUTTON_PRESS:
|
|
1105 return 1;
|
|
1106 default:
|
|
1107 }
|
|
1108 }
|
|
1109 return result;
|
|
1110 }
|
|
1111
|
|
1112
|
|
1113 override int /*long*/ gtk_changed (GtkWidget* widget) {
|
|
1114 /*
|
|
1115 * Feature in GTK. When the user types, GTK positions
|
|
1116 * the caret after sending the changed signal. This
|
|
1117 * means that application code that attempts to position
|
|
1118 * the caret during a changed signal will fail. The fix
|
|
1119 * is to post the modify event when the user is typing.
|
|
1120 */
|
|
1121 bool keyPress = false;
|
|
1122 auto eventPtr = OS.gtk_get_current_event ();
|
|
1123 if (eventPtr !is null) {
|
|
1124 GdkEventKey* gdkEvent = cast(GdkEventKey*)eventPtr;
|
|
1125 switch (gdkEvent.type) {
|
|
1126 case OS.GDK_KEY_PRESS:
|
|
1127 keyPress = true;
|
|
1128 break;
|
|
1129 default:
|
|
1130 }
|
|
1131 OS.gdk_event_free (eventPtr);
|
|
1132 }
|
|
1133 if (keyPress) {
|
|
1134 postEvent (SWT.Modify);
|
|
1135 } else {
|
|
1136 sendEvent (SWT.Modify);
|
|
1137 }
|
|
1138 return 0;
|
|
1139 }
|
|
1140
|
|
1141 override int /*long*/ gtk_commit (GtkIMContext* imcontext, char* text) {
|
|
1142 if (text is null) return 0;
|
|
1143 if ((style & SWT.SINGLE) !is 0) {
|
|
1144 if (!OS.gtk_editable_get_editable (cast(GtkEditable*)handle)) return 0;
|
|
1145 }
|
|
1146 char [] chars = fromStringz( text ).dup;
|
|
1147 if (chars.length is 0) return 0;
|
|
1148 char [] newChars = sendIMKeyEvent (SWT.KeyDown, null, chars);
|
|
1149 if (newChars is null) return 0;
|
|
1150 /*
|
|
1151 * Feature in GTK. For a GtkEntry, during the insert-text signal,
|
|
1152 * GTK allows the programmer to change only the caret location,
|
|
1153 * not the selection. If the programmer changes the selection,
|
|
1154 * the new selection is lost. The fix is to detect a selection
|
|
1155 * change and set it after the insert-text signal has completed.
|
|
1156 */
|
|
1157 fixStart = fixEnd = -1;
|
|
1158 OS.g_signal_handlers_block_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCOMMIT);
|
|
1159 int id = OS.g_signal_lookup (OS.commit.ptr, OS.gtk_im_context_get_type ());
|
|
1160 int mask = OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
|
|
1161 OS.g_signal_handlers_unblock_matched (imContext, mask, id, 0, null, null, cast(void*)handle);
|
|
1162 if (newChars is chars) {
|
|
1163 OS.g_signal_emit_by_name1 (imContext, OS.commit.ptr, cast(int)text);
|
|
1164 } else {
|
|
1165 OS.g_signal_emit_by_name1 (imContext, OS.commit.ptr, cast(int)toStringz(newChars) );
|
|
1166 }
|
|
1167 OS.g_signal_handlers_unblock_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCOMMIT );
|
|
1168 OS.g_signal_handlers_block_matched (imContext, mask, id, 0, null, null, cast(void*)handle);
|
|
1169 if ((style & SWT.SINGLE) !is 0) {
|
|
1170 if (fixStart !is -1 && fixEnd !is -1) {
|
|
1171 OS.gtk_editable_set_position (cast(GtkEditable*)handle, fixStart);
|
|
1172 OS.gtk_editable_select_region (cast(GtkEditable*)handle, fixStart, fixEnd);
|
|
1173 }
|
|
1174 }
|
|
1175 fixStart = fixEnd = -1;
|
|
1176 return 0;
|
|
1177 }
|
|
1178
|
|
1179 override int /*long*/ gtk_delete_range (GtkWidget* widget, int /*long*/ iter1, int /*long*/ iter2) {
|
|
1180 if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
|
|
1181 GtkTextIter startIter = *cast(GtkTextIter*)iter1;
|
|
1182 GtkTextIter endIter = *cast(GtkTextIter*)iter2;
|
|
1183 int start = OS.gtk_text_iter_get_offset (&startIter);
|
|
1184 int end = OS.gtk_text_iter_get_offset (&endIter);
|
|
1185 String newText = verifyText ("", start, end);
|
|
1186 if (newText is null) {
|
|
1187 /* Remember the selection when the text was deleted */
|
|
1188 OS.gtk_text_buffer_get_selection_bounds (bufferHandle, &startIter, &endIter);
|
|
1189 start = OS.gtk_text_iter_get_offset (&startIter);
|
|
1190 end = OS.gtk_text_iter_get_offset (&endIter);
|
|
1191 if (start !is end) {
|
|
1192 fixStart = start;
|
|
1193 fixEnd = end;
|
|
1194 }
|
|
1195 OS.g_signal_stop_emission_by_name (bufferHandle, OS.delete_range.ptr);
|
|
1196 } else {
|
|
1197 if (newText.length > 0) {
|
|
1198 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1199 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_RANGE);
|
|
1200 OS.gtk_text_buffer_delete (bufferHandle, &startIter, &endIter);
|
|
1201 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_RANGE);
|
|
1202 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1203 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1204 OS.gtk_text_buffer_insert (bufferHandle, &startIter, newText.ptr, newText.length);
|
|
1205 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1206 OS.g_signal_stop_emission_by_name (bufferHandle, OS.delete_range.ptr);
|
|
1207 }
|
|
1208 }
|
|
1209 return 0;
|
|
1210 }
|
|
1211
|
|
1212 override int /*long*/ gtk_delete_text (GtkWidget* widget, int /*long*/ start_pos, int /*long*/ end_pos) {
|
|
1213 if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
|
|
1214 String newText = verifyText ("", cast(int)/*64*/start_pos, cast(int)/*64*/end_pos);
|
|
1215 if (newText is null) {
|
|
1216 /* Remember the selection when the text was deleted */
|
|
1217 int newStart, newEnd;
|
|
1218 OS.gtk_editable_get_selection_bounds (cast(GtkEditable*)handle, &newStart, &newEnd);
|
|
1219 if (newStart !is newEnd) {
|
|
1220 fixStart = newStart;
|
|
1221 fixEnd = newEnd;
|
|
1222 }
|
|
1223 OS.g_signal_stop_emission_by_name (handle, OS.delete_text.ptr);
|
|
1224 } else {
|
|
1225 if (newText.length > 0) {
|
|
1226 int pos;
|
|
1227 pos = cast(int)/*64*/end_pos;
|
|
1228 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1229 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1230 OS.gtk_editable_insert_text (cast(GtkEditable*)handle, newText.ptr, newText.length, &pos);
|
|
1231 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1232 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1233 OS.gtk_editable_set_position (cast(GtkEditable*)handle, pos);
|
|
1234 }
|
|
1235 }
|
|
1236 return 0;
|
|
1237 }
|
|
1238
|
|
1239 override int /*long*/ gtk_event_after (GtkWidget* widget, GdkEvent* event) {
|
|
1240 if (cursor !is null) gtk_setCursor (cursor.handle);
|
|
1241 /*
|
|
1242 * Feature in GTK. The gtk-entry-select-on-focus property is a global
|
|
1243 * setting. Return it to its default value after the GtkEntry has done
|
|
1244 * its focus in processing so that other widgets (such as the combo)
|
|
1245 * use the correct value.
|
|
1246 */
|
|
1247 if ((style & SWT.SINGLE) !is 0 && display.entrySelectOnFocus) {
|
|
1248 switch (event.type) {
|
|
1249 case OS.GDK_FOCUS_CHANGE:
|
|
1250 GdkEventFocus* gdkEventFocus = cast(GdkEventFocus*)event;
|
|
1251 if (gdkEventFocus.in_ is 0) {
|
|
1252 auto settings = OS.gtk_settings_get_default ();
|
|
1253 OS.g_object_set1 (settings, OS.gtk_entry_select_on_focus.ptr, true );
|
|
1254 }
|
|
1255 break;
|
|
1256 default:
|
|
1257 }
|
|
1258 }
|
|
1259 return super.gtk_event_after (widget, event);
|
|
1260 }
|
|
1261
|
|
1262 override int /*long*/ gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) {
|
|
1263 fixIM ();
|
|
1264 return super.gtk_focus_out_event (widget, event);
|
|
1265 }
|
|
1266
|
|
1267 override int /*long*/ gtk_grab_focus (GtkWidget* widget) {
|
|
1268 auto result = super.gtk_grab_focus (widget);
|
|
1269 /*
|
|
1270 * Feature in GTK. GtkEntry widgets select their text on focus in,
|
|
1271 * clearing the previous selection. This behavior is controlled by
|
|
1272 * the gtk-entry-select-on-focus property. The fix is to disable
|
|
1273 * this property when a GtkEntry is given focus and restore it after
|
|
1274 * the entry has done focus in processing.
|
|
1275 */
|
|
1276 if ((style & SWT.SINGLE) !is 0 && display.entrySelectOnFocus) {
|
|
1277 auto settings = OS.gtk_settings_get_default ();
|
|
1278 OS.g_object_set1 (settings, OS.gtk_entry_select_on_focus.ptr, false );
|
|
1279 }
|
|
1280 return result;
|
|
1281 }
|
|
1282
|
|
1283 override int /*long*/ gtk_insert_text (GtkEditable* widget, char* new_text, int new_text_length, int position) {
|
|
1284 if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
|
|
1285 if (new_text is null || new_text_length is 0) return 0;
|
51
|
1286 String oldText = (cast(char*)new_text)[ 0 .. new_text_length ]._idup();
|
25
|
1287 int pos;
|
|
1288 pos = *cast(int*)position;
|
|
1289 if (pos is -1) {
|
|
1290 auto ptr = OS.gtk_entry_get_text (cast(GtkEntry*)handle);
|
|
1291 pos = cast(int)/*64*/OS.g_utf8_strlen (ptr, -1);
|
|
1292 }
|
|
1293 /* Use the selection when the text was deleted */
|
|
1294 int start = pos, end = pos;
|
|
1295 if (fixStart !is -1 && fixEnd !is -1) {
|
|
1296 start = pos = fixStart;
|
|
1297 end = fixEnd;
|
|
1298 fixStart = fixEnd = -1;
|
|
1299 }
|
|
1300 String newText = verifyText (oldText, start, end);
|
|
1301 if (newText !is oldText) {
|
|
1302 int newStart, newEnd;
|
|
1303 OS.gtk_editable_get_selection_bounds (cast(GtkEditable*)handle, &newStart, &newEnd);
|
|
1304 if (newText !is null) {
|
|
1305 if (newStart !is newEnd) {
|
|
1306 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_TEXT);
|
|
1307 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1308 OS.gtk_editable_delete_selection (cast(GtkEditable*)handle);
|
|
1309 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_TEXT);
|
|
1310 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1311 }
|
|
1312 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1313 OS.gtk_editable_insert_text (cast(GtkEditable*)handle, newText.ptr, newText.length, &pos);
|
|
1314 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1315 newStart = newEnd = pos;
|
|
1316 }
|
|
1317 pos = newEnd;
|
|
1318 if (newStart !is newEnd) {
|
|
1319 fixStart = newStart;
|
|
1320 fixEnd = newEnd;
|
|
1321 }
|
|
1322 *cast(int*)position = pos;
|
|
1323 OS.g_signal_stop_emission_by_name (handle, OS.insert_text.ptr);
|
|
1324 }
|
|
1325 return 0;
|
|
1326 }
|
|
1327
|
|
1328 override int /*long*/ gtk_key_press_event (GtkWidget* widget, GdkEventKey* event) {
|
|
1329 auto result = super.gtk_key_press_event (widget, event);
|
|
1330 if (result !is 0) fixIM ();
|
|
1331 if (gdkEventKey is cast(GdkEventKey*)-1) result = 1;
|
|
1332 gdkEventKey = null;
|
|
1333 return result;
|
|
1334 }
|
|
1335
|
|
1336 override int /*long*/ gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) {
|
|
1337 if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
|
|
1338 OS.gtk_widget_set_direction (menu, OS.GTK_TEXT_DIR_RTL);
|
|
1339 display.doSetDirectionProc (menu, OS.GTK_TEXT_DIR_RTL);
|
|
1340 }
|
|
1341 return 0;
|
|
1342 }
|
|
1343
|
|
1344 override int /*long*/ gtk_text_buffer_insert_text (GtkTextBuffer *widget, GtkTextIter *iter, char *text, int len) {
|
|
1345 if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
|
|
1346 GtkTextIter position = *iter;
|
|
1347 /* Use the selection when the text was deleted */
|
|
1348 int start = OS.gtk_text_iter_get_offset (&position), end = start;
|
|
1349 if (fixStart !is -1 && fixEnd !is -1) {
|
|
1350 start = fixStart;
|
|
1351 end = fixEnd;
|
|
1352 fixStart = fixEnd = -1;
|
|
1353 }
|
51
|
1354 String oldText = cast(String)text[ 0 .. len ];
|
25
|
1355 String newText = verifyText (oldText, start, end);
|
|
1356 if (newText is null) {
|
|
1357 OS.g_signal_stop_emission_by_name (bufferHandle, OS.insert_text.ptr);
|
|
1358 } else {
|
|
1359 if (newText !is oldText) {
|
|
1360 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1361 OS.gtk_text_buffer_insert (bufferHandle, iter, newText.ptr, newText.length);
|
|
1362 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1363 OS.g_signal_stop_emission_by_name (bufferHandle, OS.insert_text.ptr);
|
|
1364 }
|
|
1365 }
|
|
1366 return 0;
|
|
1367 }
|
|
1368
|
|
1369 override void hookEvents () {
|
|
1370 super.hookEvents();
|
|
1371 if ((style & SWT.SINGLE) !is 0) {
|
|
1372 OS.g_signal_connect_closure (handle, OS.changed.ptr, display.closures [CHANGED], true);
|
|
1373 OS.g_signal_connect_closure (handle, OS.insert_text.ptr, display.closures [INSERT_TEXT], false);
|
|
1374 OS.g_signal_connect_closure (handle, OS.delete_text.ptr, display.closures [DELETE_TEXT], false);
|
|
1375 OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE], false);
|
|
1376 OS.g_signal_connect_closure (handle, OS.grab_focus.ptr, display.closures [GRAB_FOCUS], false);
|
|
1377 OS.g_signal_connect_closure (handle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false);
|
|
1378 } else {
|
|
1379 OS.g_signal_connect_closure (bufferHandle, OS.changed.ptr, display.closures [CHANGED], false);
|
|
1380 OS.g_signal_connect_closure (bufferHandle, OS.insert_text.ptr, display.closures [TEXT_BUFFER_INSERT_TEXT], false);
|
|
1381 OS.g_signal_connect_closure (bufferHandle, OS.delete_range.ptr, display.closures [DELETE_RANGE], false);
|
|
1382 OS.g_signal_connect_closure (handle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false);
|
|
1383 }
|
|
1384 auto imContext = imContext ();
|
|
1385 if (imContext !is null) {
|
|
1386 OS.g_signal_connect_closure (imContext, OS.commit.ptr, display.closures [COMMIT], false);
|
|
1387 int id = OS.g_signal_lookup (OS.commit.ptr, OS.gtk_im_context_get_type ());
|
|
1388 int mask = OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
|
|
1389 OS.g_signal_handlers_block_matched (imContext, mask, id, 0, null, null, cast(void*)handle);
|
|
1390 }
|
|
1391 }
|
|
1392
|
|
1393 GtkIMContext* imContext () {
|
|
1394 if ((style & SWT.SINGLE) !is 0) {
|
|
1395 return OS.gtk_editable_get_editable (handle) ? OS.GTK_ENTRY_IM_CONTEXT (handle) : null;
|
|
1396 }
|
|
1397 return OS.GTK_TEXTVIEW_IM_CONTEXT (cast(GtkTextView*)handle);
|
|
1398 }
|
|
1399
|
|
1400 /**
|
|
1401 * Inserts a string.
|
|
1402 * <p>
|
|
1403 * The old selection is replaced with the new text.
|
|
1404 * </p>
|
|
1405 *
|
|
1406 * @param string the string
|
|
1407 *
|
|
1408 * @exception SWTException <ul>
|
|
1409 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1410 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1411 * </ul>
|
|
1412 */
|
|
1413 public void insert (String string) {
|
|
1414 checkWidget ();
|
|
1415 // SWT extension: allow null for zero length string
|
|
1416 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1417 if ((style & SWT.SINGLE) !is 0) {
|
|
1418 int start, end;
|
|
1419 OS.gtk_editable_get_selection_bounds (cast(GtkEditable*)handle, &start, &end);
|
|
1420 OS.gtk_editable_delete_selection (cast(GtkEditable*)handle);
|
|
1421 OS.gtk_editable_insert_text (cast(GtkEditable*)handle, string.ptr, string.length, &start);
|
|
1422 OS.gtk_editable_set_position (cast(GtkEditable*)handle, start);
|
|
1423 } else {
|
|
1424 GtkTextIter start;
|
|
1425 GtkTextIter end;
|
|
1426 if (OS.gtk_text_buffer_get_selection_bounds (bufferHandle, &start, &end)) {
|
|
1427 OS.gtk_text_buffer_delete (bufferHandle, &start, &end);
|
|
1428 }
|
|
1429 OS.gtk_text_buffer_insert (bufferHandle, &start, string.ptr, string.length);
|
|
1430 OS.gtk_text_buffer_place_cursor (bufferHandle, &start);
|
|
1431 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1432 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
1433 }
|
|
1434 }
|
|
1435
|
|
1436 override GdkDrawable* paintWindow () {
|
|
1437 if ((style & SWT.SINGLE) !is 0) {
|
|
1438 auto window = super.paintWindow ();
|
|
1439 auto children = OS.gdk_window_get_children (window);
|
|
1440 if (children !is null) window = cast(GdkDrawable*) OS.g_list_data (children);
|
|
1441 OS.g_list_free (children);
|
|
1442 return window;
|
|
1443 }
|
|
1444 OS.gtk_widget_realize (handle);
|
|
1445 return OS.gtk_text_view_get_window (cast(GtkTextView*)handle, OS.GTK_TEXT_WINDOW_TEXT);
|
|
1446 }
|
|
1447
|
|
1448 /**
|
|
1449 * Pastes text from clipboard.
|
|
1450 * <p>
|
|
1451 * The selected text is deleted from the widget
|
|
1452 * and new text inserted from the clipboard.
|
|
1453 * </p>
|
|
1454 *
|
|
1455 * @exception SWTException <ul>
|
|
1456 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1457 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1458 * </ul>
|
|
1459 */
|
|
1460 public void paste () {
|
|
1461 checkWidget ();
|
|
1462 if ((style & SWT.SINGLE) !is 0) {
|
|
1463 OS.gtk_editable_paste_clipboard (cast(GtkEditable*)handle);
|
|
1464 } else {
|
|
1465 auto clipboard = OS.gtk_clipboard_get (cast(void*)OS.GDK_NONE);
|
|
1466 OS.gtk_text_buffer_paste_clipboard (bufferHandle, clipboard, null, OS.gtk_text_view_get_editable (cast(GtkTextView*)handle));
|
|
1467 }
|
|
1468 }
|
|
1469
|
|
1470 override void register () {
|
|
1471 super.register ();
|
|
1472 if (bufferHandle !is null) display.addWidget (cast(GtkWidget*)bufferHandle, this);
|
|
1473 auto imContext = imContext ();
|
|
1474 if (imContext !is null) display.addWidget (cast(GtkWidget*)imContext, this);
|
|
1475 }
|
|
1476
|
|
1477 override void releaseWidget () {
|
|
1478 super.releaseWidget ();
|
|
1479 fixIM ();
|
|
1480 if (OS.GTK_VERSION < OS.buildVERSION (2, 6, 0)) {
|
|
1481 /*
|
|
1482 * Bug in GTK. Any text copied into the clipboard will be lost when
|
|
1483 * the GtkTextView is destroyed. The fix is to paste the contents as
|
|
1484 * the widget is being destroyed to reference the text buffer, keeping
|
|
1485 * it around until ownership of the clipboard is lost.
|
|
1486 */
|
|
1487 if ((style & SWT.MULTI) !is 0) {
|
|
1488 auto clipboard = OS.gtk_clipboard_get (cast(void*)OS.GDK_NONE);
|
|
1489 OS.gtk_text_buffer_paste_clipboard (bufferHandle, clipboard, null, OS.gtk_text_view_get_editable (cast(GtkTextView*)handle));
|
|
1490 }
|
|
1491 }
|
|
1492 message = null;
|
|
1493 }
|
|
1494
|
|
1495 /**
|
|
1496 * Removes the listener from the collection of listeners who will
|
|
1497 * be notified when the receiver's text is modified.
|
|
1498 *
|
|
1499 * @param listener the listener which should no longer be notified
|
|
1500 *
|
|
1501 * @exception IllegalArgumentException <ul>
|
|
1502 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
1503 * </ul>
|
|
1504 * @exception SWTException <ul>
|
|
1505 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1506 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1507 * </ul>
|
|
1508 *
|
|
1509 * @see ModifyListener
|
|
1510 * @see #addModifyListener
|
|
1511 */
|
|
1512 public void removeModifyListener (ModifyListener listener) {
|
|
1513 checkWidget ();
|
|
1514 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1515 if (eventTable is null) return;
|
|
1516 eventTable.unhook (SWT.Modify, listener);
|
|
1517 }
|
|
1518
|
|
1519 /**
|
|
1520 * Removes the listener from the collection of listeners who will
|
|
1521 * be notified when the control is selected by the user.
|
|
1522 *
|
|
1523 * @param listener the listener which should no longer be notified
|
|
1524 *
|
|
1525 * @exception IllegalArgumentException <ul>
|
|
1526 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
1527 * </ul>
|
|
1528 * @exception SWTException <ul>
|
|
1529 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1530 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1531 * </ul>
|
|
1532 *
|
|
1533 * @see SelectionListener
|
|
1534 * @see #addSelectionListener
|
|
1535 */
|
|
1536 public void removeSelectionListener(SelectionListener listener) {
|
|
1537 checkWidget ();
|
|
1538 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1539 if (eventTable is null) return;
|
|
1540 eventTable.unhook(SWT.Selection, listener);
|
|
1541 eventTable.unhook(SWT.DefaultSelection,listener);
|
|
1542 }
|
|
1543
|
|
1544 /**
|
|
1545 * Removes the listener from the collection of listeners who will
|
|
1546 * be notified when the control is verified.
|
|
1547 *
|
|
1548 * @param listener the listener which should no longer be notified
|
|
1549 *
|
|
1550 * @exception IllegalArgumentException <ul>
|
|
1551 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
1552 * </ul>
|
|
1553 * @exception SWTException <ul>
|
|
1554 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1555 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1556 * </ul>
|
|
1557 *
|
|
1558 * @see VerifyListener
|
|
1559 * @see #addVerifyListener
|
|
1560 */
|
|
1561 public void removeVerifyListener (VerifyListener listener) {
|
|
1562 checkWidget ();
|
|
1563 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1564 if (eventTable is null) return;
|
|
1565 eventTable.unhook (SWT.Verify, listener);
|
|
1566 }
|
|
1567
|
|
1568 /**
|
|
1569 * Selects all the text in the receiver.
|
|
1570 *
|
|
1571 * @exception SWTException <ul>
|
|
1572 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1573 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1574 * </ul>
|
|
1575 */
|
|
1576 public void selectAll () {
|
|
1577 checkWidget ();
|
|
1578 if ((style & SWT.SINGLE) !is 0) {
|
|
1579 OS.gtk_editable_select_region (cast(GtkEditable*)handle, 0, -1);
|
|
1580 } else {
|
|
1581 GtkTextIter start;
|
|
1582 GtkTextIter end;
|
|
1583 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &start, 0);
|
|
1584 OS.gtk_text_buffer_get_end_iter (bufferHandle, &end);
|
|
1585 auto insertMark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1586 auto selectionMark = OS.gtk_text_buffer_get_selection_bound (bufferHandle);
|
|
1587 OS.gtk_text_buffer_move_mark (bufferHandle, selectionMark, &start);
|
|
1588 OS.gtk_text_buffer_move_mark (bufferHandle, insertMark, &end);
|
|
1589 }
|
|
1590 }
|
|
1591
|
|
1592 override void setBackgroundColor (GdkColor* color) {
|
|
1593 super.setBackgroundColor (color);
|
|
1594 OS.gtk_widget_modify_base (handle, 0, color);
|
|
1595 }
|
|
1596
|
|
1597 override void gtk_setCursor (GdkCursor* cursor) {
|
|
1598 GdkCursor* defaultCursor;
|
|
1599 if (cursor is null) defaultCursor = OS.gdk_cursor_new (OS.GDK_XTERM);
|
|
1600 super.gtk_setCursor (cursor !is null ? cursor : defaultCursor);
|
|
1601 if (cursor is null) OS.gdk_cursor_destroy (defaultCursor);
|
|
1602 }
|
|
1603
|
|
1604 /**
|
|
1605 * Sets the double click enabled flag.
|
|
1606 * <p>
|
|
1607 * The double click flag enables or disables the
|
|
1608 * default action of the text widget when the user
|
|
1609 * double clicks.
|
|
1610 * </p><p>
|
|
1611 * Note: This operation is a hint and is not supported on
|
|
1612 * platforms that do not have this concept.
|
|
1613 * </p>
|
|
1614 *
|
|
1615 * @param doubleClick the new double click flag
|
|
1616 *
|
|
1617 * @exception SWTException <ul>
|
|
1618 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1619 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1620 * </ul>
|
|
1621 */
|
|
1622 public void setDoubleClickEnabled (bool doubleClick) {
|
|
1623 checkWidget ();
|
|
1624 this.doubleClick = doubleClick;
|
|
1625 }
|
|
1626
|
|
1627 /**
|
|
1628 * Sets the echo character.
|
|
1629 * <p>
|
|
1630 * The echo character is the character that is
|
|
1631 * displayed when the user enters text or the
|
|
1632 * text is changed by the programmer. Setting
|
|
1633 * the echo character to '\0' clears the echo
|
|
1634 * character and redraws the original text.
|
|
1635 * If for any reason the echo character is invalid,
|
|
1636 * or if the platform does not allow modification
|
|
1637 * of the echo character, the default echo character
|
|
1638 * for the platform is used.
|
|
1639 * </p>
|
|
1640 *
|
|
1641 * @param echo the new echo character
|
|
1642 *
|
|
1643 * @exception SWTException <ul>
|
|
1644 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1645 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1646 * </ul>
|
|
1647 */
|
|
1648 public void setEchoChar (char echo) {
|
|
1649 checkWidget ();
|
|
1650 if ((style & SWT.SINGLE) !is 0) {
|
|
1651 OS.gtk_entry_set_visibility (cast(GtkEntry*)handle, echo is '\0');
|
|
1652 OS.gtk_entry_set_invisible_char (cast(GtkEntry*)handle, echo);
|
|
1653 }
|
|
1654 }
|
|
1655
|
|
1656 /**
|
|
1657 * Sets the editable state.
|
|
1658 *
|
|
1659 * @param editable the new editable state
|
|
1660 *
|
|
1661 * @exception SWTException <ul>
|
|
1662 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1663 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1664 * </ul>
|
|
1665 */
|
|
1666 public void setEditable (bool editable) {
|
|
1667 checkWidget ();
|
|
1668 style &= ~SWT.READ_ONLY;
|
|
1669 if (!editable) style |= SWT.READ_ONLY;
|
|
1670 if ((style & SWT.SINGLE) !is 0) {
|
|
1671 OS.gtk_editable_set_editable (cast(GtkEditable*)handle, editable);
|
|
1672 } else {
|
|
1673 OS.gtk_text_view_set_editable (cast(GtkTextView*)handle, editable);
|
|
1674 }
|
|
1675 }
|
|
1676
|
|
1677 override void setFontDescription (PangoFontDescription* font) {
|
|
1678 super.setFontDescription (font);
|
|
1679 setTabStops (tabs);
|
|
1680 }
|
|
1681
|
|
1682 /**
|
|
1683 * Sets the widget message. When the widget is created
|
|
1684 * with the style <code>SWT.SEARCH</code>, the message text
|
|
1685 * is displayed as a hint for the user, indicating the
|
|
1686 * purpose of the field.
|
|
1687 * <p>
|
|
1688 * Note: This operation is a <em>HINT</em> and is not
|
|
1689 * supported on platforms that do not have this concept.
|
|
1690 * </p>
|
|
1691 *
|
|
1692 * @param message the new message
|
|
1693 *
|
|
1694 * @exception IllegalArgumentException <ul>
|
|
1695 * <li>ERROR_NULL_ARGUMENT - if the message is null</li>
|
|
1696 * </ul>
|
|
1697 * @exception SWTException <ul>
|
|
1698 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1699 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1700 * </ul>
|
|
1701 *
|
|
1702 * @since 3.3
|
|
1703 */
|
|
1704 public void setMessage (String message) {
|
|
1705 checkWidget ();
|
|
1706 // SWT extension: allow null for zero length string
|
|
1707 //if (message is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1708 this.message = message;
|
|
1709 }
|
|
1710
|
|
1711 /**
|
|
1712 * Sets the orientation of the receiver, which must be one
|
|
1713 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
|
|
1714 * <p>
|
|
1715 * Note: This operation is a hint and is not supported on
|
|
1716 * platforms that do not have this concept.
|
|
1717 * </p>
|
|
1718 *
|
|
1719 * @param orientation new orientation style
|
|
1720 *
|
|
1721 * @exception SWTException <ul>
|
|
1722 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1723 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1724 * </ul>
|
|
1725 *
|
|
1726 * @since 2.1.2
|
|
1727 */
|
|
1728 public void setOrientation (int orientation) {
|
|
1729 checkWidget();
|
|
1730 }
|
|
1731
|
|
1732 /**
|
|
1733 * Sets the selection.
|
|
1734 * <p>
|
|
1735 * Indexing is zero based. The range of
|
|
1736 * a selection is from 0..N where N is
|
|
1737 * the number of characters in the widget.
|
|
1738 * </p><p>
|
|
1739 * Text selections are specified in terms of
|
|
1740 * caret positions. In a text widget that
|
|
1741 * contains N characters, there are N+1 caret
|
|
1742 * positions, ranging from 0..N. This differs
|
|
1743 * from other functions that address character
|
|
1744 * position such as getText () that use the
|
|
1745 * regular array indexing rules.
|
|
1746 * </p>
|
|
1747 *
|
|
1748 * @param start new caret position
|
|
1749 *
|
|
1750 * @exception SWTException <ul>
|
|
1751 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1752 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1753 * </ul>
|
|
1754 */
|
|
1755 public void setSelection (int start) {
|
|
1756 checkWidget ();
|
|
1757 if ((style & SWT.SINGLE) !is 0) {
|
|
1758 OS.gtk_editable_set_position (cast(GtkEditable*)handle, start);
|
|
1759 } else {
|
|
1760 GtkTextIter position;
|
|
1761 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &position, start);
|
|
1762 OS.gtk_text_buffer_place_cursor (bufferHandle, &position);
|
|
1763 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1764 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
1765 }
|
|
1766 }
|
|
1767
|
|
1768 /**
|
|
1769 * Sets the selection to the range specified
|
|
1770 * by the given start and end indices.
|
|
1771 * <p>
|
|
1772 * Indexing is zero based. The range of
|
|
1773 * a selection is from 0..N where N is
|
|
1774 * the number of characters in the widget.
|
|
1775 * </p><p>
|
|
1776 * Text selections are specified in terms of
|
|
1777 * caret positions. In a text widget that
|
|
1778 * contains N characters, there are N+1 caret
|
|
1779 * positions, ranging from 0..N. This differs
|
|
1780 * from other functions that address character
|
|
1781 * position such as getText () that use the
|
|
1782 * usual array indexing rules.
|
|
1783 * </p>
|
|
1784 *
|
|
1785 * @param start the start of the range
|
|
1786 * @param end the end of the range
|
|
1787 *
|
|
1788 * @exception SWTException <ul>
|
|
1789 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1790 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1791 * </ul>
|
|
1792 */
|
|
1793 public void setSelection (int start, int end) {
|
|
1794 checkWidget ();
|
|
1795 if ((style & SWT.SINGLE) !is 0) {
|
|
1796 OS.gtk_editable_set_position (cast(GtkEditable*)handle, start);
|
|
1797 OS.gtk_editable_select_region (cast(GtkEditable*)handle, start, end);
|
|
1798 } else {
|
|
1799 GtkTextIter startIter;
|
|
1800 GtkTextIter endIter;
|
|
1801 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &startIter, start);
|
|
1802 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &endIter, end);
|
|
1803 auto insertMark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1804 auto selectionMark = OS.gtk_text_buffer_get_selection_bound (bufferHandle);
|
|
1805 OS.gtk_text_buffer_move_mark (bufferHandle, selectionMark, &startIter);
|
|
1806 OS.gtk_text_buffer_move_mark (bufferHandle, insertMark, &endIter);
|
|
1807 }
|
|
1808 }
|
|
1809
|
|
1810 /**
|
|
1811 * Sets the selection to the range specified
|
|
1812 * by the given point, where the x coordinate
|
|
1813 * represents the start index and the y coordinate
|
|
1814 * represents the end index.
|
|
1815 * <p>
|
|
1816 * Indexing is zero based. The range of
|
|
1817 * a selection is from 0..N where N is
|
|
1818 * the number of characters in the widget.
|
|
1819 * </p><p>
|
|
1820 * Text selections are specified in terms of
|
|
1821 * caret positions. In a text widget that
|
|
1822 * contains N characters, there are N+1 caret
|
|
1823 * positions, ranging from 0..N. This differs
|
|
1824 * from other functions that address character
|
|
1825 * position such as getText () that use the
|
|
1826 * usual array indexing rules.
|
|
1827 * </p>
|
|
1828 *
|
|
1829 * @param selection the point
|
|
1830 *
|
|
1831 * @exception IllegalArgumentException <ul>
|
|
1832 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
|
|
1833 * </ul>
|
|
1834 * @exception SWTException <ul>
|
|
1835 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1836 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1837 * </ul>
|
|
1838 */
|
|
1839 public void setSelection (Point selection) {
|
|
1840 checkWidget ();
|
|
1841 if (selection is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1842 setSelection (selection.x, selection.y);
|
|
1843 }
|
|
1844
|
|
1845 /**
|
|
1846 * Sets the number of tabs.
|
|
1847 * <p>
|
|
1848 * Tab stop spacing is specified in terms of the
|
|
1849 * space (' ') character. The width of a single
|
|
1850 * tab stop is the pixel width of the spaces.
|
|
1851 * </p>
|
|
1852 *
|
|
1853 * @param tabs the number of tabs
|
|
1854 *
|
|
1855 * </ul>
|
|
1856 * @exception SWTException <ul>
|
|
1857 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1858 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1859 * </ul>
|
|
1860 */
|
|
1861 public void setTabs (int tabs) {
|
|
1862 checkWidget ();
|
|
1863 if (tabs < 0) return;
|
|
1864 setTabStops (this.tabs = tabs);
|
|
1865 }
|
|
1866
|
|
1867 void setTabStops (int tabs) {
|
|
1868 if ((style & SWT.SINGLE) !is 0) return;
|
|
1869 int tabWidth = getTabWidth (tabs);
|
|
1870 auto tabArray = OS.pango_tab_array_new (1, false);
|
|
1871 OS.pango_tab_array_set_tab (tabArray, 0, OS.PANGO_TAB_LEFT, tabWidth);
|
|
1872 OS.gtk_text_view_set_tabs (cast(GtkTextView*)handle, tabArray);
|
|
1873 OS.pango_tab_array_free (tabArray);
|
|
1874 }
|
|
1875
|
|
1876 /**
|
|
1877 * Sets the contents of the receiver to the given string. If the receiver has style
|
|
1878 * SINGLE and the argument contains multiple lines of text, the result of this
|
|
1879 * operation is undefined and may vary from platform to platform.
|
|
1880 *
|
|
1881 * @param string the new text
|
|
1882 *
|
|
1883 * @exception SWTException <ul>
|
|
1884 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1885 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1886 * </ul>
|
|
1887 */
|
|
1888 public void setText (String string) {
|
|
1889 checkWidget ();
|
|
1890 // SWT extension: allow null for zero length string
|
|
1891 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1892 /*
|
|
1893 * Feature in gtk. When text is set in gtk, separate events are fired for the deletion and
|
|
1894 * insertion of the text. This is not wrong, but is inconsistent with other platforms. The
|
|
1895 * fix is to block the firing of these events and fire them ourselves in a consistent manner.
|
|
1896 */
|
|
1897 if (hooks (SWT.Verify) || filters (SWT.Verify)) {
|
|
1898 string = verifyText (string, 0, getCharCount ());
|
|
1899 if (string is null) return;
|
|
1900 }
|
|
1901 if ((style & SWT.SINGLE) !is 0) {
|
|
1902 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1903 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_TEXT);
|
|
1904 OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1905 OS.gtk_entry_set_text (cast(GtkEntry*)handle, toStringz(string) );
|
|
1906 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1907 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_TEXT);
|
|
1908 OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udINSERT_TEXT);
|
|
1909 } else {
|
|
1910 GtkTextIter position;
|
|
1911 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1912 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_RANGE);
|
|
1913 OS.g_signal_handlers_block_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1914 OS.gtk_text_buffer_set_text (bufferHandle, string.ptr, string.length);
|
|
1915 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1916 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udDELETE_RANGE);
|
|
1917 OS.g_signal_handlers_unblock_matched (bufferHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEXT_BUFFER_INSERT_TEXT);
|
|
1918 OS.gtk_text_buffer_get_iter_at_offset (bufferHandle, &position, 0);
|
|
1919 OS.gtk_text_buffer_place_cursor (bufferHandle, &position);
|
|
1920 auto mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1921 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
1922 }
|
|
1923 sendEvent (SWT.Modify);
|
|
1924 }
|
|
1925
|
|
1926 /**
|
|
1927 * Sets the maximum number of characters that the receiver
|
|
1928 * is capable of holding to be the argument.
|
|
1929 * <p>
|
|
1930 * Instead of trying to set the text limit to zero, consider
|
|
1931 * creating a read-only text widget.
|
|
1932 * </p><p>
|
|
1933 * To reset this value to the default, use <code>setTextLimit(Text.LIMIT)</code>.
|
|
1934 * Specifying a limit value larger than <code>Text.LIMIT</code> sets the
|
|
1935 * receiver's limit to <code>Text.LIMIT</code>.
|
|
1936 * </p>
|
|
1937 *
|
|
1938 * @param limit new text limit
|
|
1939 *
|
|
1940 * @exception IllegalArgumentException <ul>
|
|
1941 * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
|
|
1942 * </ul>
|
|
1943 * @exception SWTException <ul>
|
|
1944 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1945 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1946 * </ul>
|
|
1947 *
|
|
1948 * @see #LIMIT
|
|
1949 */
|
|
1950 public void setTextLimit (int limit) {
|
|
1951 checkWidget ();
|
|
1952 if (limit is 0) error (SWT.ERROR_CANNOT_BE_ZERO);
|
|
1953 if ((style & SWT.SINGLE) !is 0) OS.gtk_entry_set_max_length (cast(GtkEntry*)handle, limit);
|
|
1954 }
|
|
1955
|
|
1956 /**
|
|
1957 * Sets the zero-relative index of the line which is currently
|
|
1958 * at the top of the receiver. This index can change when lines
|
|
1959 * are scrolled or new lines are added and removed.
|
|
1960 *
|
|
1961 * @param index the index of the top item
|
|
1962 *
|
|
1963 * @exception SWTException <ul>
|
|
1964 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1965 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1966 * </ul>
|
|
1967 */
|
|
1968 public void setTopIndex (int index) {
|
|
1969 checkWidget ();
|
|
1970 if ((style & SWT.SINGLE) !is 0) return;
|
|
1971 GtkTextIter position;
|
|
1972 OS.gtk_text_buffer_get_iter_at_line (bufferHandle, &position, index);
|
|
1973 OS.gtk_text_view_scroll_to_iter (cast(GtkTextView*)handle, &position, 0, true, 0, 0);
|
|
1974 }
|
|
1975
|
|
1976 /**
|
|
1977 * Shows the selection.
|
|
1978 * <p>
|
|
1979 * If the selection is already showing
|
|
1980 * in the receiver, this method simply returns. Otherwise,
|
|
1981 * lines are scrolled until the selection is visible.
|
|
1982 * </p>
|
|
1983 *
|
|
1984 * @exception SWTException <ul>
|
|
1985 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1986 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1987 * </ul>
|
|
1988 */
|
|
1989 public void showSelection () {
|
|
1990 checkWidget ();
|
|
1991 if ((style & SWT.SINGLE) !is 0) return;
|
|
1992 auto mark = OS.gtk_text_buffer_get_selection_bound (bufferHandle);
|
|
1993 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
1994 mark = OS.gtk_text_buffer_get_insert (bufferHandle);
|
|
1995 OS.gtk_text_view_scroll_mark_onscreen (cast(GtkTextView*)handle, mark);
|
|
1996 }
|
|
1997
|
|
1998 override bool translateTraversal (GdkEventKey* keyEvent) {
|
|
1999 int key = keyEvent.keyval;
|
|
2000 switch (key) {
|
|
2001 case OS.GDK_KP_Enter:
|
|
2002 case OS.GDK_Return: {
|
|
2003 auto imContext = imContext ();
|
|
2004 if (imContext !is null) {
|
|
2005 char* preeditString;
|
|
2006 OS.gtk_im_context_get_preedit_string (imContext, &preeditString, null, null);
|
|
2007 if (preeditString !is null) {
|
51
|
2008 int length = OS.strlen (preeditString);
|
25
|
2009 OS.g_free (preeditString);
|
|
2010 if (length !is 0) return false;
|
|
2011 }
|
|
2012 }
|
|
2013 default:
|
|
2014 }
|
|
2015 }
|
|
2016 return super.translateTraversal (keyEvent);
|
|
2017 }
|
|
2018
|
|
2019 override int traversalCode (int key, GdkEventKey* event) {
|
|
2020 int bits = super.traversalCode (key, event);
|
|
2021 if ((style & SWT.READ_ONLY) !is 0) return bits;
|
|
2022 if ((style & SWT.MULTI) !is 0) {
|
|
2023 bits &= ~SWT.TRAVERSE_RETURN;
|
|
2024 if (key is OS.GDK_Tab && event !is null) {
|
|
2025 bool next = (event.state & OS.GDK_SHIFT_MASK) is 0;
|
|
2026 if (next && (event.state & OS.GDK_CONTROL_MASK) is 0) {
|
|
2027 bits &= ~(SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS);
|
|
2028 }
|
|
2029 }
|
|
2030 }
|
|
2031 return bits;
|
|
2032 }
|
|
2033
|
|
2034 String verifyText (String string, int start, int end) {
|
|
2035 if (string.length is 0 && start is end) return null;
|
|
2036 Event event = new Event ();
|
|
2037 event.text = string;
|
|
2038 event.start = start;
|
|
2039 event.end = end;
|
|
2040 auto eventPtr = OS.gtk_get_current_event ();
|
|
2041 if (eventPtr !is null) {
|
|
2042 GdkEventKey* gdkEvent = cast(GdkEventKey*)eventPtr;
|
|
2043 switch (gdkEvent.type) {
|
|
2044 case OS.GDK_KEY_PRESS:
|
|
2045 setKeyState (event, gdkEvent);
|
|
2046 break;
|
|
2047 default:
|
|
2048 }
|
|
2049 OS.gdk_event_free (eventPtr);
|
|
2050 }
|
|
2051 /*
|
|
2052 * It is possible (but unlikely), that application
|
|
2053 * code could have disposed the widget in the verify
|
|
2054 * event. If this happens, answer null to cancel
|
|
2055 * the operation.
|
|
2056 */
|
|
2057 sendEvent (SWT.Verify, event);
|
|
2058 if (!event.doit || isDisposed ()) return null;
|
|
2059 return event.text;
|
|
2060 }
|
|
2061
|
|
2062 }
|