Source code: org/eclipse/swt/widgets/Combo.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.internal.*;
16 import org.eclipse.swt.internal.gtk.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.events.*;
19
20 /**
21 * Instances of this class are controls that allow the user
22 * to choose an item from a list of items, or optionally
23 * enter a new value by typing it into an editable text
24 * field. Often, <code>Combo</code>s are used in the same place
25 * where a single selection <code>List</code> widget could
26 * be used but space is limited. A <code>Combo</code> takes
27 * less space than a <code>List</code> widget and shows
28 * similar information.
29 * <p>
30 * Note: Since <code>Combo</code>s can contain both a list
31 * and an editable text field, it is possible to confuse methods
32 * which access one versus the other (compare for example,
33 * <code>clearSelection()</code> and <code>deselectAll()</code>).
34 * The API documentation is careful to indicate either "the
35 * receiver's list" or the "the receiver's text field" to
36 * distinguish between the two cases.
37 * </p><p>
38 * Note that although this class is a subclass of <code>Composite</code>,
39 * it does not make sense to add children to it, or set a layout on it.
40 * </p>
41 * <dl>
42 * <dt><b>Styles:</b></dt>
43 * <dd>DROP_DOWN, READ_ONLY, SIMPLE</dd>
44 * <dt><b>Events:</b></dt>
45 * <dd>DefaultSelection, Modify, Selection</dd>
46 * </dl>
47 * <p>
48 * Note: Only one of the styles DROP_DOWN and SIMPLE
49 * may be specified.
50 * </p><p>
51 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
52 * </p>
53 *
54 * @see List
55 */
56 public class Combo extends Composite {
57 long /*int*/ arrowHandle, entryHandle, listHandle;
58 int lastEventTime, visibleCount = 5;
59 String [] items = new String [0];
60 boolean ignoreSelect;
61
62 static final int INNER_BORDER = 2;
63
64 /**
65 * the operating system limit for the number of characters
66 * that the text field in an instance of this class can hold
67 */
68 public final static int LIMIT;
69
70 /*
71 * These values can be different on different platforms.
72 * Therefore they are not initialized in the declaration
73 * to stop the compiler from inlining.
74 */
75 static {
76 LIMIT = 0xFFFF;
77 }
78
79 /**
80 * Constructs a new instance of this class given its parent
81 * and a style value describing its behavior and appearance.
82 * <p>
83 * The style value is either one of the style constants defined in
84 * class <code>SWT</code> which is applicable to instances of this
85 * class, or must be built by <em>bitwise OR</em>'ing together
86 * (that is, using the <code>int</code> "|" operator) two or more
87 * of those <code>SWT</code> style constants. The class description
88 * lists the style constants that are applicable to the class.
89 * Style bits are also inherited from superclasses.
90 * </p>
91 *
92 * @param parent a composite control which will be the parent of the new instance (cannot be null)
93 * @param style the style of control to construct
94 *
95 * @exception IllegalArgumentException <ul>
96 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
97 * </ul>
98 * @exception SWTException <ul>
99 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
100 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
101 * </ul>
102 *
103 * @see SWT#DROP_DOWN
104 * @see SWT#READ_ONLY
105 * @see SWT#SIMPLE
106 * @see Widget#checkSubclass
107 * @see Widget#getStyle
108 */
109 public Combo (Composite parent, int style) {
110 super (parent, checkStyle (style));
111 }
112
113 /**
114 * Adds the argument to the end of the receiver's list.
115 *
116 * @param string the new item
117 *
118 * @exception IllegalArgumentException <ul>
119 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
120 * </ul>
121 * @exception SWTException <ul>
122 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
123 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
124 * </ul>
125 * @exception SWTError <ul>
126 * <li>ERROR_ITEM_NOT_ADDED - if the operation fails because of an operating system failure</li>
127 * </ul>
128 *
129 * @see #add(String,int)
130 */
131 public void add (String string) {
132 checkWidget();
133 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
134 String [] newItems = new String [items.length + 1];
135 System.arraycopy (items, 0, newItems, 0, items.length);
136 newItems [items.length] = string;
137 setItems (newItems, true, true);
138 }
139
140 /**
141 * Adds the argument to the receiver's list at the given
142 * zero-relative index.
143 * <p>
144 * Note: To add an item at the end of the list, use the
145 * result of calling <code>getItemCount()</code> as the
146 * index or use <code>add(String)</code>.
147 * </p>
148 *
149 * @param string the new item
150 * @param index the index for the item
151 *
152 * @exception IllegalArgumentException <ul>
153 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
154 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
155 * </ul>
156 * @exception SWTException <ul>
157 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
158 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
159 * </ul>
160 * @exception SWTError <ul>
161 * <li>ERROR_ITEM_NOT_ADDED - if the operation fails because of an operating system failure</li>
162 * </ul>
163 *
164 * @see #add(String)
165 */
166 public void add (String string, int index) {
167 checkWidget();
168 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
169 if (!(0 <= index && index <= items.length)) {
170 error (SWT.ERROR_INVALID_RANGE);
171 }
172 String [] newItems = new String [items.length + 1];
173 System.arraycopy (items, 0, newItems, 0, index);
174 newItems [index] = string;
175 System.arraycopy (items, index, newItems, index + 1, items.length - index);
176 setItems (newItems, true, true);
177 }
178
179 /**
180 * Adds the listener to the collection of listeners who will
181 * be notified when the receiver's text is modified, by sending
182 * it one of the messages defined in the <code>ModifyListener</code>
183 * interface.
184 *
185 * @param listener the listener which should be notified
186 *
187 * @exception IllegalArgumentException <ul>
188 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
189 * </ul>
190 * @exception SWTException <ul>
191 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
192 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
193 * </ul>
194 *
195 * @see ModifyListener
196 * @see #removeModifyListener
197 */
198 public void addModifyListener (ModifyListener listener) {
199 checkWidget();
200 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
201 TypedListener typedListener = new TypedListener (listener);
202 addListener (SWT.Modify, typedListener);
203 }
204
205 /**
206 * Adds the listener to the collection of listeners who will
207 * be notified when the receiver's selection changes, by sending
208 * it one of the messages defined in the <code>SelectionListener</code>
209 * interface.
210 * <p>
211 * <code>widgetSelected</code> is called when the combo's list selection changes.
212 * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
213 * </p>
214 *
215 * @param listener the listener which should be notified
216 *
217 * @exception IllegalArgumentException <ul>
218 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
219 * </ul>
220 * @exception SWTException <ul>
221 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
222 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
223 * </ul>
224 *
225 * @see SelectionListener
226 * @see #removeSelectionListener
227 * @see SelectionEvent
228 */
229 public void addSelectionListener(SelectionListener listener) {
230 checkWidget();
231 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
232 TypedListener typedListener = new TypedListener (listener);
233 addListener (SWT.Selection,typedListener);
234 addListener (SWT.DefaultSelection,typedListener);
235 }
236
237 static int checkStyle (int style) {
238 /*
239 * Feature in Windows. It is not possible to create
240 * a combo box that has a border using Windows style
241 * bits. All combo boxes draw their own border and
242 * do not use the standard Windows border styles.
243 * Therefore, no matter what style bits are specified,
244 * clear the BORDER bits so that the SWT style will
245 * match the Windows widget.
246 *
247 * The Windows behavior is currently implemented on
248 * all platforms.
249 */
250 style &= ~SWT.BORDER;
251
252 /*
253 * Even though it is legal to create this widget
254 * with scroll bars, they serve no useful purpose
255 * because they do not automatically scroll the
256 * widget's client area. The fix is to clear
257 * the SWT style.
258 */
259 style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
260 style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
261 if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY;
262 return style;
263 }
264
265 /**
266 * Sets the selection in the receiver's text field to an empty
267 * selection starting just before the first character. If the
268 * text field is editable, this has the effect of placing the
269 * i-beam at the start of the text.
270 * <p>
271 * Note: To clear the selected items in the receiver's list,
272 * use <code>deselectAll()</code>.
273 * </p>
274 *
275 * @exception SWTException <ul>
276 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
277 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
278 * </ul>
279 *
280 * @see #deselectAll
281 */
282 public void clearSelection () {
283 checkWidget();
284 int position = OS.gtk_editable_get_position (entryHandle);
285 OS.gtk_editable_select_region (entryHandle, position, position);
286 }
287
288 public Point computeSize (int wHint, int hHint, boolean changed) {
289 checkWidget ();
290 if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
291 if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
292 int[] w = new int [1], h = new int [1];
293 long /*int*/ layout = OS.gtk_entry_get_layout (entryHandle);
294 OS.pango_layout_get_size (layout, w, h);
295 int xborder = INNER_BORDER, yborder = INNER_BORDER;
296 long /*int*/ style = OS.gtk_widget_get_style (entryHandle);
297 xborder += OS.gtk_style_get_xthickness (style);
298 yborder += OS.gtk_style_get_ythickness (style);
299 int [] property = new int [1];
300 OS.gtk_widget_style_get (entryHandle, OS.interior_focus, property, 0);
301 if (property [0] != 0) {
302 OS.gtk_widget_style_get (entryHandle, OS.focus_line_width, property, 0);
303 xborder += property [0];
304 yborder += property [0];
305 }
306 int width = OS.PANGO_PIXELS (w [0]) + xborder * 2;
307 int height = OS.PANGO_PIXELS (h [0]) + yborder * 2;
308
309 GtkRequisition arrowRequesition = new GtkRequisition ();
310 OS.gtk_widget_size_request (arrowHandle, arrowRequesition);
311 GtkRequisition listRequesition = new GtkRequisition ();
312 long /*int*/ listParent = OS.gtk_widget_get_parent (listHandle);
313 OS.gtk_widget_size_request (listParent != 0 ? listParent : listHandle, listRequesition);
314
315 width = Math.max (listRequesition.width, width) + arrowRequesition.width + 4;
316 width = wHint == SWT.DEFAULT ? width : wHint;
317 height = hHint == SWT.DEFAULT ? height : hHint;
318 return new Point (width, height);
319 }
320
321 /**
322 * Copies the selected text.
323 * <p>
324 * The current selection is copied to the clipboard.
325 * </p>
326 *
327 * @exception SWTException <ul>
328 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
329 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
330 * </ul>
331 *
332 * @since 2.1
333 */
334 public void copy () {
335 checkWidget ();
336 OS.gtk_editable_copy_clipboard (entryHandle);
337 }
338
339 void createHandle (int index) {
340 state |= HANDLE | MENU;
341 fixedHandle = OS.gtk_fixed_new ();
342 if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
343 OS.gtk_fixed_set_has_window (fixedHandle, true);
344 handle = OS.gtk_combo_new ();
345 if (handle == 0) error (SWT.ERROR_NO_HANDLES);
346 long /*int*/ parentHandle = parent.parentingHandle ();
347 OS.gtk_container_add (parentHandle, fixedHandle);
348 OS.gtk_container_add (fixedHandle, handle);
349 OS.gtk_widget_show (fixedHandle);
350 OS.gtk_widget_show (handle);
351 GtkCombo combo = new GtkCombo ();
352 OS.memmove (combo, handle);
353 entryHandle = combo.entry;
354 listHandle = combo.list;
355
356 /*
357 * Feature in GTK. There is no API to query the arrow
358 * handle from a combo box although it is possible to
359 * get the list and text field. The arrow handle is needed
360 * to hook events. The fix is to find the first child that is
361 * not the entry or list and assume this is the arrow handle.
362 */
363 long /*int*/ list = OS.gtk_container_get_children (handle);
364 if (list != 0) {
365 int i = 0, count = OS.g_list_length (list);
366 while (i<count) {
367 long /*int*/ childHandle = OS.g_list_nth_data (list, i);
368 if (childHandle != entryHandle && childHandle != listHandle) {
369 arrowHandle = childHandle;
370 break;
371 }
372 i++;
373 }
374 OS.g_list_free (list);
375 }
376
377 boolean editable = (style & SWT.READ_ONLY) == 0;
378 OS.gtk_editable_set_editable (entryHandle, editable);
379 OS.gtk_entry_set_activates_default (entryHandle, true);
380 OS.gtk_combo_disable_activate (handle);
381 OS.gtk_combo_set_case_sensitive (handle, true);
382 }
383
384 /**
385 * Cuts the selected text.
386 * <p>
387 * The current selection is first copied to the
388 * clipboard and then deleted from the widget.
389 * </p>
390 *
391 * @exception SWTException <ul>
392 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
393 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
394 * </ul>
395 *
396 * @since 2.1
397 */
398 public void cut () {
399 checkWidget ();
400 OS.gtk_editable_cut_clipboard (entryHandle);
401 }
402
403 void deregister () {
404 super.deregister ();
405 if (arrowHandle != 0) display.removeWidget (arrowHandle);
406 display.removeWidget (entryHandle);
407 display.removeWidget (listHandle);
408 long /*int*/ imContext = imContext ();
409 if (imContext != 0) display.removeWidget (imContext);
410 }
411
412 boolean filterKey (int keyval, long /*int*/ event) {
413 /*
414 * Bug in GTK. On simplified Chinese, when the IM is open and the user
415 * presses a tab key, focus traversal occurs and the IM stops working.
416 * In order to process keys properly in SWT, if the same key event is
417 * dispatched twice, it is ignored. If the tab key is not dispatched twice,
418 * the IM fails. The fix is to dispatch it.
419 */
420 boolean isTab = keyval == OS.GDK_Tab || keyval == OS.GDK_ISO_Left_Tab;
421 int time = OS.gdk_event_get_time (event);
422 if (time != lastEventTime || isTab) {
423 lastEventTime = time;
424 long /*int*/ imContext = imContext ();
425 if (imContext != 0) {
426 return OS.gtk_im_context_filter_keypress (imContext, event);
427 }
428 }
429 return false;
430 }
431
432 long /*int*/ fontHandle () {
433 if (entryHandle != 0) return entryHandle;
434 return super.fontHandle ();
435 }
436
437 long /*int*/ focusHandle () {
438 if (entryHandle != 0) return entryHandle;
439 return super.focusHandle ();
440 }
441
442 boolean hasFocus () {
443 if (super.hasFocus ()) return true;
444 if (OS.GTK_WIDGET_HAS_FOCUS (entryHandle)) return true;
445 if (OS.GTK_WIDGET_HAS_FOCUS (listHandle)) return true;
446 return false;
447 }
448
449 void hookEvents () {
450 //TODO - fix multiple enter/exit
451 super.hookEvents ();
452 long /*int*/ windowProc2 = display.windowProc2;
453 long /*int*/ windowProc3 = display.windowProc3;
454 OS.g_signal_connect_after (entryHandle, OS.changed, windowProc2, CHANGED);
455 OS.g_signal_connect (entryHandle, OS.activate, windowProc2, ACTIVATE);
456 int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK |
457 OS.GDK_BUTTON_RELEASE_MASK | OS.GDK_ENTER_NOTIFY_MASK |
458 OS.GDK_LEAVE_NOTIFY_MASK;
459 long /*int*/ [] handles = new long /*int*/ [] {arrowHandle, entryHandle, listHandle};
460 for (int i=0; i<handles.length; i++) {
461 long /*int*/ eventHandle = handles [i];
462 if (eventHandle != 0) {
463 /* Connect the mouse signals */
464 OS.gtk_widget_add_events (eventHandle, eventMask);
465 OS.g_signal_connect (eventHandle, OS.button_press_event, windowProc3, BUTTON_PRESS_EVENT);
466 OS.g_signal_connect (eventHandle, OS.button_release_event, windowProc3, BUTTON_RELEASE_EVENT);
467 OS.g_signal_connect (eventHandle, OS.motion_notify_event, windowProc3, MOTION_NOTIFY_EVENT);
468 OS.g_signal_connect (eventHandle, OS.enter_notify_event, windowProc3, ENTER_NOTIFY_EVENT);
469 OS.g_signal_connect (eventHandle, OS.leave_notify_event, windowProc3, LEAVE_NOTIFY_EVENT);
470 /*
471 * Feature in GTK. Events such as mouse move are propagated up
472 * the widget hierarchy and are seen by the parent. This is the
473 * correct GTK behavior but not correct for SWT. The fix is to
474 * hook a signal after and stop the propagation using a negative
475 * event number to distinguish this case.
476 */
477 OS.g_signal_connect_after (eventHandle, OS.button_press_event, windowProc3, -BUTTON_PRESS_EVENT);
478 OS.g_signal_connect_after (eventHandle, OS.button_release_event, windowProc3, -BUTTON_RELEASE_EVENT);
479 OS.g_signal_connect_after (eventHandle, OS.motion_notify_event, windowProc3, -MOTION_NOTIFY_EVENT);
480
481 /* Connect the event_after signal for both key and mouse */
482 if (eventHandle != entryHandle) {
483 OS.g_signal_connect (eventHandle, OS.event_after, windowProc3, EVENT_AFTER);
484 }
485 }
486 }
487 long /*int*/ imContext = imContext ();
488 if (imContext != 0) {
489 OS.g_signal_connect (imContext, OS.commit, windowProc3, COMMIT);
490 int id = OS.g_signal_lookup (OS.commit, OS.gtk_im_context_get_type ());
491 int blockMask = OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
492 OS.g_signal_handlers_block_matched (imContext, blockMask, id, 0, 0, 0, entryHandle);
493 }
494 }
495
496 long /*int*/ imContext () {
497 return OS.GTK_ENTRY_IM_CONTEXT (entryHandle);
498 }
499
500 /**
501 * Deselects the item at the given zero-relative index in the receiver's
502 * list. If the item at the index was already deselected, it remains
503 * deselected. Indices that are out of range are ignored.
504 *
505 * @param index the index of the item to deselect
506 *
507 * @exception SWTException <ul>
508 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
509 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
510 * </ul>
511 */
512 public void deselect (int index) {
513 checkWidget();
514 boolean isSelected = getSelectionIndex () == index;
515 setItems (items, !isSelected, !isSelected);
516 }
517
518 /**
519 * Deselects all selected items in the receiver's list.
520 * <p>
521 * Note: To clear the selection in the receiver's text field,
522 * use <code>clearSelection()</code>.
523 * </p>
524 *
525 * @exception SWTException <ul>
526 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
527 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
528 * </ul>
529 *
530 * @see #clearSelection
531 */
532 public void deselectAll () {
533 checkWidget();
534 setItems (items, false, false);
535 }
536
537 GdkColor getBackgroundColor () {
538 return getBaseColor ();
539 }
540
541 GdkColor getForegroundColor () {
542 return getTextColor ();
543 }
544
545 /**
546 * Returns the item at the given, zero-relative index in the
547 * receiver's list. Throws an exception if the index is out
548 * of range.
549 *
550 * @param index the index of the item to return
551 * @return the item at the given index
552 *
553 * @exception IllegalArgumentException <ul>
554 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
555 * </ul>
556 * @exception SWTException <ul>
557 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
559 * </ul>
560 * @exception SWTError <ul>
561 * <li>ERROR_CANNOT_GET_ITEM - if the operation fails because of an operating system failure</li>
562 * </ul>
563 */
564 public String getItem (int index) {
565 checkWidget();
566 if (!(0 <= index && index < items.length)) {
567 error (SWT.ERROR_INVALID_RANGE);
568 }
569 return items [index];
570 }
571
572 /**
573 * Returns the number of items contained in the receiver's list.
574 *
575 * @return the number of items
576 *
577 * @exception SWTException <ul>
578 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
579 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
580 * </ul>
581 * @exception SWTError <ul>
582 * <li>ERROR_CANNOT_GET_COUNT - if the operation fails because of an operating system failure</li>
583 * </ul>
584 */
585 public int getItemCount () {
586 checkWidget();
587 return items.length;
588 }
589
590 /**
591 * Returns the height of the area which would be used to
592 * display <em>one</em> of the items in the receiver's list.
593 *
594 * @return the height of one item
595 *
596 * @exception SWTException <ul>
597 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
598 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
599 * </ul>
600 * @exception SWTError <ul>
601 * <li>ERROR_CANNOT_GET_ITEM_HEIGHT - if the operation fails because of an operating system failure</li>
602 * </ul>
603 */
604 public int getItemHeight () {
605 checkWidget();
606 return fontHeight (getFontDescription (), listHandle != 0 ? listHandle : handle);
607 }
608
609 /**
610 * Returns an array of <code>String</code>s which are the items
611 * in the receiver's list.
612 * <p>
613 * Note: This is not the actual structure used by the receiver
614 * to maintain its list of items, so modifying the array will
615 * not affect the receiver.
616 * </p>
617 *
618 * @return the items in the receiver's list
619 *
620 * @exception SWTException <ul>
621 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
622 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
623 * </ul>
624 * @exception SWTError <ul>
625 * <li>ERROR_CANNOT_GET_ITEM - if the operation fails because of an operating system failure</li>
626 * </ul>
627 */
628 public String [] getItems () {
629 checkWidget();
630 String [] result = new String [items.length];
631 System.arraycopy (items, 0, result, 0, items.length);
632 return result;
633 }
634
635 /**
636 * Returns the orientation of the receiver.
637 *
638 * @return the orientation style
639 *
640 * @exception SWTException <ul>
641 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
642 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
643 * </ul>
644 *
645 * @since 2.1.2
646 */
647 public int getOrientation () {
648 checkWidget();
649 return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
650 }
651
652 /**
653 * Returns a <code>Point</code> whose x coordinate is the start
654 * of the selection in the receiver's text field, and whose y
655 * coordinate is the end of the selection. The returned values
656 * are zero-relative. An "empty" selection as indicated by
657 * the the x and y coordinates having the same value.
658 *
659 * @return a point representing the selection start and end
660 *
661 * @exception SWTException <ul>
662 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
663 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
664 * </ul>
665 */
666 public Point getSelection () {
667 checkWidget ();
668 int [] start = new int [1];
669 int [] end = new int [1];
670 OS.gtk_editable_get_selection_bounds (entryHandle, start, end);
671 return new Point(start [0], end [0]);
672 }
673
674 /**
675 * Returns the zero-relative index of the item which is currently
676 * selected in the receiver's list, or -1 if no item is selected.
677 *
678 * @return the index of the selected item
679 *
680 * @exception SWTException <ul>
681 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
682 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
683 * </ul>
684 */
685 public int getSelectionIndex () {
686 checkWidget();
687 //NOT RIGHT FOR EDITABLE
688 return indexOf (getText ());
689 }
690
691 /**
692 * Returns a string containing a copy of the contents of the
693 * receiver's text field.
694 *
695 * @return the receiver's text
696 *
697 * @exception SWTException <ul>
698 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
699 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
700 * </ul>
701 */
702 public String getText () {
703 checkWidget();
704 long /*int*/ address = OS.gtk_entry_get_text (entryHandle);
705 int length = OS.strlen (address);
706 byte [] buffer = new byte [length];
707 OS.memmove (buffer, address, length);
708 return new String (Converter.mbcsToWcs (null, buffer));
709 }
710
711 String getText (int start, int stop) {
712 /*
713 * NOTE: The current implementation uses substring ()
714 * which can reference a potentially large character
715 * array.
716 */
717 return getText ().substring (start, stop - 1);
718 }
719
720 /**
721 * Returns the height of the receivers's text field.
722 *
723 * @return the text height
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 * @exception SWTError <ul>
730 * <li>ERROR_CANNOT_GET_ITEM_HEIGHT - if the operation fails because of an operating system failure</li>
731 * </ul>
732 */
733 public int getTextHeight () {
734 checkWidget();
735 return fontHeight (getFontDescription (), entryHandle != 0 ? entryHandle : handle) + 8;
736 }
737
738 /**
739 * Returns the maximum number of characters that the receiver's
740 * text field is capable of holding. If this has not been changed
741 * by <code>setTextLimit()</code>, it will be the constant
742 * <code>Combo.LIMIT</code>.
743 *
744 * @return the text limit
745 *
746 * @exception SWTException <ul>
747 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
748 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
749 * </ul>
750 */
751 public int getTextLimit () {
752 checkWidget();
753 int limit = OS.gtk_entry_get_max_length (entryHandle);
754 return limit == 0 ? LIMIT : limit;
755 }
756
757 /**
758 * Gets the number of items that are visible in the drop
759 * down portion of the receiver's list.
760 *
761 * @return the number of items that are visible
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 * @since 3.0
769 */
770 public int getVisibleItemCount () {
771 checkWidget ();
772 return visibleCount;
773 }
774
775 long /*int*/ gtk_activate (long /*int*/ widget) {
776 postEvent (SWT.DefaultSelection);
777 return 0;
778 }
779
780 long /*int*/ gtk_changed (long /*int*/ widget) {
781 if (!ignoreSelect) {
782 long /*int*/ ptr = OS.gtk_entry_get_text (entryHandle);
783 int length = OS.strlen (ptr);
784 byte [] buffer = new byte [length];
785 OS.memmove (buffer, ptr, length);
786 String text = new String (Converter.mbcsToWcs (null, buffer));
787 for (int i = 0; i < items.length; i++) {
788 if (items [i].equals (text)) {
789 postEvent (SWT.Selection);
790 break;
791 }
792 }
793 }
794 sendEvent (SWT.Modify);
795 return 0;
796 }
797
798 long /*int*/ gtk_commit (long /*int*/ imContext, long /*int*/ text) {
799 if (text == 0) return 0;
800 if (!OS.gtk_editable_get_editable (entryHandle)) return 0;
801 int length = OS.strlen (text);
802 if (length == 0) return 0;
803 byte [] buffer = new byte [length];
804 OS.memmove (buffer, text, length);
805 char [] chars = Converter.mbcsToWcs (null, buffer);
806 char [] newChars = sendIMKeyEvent (SWT.KeyDown, null, chars);
807 if (newChars == null) return 0;
808 OS.g_signal_handlers_block_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, COMMIT);
809 int id = OS.g_signal_lookup (OS.commit, OS.gtk_im_context_get_type ());
810 int mask = OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
811 OS.g_signal_handlers_unblock_matched (imContext, mask, id, 0, 0, 0, entryHandle);
812 if (newChars == chars) {
813 OS.g_signal_emit_by_name (imContext, OS.commit, text);
814 } else {
815 buffer = Converter.wcsToMbcs (null, newChars, true);
816 OS.g_signal_emit_by_name (imContext, OS.commit, buffer);
817 }
818 OS.g_signal_handlers_unblock_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, COMMIT);
819 OS.g_signal_handlers_block_matched (imContext, mask, id, 0, 0, 0, entryHandle);
820 return 0;
821 }
822
823 long /*int*/ gtk_popup_menu (long /*int*/ widget) {
824 int [] x = new int [1], y = new int [1];
825 OS.gdk_window_get_pointer (0, x, y, null);
826 return showMenu (x [0], y [0]) ? 1 : 0;
827 }
828
829 /**
830 * Searches the receiver's list starting at the first item
831 * (index 0) until an item is found that is equal to the
832 * argument, and returns the index of that item. If no item
833 * is found, returns -1.
834 *
835 * @param string the search item
836 * @return the index of the item
837 *
838 * @exception IllegalArgumentException <ul>
839 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
840 * </ul>
841 * @exception SWTException <ul>
842 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
843 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
844 * </ul>
845 */
846 public int indexOf (String string) {
847 checkWidget();
848 return indexOf (string, 0);
849 }
850
851 /**
852 * Searches the receiver's list starting at the given,
853 * zero-relative index until an item is found that is equal
854 * to the argument, and returns the index of that item. If
855 * no item is found or the starting index is out of range,
856 * returns -1.
857 *
858 * @param string the search item
859 * @param start the zero-relative index at which to begin the search
860 * @return the index of the item
861 *
862 * @exception IllegalArgumentException <ul>
863 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
864 * </ul>
865 * @exception SWTException <ul>
866 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
867 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
868 * </ul>
869 */
870 public int indexOf (String string, int start) {
871 checkWidget();
872 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
873 if (!(0 <= start && start < items.length)) return -1;
874 for (int i=start; i<items.length; i++) {
875 if (string.equals(items [i])) return i;
876 }
877 return -1;
878 }
879
880 /**
881 * Pastes text from clipboard.
882 * <p>
883 * The selected text is deleted from the widget
884 * and new text inserted from the clipboard.
885 * </p>
886 *
887 * @exception SWTException <ul>
888 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
889 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
890 * </ul>
891 *
892 * @since 2.1
893 */
894 public void paste () {
895 checkWidget ();
896 OS.gtk_editable_paste_clipboard (entryHandle);
897 }
898
899 long /*int*/ parentingHandle() {
900 return fixedHandle;
901 }
902
903 void register () {
904 super.register ();
905 if (arrowHandle != 0) display.addWidget (arrowHandle, this);
906 display.addWidget (entryHandle, this);
907 display.addWidget (listHandle, this);
908 long /*int*/ imContext = imContext ();
909 if (imContext != 0) display.addWidget (imContext, this);
910 }
911
912 void releaseHandle () {
913 super.releaseHandle ();
914 entryHandle = listHandle = 0;
915 }
916
917 /**
918 * Removes the item from the receiver's list at the given
919 * zero-relative index.
920 *
921 * @param index the index for the item
922 *
923 * @exception IllegalArgumentException <ul>
924 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
925 * </ul>
926 * @exception SWTException <ul>
927 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
928 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
929 * </ul>
930 * @exception SWTError <ul>
931 * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
932 * </ul>
933 */
934 public void remove (int index) {
935 checkWidget();
936 if (!(0 <= index && index < items.length)) {
937 error (SWT.ERROR_INVALID_RANGE);
938 }
939 String [] oldItems = items;
940 String [] newItems = new String [oldItems.length - 1];
941 System.arraycopy (oldItems, 0, newItems, 0, index);
942 System.arraycopy (oldItems, index + 1, newItems, index, oldItems.length - index - 1);
943 setItems (newItems, true, true);
944 }
945
946 /**
947 * Removes the items from the receiver's list which are
948 * between the given zero-relative start and end
949 * indices (inclusive).
950 *
951 * @param start the start of the range
952 * @param end the end of the range
953 *
954 * @exception IllegalArgumentException <ul>
955 * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
956 * </ul>
957 * @exception SWTException <ul>
958 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
959 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
960 * </ul>
961 * @exception SWTError <ul>
962 * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
963 * </ul>
964 */
965 public void remove (int start, int end) {
966 checkWidget();
967 if (start > end) return;
968 if (!(0 <= start && start <= end && end < items.length)) {
969 error (SWT.ERROR_INVALID_RANGE);
970 }
971 String [] oldItems = items;
972 String [] newItems = new String [oldItems.length - (end - start + 1)];
973 System.arraycopy (oldItems, 0, newItems, 0, start);
974 System.arraycopy (oldItems, end + 1, newItems, start, oldItems.length - end - 1);
975 setItems (newItems, true, true);
976 }
977
978 /**
979 * Searches the receiver's list starting at the first item
980 * until an item is found that is equal to the argument,
981 * and removes that item from the list.
982 *
983 * @param string the item to remove
984 *
985 * @exception IllegalArgumentException <ul>
986 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
987 * <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li>
988 * </ul>
989 * @exception SWTException <ul>
990 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
991 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
992 * </ul>
993 * @exception SWTError <ul>
994 * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
995 * </ul>
996 */
997 public void remove (String string) {
998 checkWidget();
999 int index = indexOf (string, 0);
1000 if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
1001 remove (index);
1002}
1003
1004/**
1005 * Removes all of the items from the receiver's list.
1006 * <p>
1007 * @exception SWTException <ul>
1008 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1009 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1010 * </ul>
1011 */
1012public void removeAll () {
1013 checkWidget();
1014 setItems (new String [0], false, false);
1015}
1016
1017/**
1018 * Removes the listener from the collection of listeners who will
1019 * be notified when the receiver's text is modified.
1020 *
1021 * @param listener the listener which should no longer be notified
1022 *
1023 * @exception IllegalArgumentException <ul>
1024 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1025 * </ul>
1026 * @exception SWTException <ul>
1027 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1028 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1029 * </ul>
1030 *
1031 * @see ModifyListener
1032 * @see #addModifyListener
1033 */
1034public void removeModifyListener (ModifyListener listener) {
1035 checkWidget();
1036 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1037 if (eventTable == null) return;
1038 eventTable.unhook (SWT.Modify, listener);
1039}
1040
1041/**
1042 * Removes the listener from the collection of listeners who will
1043 * be notified when the receiver's selection changes.
1044 *
1045 * @param listener the listener which should no longer be notified
1046 *
1047 * @exception IllegalArgumentException <ul>
1048 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1049 * </ul>
1050 * @exception SWTException <ul>
1051 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1052 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1053 * </ul>
1054 *
1055 * @see SelectionListener
1056 * @see #addSelectionListener
1057 */
1058public void removeSelectionListener (SelectionListener listener) {
1059 checkWidget();
1060 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1061 if (eventTable == null) return;
1062 eventTable.unhook (SWT.Selection, listener);
1063 eventTable.unhook (SWT.DefaultSelection,listener);
1064}
1065
1066/**
1067 * Selects the item at the given zero-relative index in the receiver's
1068 * list. If the item at the index was already selected, it remains
1069 * selected. Indices that are out of range are ignored.
1070 *
1071 * @param index the index of the item to select
1072 *
1073 * @exception SWTException <ul>
1074 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1075 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1076 * </ul>
1077 */
1078public void select (int index) {
1079 checkWidget();
1080 if (index < 0 || index >= items.length) return;
1081 setText (items [index]);
1082}
1083
1084void setBackgroundColor (GdkColor color) {
1085 super.setBackgroundColor (color);
1086 if (entryHandle != 0) OS.gtk_widget_modify_base (entryHandle, 0, color);
1087 if (listHandle != 0) OS.gtk_widget_modify_base (listHandle, 0, color);
1088}
1089
1090boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
1091 int newHeight = (resize && (style & SWT.DROP_DOWN) != 0) ? getTextHeight () : height;
1092 return super.setBounds (x, y, width, newHeight, move, resize);
1093}
1094
1095void setFontDescription (long /*int*/ font) {
1096 super.setFontDescription (font);
1097 if (entryHandle != 0) OS.gtk_widget_modify_font (entryHandle, font);
1098 if (listHandle != 0) {
1099 OS.gtk_widget_modify_font (listHandle, font);
1100 long /*int*/ itemsList = OS.gtk_container_get_children (listHandle);
1101 if (itemsList != 0) {
1102 int count = OS.g_list_length (itemsList);
1103 for (int i=count - 1; i>=0; i--) {
1104 long /*int*/ widget = OS.gtk_bin_get_child (OS.g_list_nth_data (itemsList, i));
1105 OS.gtk_widget_modify_font (widget, font);
1106 }
1107 OS.g_list_free (itemsList);
1108 }
1109 }
1110}
1111
1112void setForegroundColor (GdkColor color) {
1113 super.setForegroundColor (color);
1114 if (entryHandle != 0) OS.gtk_widget_modify_text (entryHandle, 0, color);
1115 if (listHandle != 0) {
1116 OS.gtk_widget_modify_text (listHandle, 0, color);
1117 long /*int*/ itemsList = OS.gtk_container_get_children (listHandle);
1118 if (itemsList != 0) {
1119 int count = OS.g_list_length (itemsList);
1120 for (int i=count - 1; i>=0; i--) {
1121 long /*int*/ widget = OS.gtk_bin_get_child (OS.g_list_nth_data (itemsList, i));
1122 OS.gtk_widget_modify_fg (widget, OS.GTK_STATE_NORMAL, color);
1123 }
1124 OS.g_list_free (itemsList);
1125 }
1126 }
1127}
1128
1129/**
1130 * Sets the text of the item in the receiver's list at the given
1131 * zero-relative index to the string argument. This is equivalent
1132 * to <code>remove</code>'ing the old item at the index, and then
1133 * <code>add</code>'ing the new item at that index.
1134 *
1135 * @param index the index for the item
1136 * @param string the new text for the item
1137 *
1138 * @exception IllegalArgumentException <ul>
1139 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
1140 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
1141 * </ul>
1142 * @exception SWTException <ul>
1143 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1144 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1145 * </ul>
1146 * @exception SWTError <ul>
1147 * <li>ERROR_ITEM_NOT_REMOVED - if the remove operation fails because of an operating system failure</li>
1148 * <li>ERROR_ITEM_NOT_ADDED - if the add operation fails because of an operating system failure</li>
1149 * </ul>
1150 */
1151public void setItem (int index, String string) {
1152 checkWidget();
1153 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1154 if (!(0 <= index && index < items.length)) {
1155 error (SWT.ERROR_INVALID_ARGUMENT);
1156 }
1157 items [index] = string;
1158 setItems (items, true, true);
1159}
1160
1161/**
1162 * Sets the receiver's list to be the given array of items.
1163 *
1164 * @param items the array of items
1165 *
1166 * @exception IllegalArgumentException <ul>
1167 * <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
1168 * </ul>
1169 * @exception SWTException <ul>
1170 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1171 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1172 * </ul>
1173 * @exception SWTError <ul>
1174 * <li>ERROR_ITEM_NOT_ADDED - if the operation fails because of an operating system failure</li>
1175 * </ul>
1176 */
1177public void setItems (String [] items) {
1178 checkWidget();
1179 if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
1180 setItems (items, false, false);
1181}
1182
1183void setItems (String [] items, boolean keepText, boolean keepSelection) {
1184 this.items = items;
1185 String text = keepText ? getText() : "";
1186 int selectedIndex = keepSelection ? getSelectionIndex() : -1;
1187 ignoreSelect = true;
1188 if (items.length == 0) {
1189 long /*int*/ itemsList = OS.gtk_container_get_children (listHandle);
1190 if (itemsList != 0) {
1191 int count = OS.g_list_length (itemsList);
1192 for (int i=count - 1; i>=0; i--) {
1193 long /*int*/ widget = OS.g_list_nth_data (itemsList, i);
1194 OS.gtk_container_remove (listHandle, widget);
1195 }
1196 OS.g_list_free (itemsList);
1197 }
1198 } else {
1199 long /*int*/ glist = 0;
1200 for (int i=0; i<items.length; i++) {
1201 String string = items [i];
1202 if (string == null) break;
1203 byte [] buffer = Converter.wcsToMbcs (null, string, true);
1204 long /*int*/ data = OS.g_malloc (buffer.length);
1205 OS.memmove (data, buffer, buffer.length);
1206 glist = OS.g_list_append (glist, data);
1207 }
1208 OS.gtk_combo_set_popdown_strings (handle, glist);
1209 if (glist != 0) {
1210 int count = OS.g_list_length (glist);
1211 for (int i=0; i<count; i++) {
1212 long /*int*/ data = OS.g_list_nth_data (glist, i);
1213 if (data != 0) OS.g_free (data);
1214 }
1215 OS.g_list_free (glist);
1216 }
1217 long /*int*/ itemsList = OS.gtk_container_get_children (listHandle);
1218 if (itemsList != 0) {
1219 long /*int*/ font = getFontDescription ();
1220 GdkColor color = getForegroundColor ();
1221 int count = OS.g_list_length (itemsList);
1222 for (int i=count - 1; i>=0; i--) {
1223 long /*int*/ widget = OS.gtk_bin_get_child (OS.g_list_nth_data (itemsList, i));
1224 OS.gtk_widget_modify_fg (widget, OS.GTK_STATE_NORMAL, color);
1225 OS.gtk_widget_modify_font (widget, font);
1226 }
1227 OS.g_list_free (itemsList);
1228 }
1229 }
1230 OS.gtk_entry_set_text (entryHandle, Converter.wcsToMbcs (null, selectedIndex != -1 ? items [selectedIndex] : text, true));
1231 ignoreSelect = false;
1232}
1233
1234/**
1235 * Sets the orientation of the receiver, which must be one
1236 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1237 * <p>
1238 *
1239 * @param orientation new orientation style
1240 *
1241 * @exception SWTException <ul>
1242 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1243 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1244 * </ul>
1245 *
1246 * @since 2.1.2
1247 */
1248public void setOrientation (int orientation) {
1249 checkWidget();
1250}
1251
1252/**
1253 * Sets the selection in the receiver's text field to the
1254 * range specified by the argument whose x coordinate is the
1255 * start of the selection and whose y coordinate is the end
1256 * of the selection.
1257 *
1258 * @param selection a point representing the new selection start and end
1259 *
1260 * @exception IllegalArgumentException <ul>
1261 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
1262 * </ul>
1263 * @exception SWTException <ul>
1264 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1265 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1266 * </ul>
1267 */
1268public void setSelection (Point selection) {
1269 checkWidget();
1270 if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
1271 OS.gtk_editable_set_position (entryHandle, selection.x);
1272 OS.gtk_editable_select_region (entryHandle, selection.x, selection.y);
1273}
1274
1275/**
1276 * Sets the contents of the receiver's text field to the
1277 * given string.
1278 * <p>
1279 * Note: The text field in a <code>Combo</code> is typically
1280 * only capable of displaying a single line of text. Thus,
1281 * setting the text to a string containing line breaks or
1282 * other special characters will probably cause it to
1283 * display incorrectly.
1284 * </p>
1285 *
1286 * @param string the new text
1287 *
1288 * @exception IllegalArgumentException <ul>
1289 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
1290 * </ul>
1291 * @exception SWTException <ul>
1292 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1293 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1294 * </ul>
1295 */
1296public void setText (String string) {
1297 checkWidget();
1298 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1299 byte [] buffer = Converter.wcsToMbcs (null, string, true);
1300 /*
1301 * Feature in gtk. When text is set in gtk, separate events are fired for the deletion and
1302 * insertion of the text. This is not wrong, but is inconsistent with other platforms. The
1303 * fix is to block the firing of these events and fire them ourselves in a consistent manner.
1304 */
1305 OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
1306 OS.gtk_entry_set_text (entryHandle, buffer);
1307 OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
1308 sendEvent (SWT.Modify);
1309}
1310
1311/**
1312 * Sets the maximum number of characters that the receiver's
1313 * text field is capable of holding to be the argument.
1314 *
1315 * @param limit new text limit
1316 *
1317 * @exception IllegalArgumentException <ul>
1318 * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
1319 * </ul>
1320 * @exception SWTException <ul>
1321 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1322 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1323 * </ul>
1324 */
1325public void setTextLimit (int limit) {
1326 checkWidget();
1327 if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
1328 OS.gtk_entry_set_max_length (entryHandle, limit);
1329}
1330
1331/**
1332 * Sets the number of items that are visible in the drop
1333 * down portion of the receiver's list.
1334 *
1335 * @param count the new number of items to be visible
1336 *
1337 * @exception SWTException <ul>
1338 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1339 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1340 * </ul>
1341 *
1342 * @since 3.0
1343 */
1344public void setVisibleItemCount (int count) {
1345 checkWidget ();
1346 if (count < 0) return;
1347 visibleCount = count;
1348}
1349
1350boolean translateTraversal (GdkEventKey keyEvent) {
1351 int key = keyEvent.keyval;
1352 switch (key) {
1353 case OS.GDK_KP_Enter:
1354 case OS.GDK_Return: {
1355 long /*int*/ imContext = imContext ();
1356 if (imContext != 0) {
1357 long /*int*/ [] preeditString = new long /*int*/ [1];
1358 OS.gtk_im_context_get_preedit_string (imContext, preeditString, null, null);
1359 if (preeditString [0] != 0) {
1360 int lenght = OS.strlen (preeditString [0]);
1361 OS.g_free (preeditString [0]);
1362 if (lenght != 0) return false;
1363 }
1364 }
1365 }
1366 }
1367 return super.translateTraversal (keyEvent);
1368}
1369
1370}