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.List;
|
|
14
|
|
15
|
|
16 import org.eclipse.swt.SWT;
|
|
17 import org.eclipse.swt.internal.gtk.OS;
|
|
18 import org.eclipse.swt.graphics.Point;
|
|
19 import org.eclipse.swt.graphics.Rectangle;
|
|
20 import org.eclipse.swt.events.SelectionListener;
|
|
21 import org.eclipse.swt.events.SelectionEvent;
|
|
22 import org.eclipse.swt.widgets.Scrollable;
|
|
23 import org.eclipse.swt.widgets.Composite;
|
|
24 import org.eclipse.swt.widgets.TypedListener;
|
|
25 import org.eclipse.swt.widgets.Display;
|
|
26 import java.lang.all;
|
|
27
|
48
|
28 version(Tango){
|
25
|
29 import tango.text.convert.Integer;
|
48
|
30 } else { // Phobos
|
|
31 }
|
25
|
32
|
|
33 /**
|
|
34 * Instances of this class represent a selectable user interface
|
|
35 * object that displays a list of strings and issues notification
|
|
36 * when a string is selected. A list may be single or multi select.
|
|
37 * <p>
|
|
38 * <dl>
|
|
39 * <dt><b>Styles:</b></dt>
|
|
40 * <dd>SINGLE, MULTI</dd>
|
|
41 * <dt><b>Events:</b></dt>
|
|
42 * <dd>Selection, DefaultSelection</dd>
|
|
43 * </dl>
|
|
44 * <p>
|
|
45 * Note: Only one of SINGLE and MULTI may be specified.
|
|
46 * </p><p>
|
|
47 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
|
|
48 * </p>
|
|
49 *
|
|
50 * @see <a href="http://www.eclipse.org/swt/snippets/#list">List snippets</a>
|
|
51 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
|
|
52 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
|
|
53 */
|
|
54 public class List : Scrollable {
|
|
55
|
|
56 alias Scrollable.computeSize computeSize;
|
|
57 alias Scrollable.dragDetect dragDetect;
|
|
58 alias Scrollable.setBackgroundColor setBackgroundColor;
|
|
59 alias Scrollable.setBounds setBounds;
|
|
60
|
|
61 GtkWidget* modelHandle;
|
|
62
|
|
63 static final int TEXT_COLUMN = 0;
|
|
64 CallbackData treeSelectionProcCallbackData;
|
|
65
|
|
66 /**
|
|
67 * Constructs a new instance of this class given its parent
|
|
68 * and a style value describing its behavior and appearance.
|
|
69 * <p>
|
|
70 * The style value is either one of the style constants defined in
|
|
71 * class <code>SWT</code> which is applicable to instances of this
|
|
72 * class, or must be built by <em>bitwise OR</em>'ing together
|
|
73 * (that is, using the <code>int</code> "|" operator) two or more
|
|
74 * of those <code>SWT</code> style constants. The class description
|
|
75 * lists the style constants that are applicable to the class.
|
|
76 * Style bits are also inherited from superclasses.
|
|
77 * </p>
|
|
78 *
|
|
79 * @param parent a composite control which will be the parent of the new instance (cannot be null)
|
|
80 * @param style the style of control to construct
|
|
81 *
|
|
82 * @exception IllegalArgumentException <ul>
|
|
83 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
|
|
84 * </ul>
|
|
85 * @exception SWTException <ul>
|
|
86 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
|
|
87 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
|
|
88 * </ul>
|
|
89 *
|
|
90 * @see SWT#SINGLE
|
|
91 * @see SWT#MULTI
|
|
92 * @see Widget#checkSubclass
|
|
93 * @see Widget#getStyle
|
|
94 */
|
|
95 public this (Composite parent, int style) {
|
|
96 super (parent, checkStyle (style));
|
|
97 }
|
|
98
|
|
99 /**
|
|
100 * Adds the argument to the end of the receiver's list.
|
|
101 *
|
|
102 * @param string the new item
|
|
103 *
|
|
104 * @exception SWTException <ul>
|
|
105 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
106 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
107 * </ul>
|
|
108 *
|
|
109 * @see #add(String,int)
|
|
110 */
|
|
111 public void add (String string) {
|
|
112 checkWidget();
|
|
113 // SWT extension: allow null for zero length string
|
|
114 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
115 char* buffer = string.toStringzValidPtr();
|
|
116 GtkTreeIter iter;
|
|
117 OS.gtk_list_store_append (cast(GtkListStore*)modelHandle, &iter);
|
|
118 OS.gtk_list_store_set1 (cast(GtkListStore*)modelHandle, &iter, TEXT_COLUMN, buffer);
|
|
119 }
|
|
120
|
|
121 /**
|
|
122 * Adds the argument to the receiver's list at the given
|
|
123 * zero-relative index.
|
|
124 * <p>
|
|
125 * Note: To add an item at the end of the list, use the
|
|
126 * result of calling <code>getItemCount()</code> as the
|
|
127 * index or use <code>add(String)</code>.
|
|
128 * </p>
|
|
129 *
|
|
130 * @param string the new item
|
|
131 * @param index the index for the item
|
|
132 *
|
|
133 * @exception IllegalArgumentException <ul>
|
|
134 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
|
|
135 * </ul>
|
|
136 * @exception SWTException <ul>
|
|
137 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
138 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
139 * </ul>
|
|
140 *
|
|
141 * @see #add(String)
|
|
142 */
|
|
143 public void add (String string, int index) {
|
|
144 checkWidget();
|
|
145 // SWT extension: allow null for zero length string
|
|
146 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
147 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
148 if (!(0 <= index && index <= count)) {
|
|
149 error (SWT.ERROR_INVALID_RANGE);
|
|
150 }
|
|
151 char* buffer = string.toStringzValidPtr();
|
|
152 GtkTreeIter iter;
|
|
153 /*
|
|
154 * Feature in GTK. It is much faster to append to a list store
|
|
155 * than to insert at the end using gtk_list_store_insert().
|
|
156 */
|
|
157 if (index is count) {
|
|
158 OS.gtk_list_store_append (cast(GtkListStore*)modelHandle, &iter);
|
|
159 } else {
|
|
160 OS.gtk_list_store_insert (cast(GtkListStore*)modelHandle, &iter, index);
|
|
161 }
|
|
162 OS.gtk_list_store_set1 (cast(GtkListStore*)modelHandle, &iter, TEXT_COLUMN, buffer);
|
|
163 }
|
|
164
|
|
165 /**
|
|
166 * Adds the listener to the collection of listeners who will
|
|
167 * be notified when the user changes the receiver's selection, by sending
|
|
168 * it one of the messages defined in the <code>SelectionListener</code>
|
|
169 * interface.
|
|
170 * <p>
|
|
171 * <code>widgetSelected</code> is called when the selection changes.
|
|
172 * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
|
|
173 * </p>
|
|
174 *
|
|
175 * @param listener the listener which should be notified when the user changes the receiver's selection
|
|
176 *
|
|
177 * @exception IllegalArgumentException <ul>
|
|
178 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
179 * </ul>
|
|
180 * @exception SWTException <ul>
|
|
181 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
182 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
183 * </ul>
|
|
184 *
|
|
185 * @see SelectionListener
|
|
186 * @see #removeSelectionListener
|
|
187 * @see SelectionEvent
|
|
188 */
|
|
189 public void addSelectionListener(SelectionListener listener) {
|
|
190 checkWidget();
|
|
191 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
192 TypedListener typedListener = new TypedListener (listener);
|
|
193 addListener (SWT.Selection,typedListener);
|
|
194 addListener (SWT.DefaultSelection,typedListener);
|
|
195 }
|
|
196
|
|
197 static int checkStyle (int style) {
|
|
198 return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
|
|
199 }
|
|
200
|
|
201 override void createHandle (int index) {
|
|
202 state |= HANDLE;
|
|
203 fixedHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
|
|
204 if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
205 OS.gtk_fixed_set_has_window (cast(GtkFixed*)fixedHandle, true);
|
|
206 scrolledHandle = cast(GtkWidget*)OS.gtk_scrolled_window_new (null, null);
|
|
207 if (scrolledHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
208 /*
|
|
209 * Columns:
|
|
210 * 0 - text
|
|
211 */
|
|
212 auto types = [OS.G_TYPE_STRING ()];
|
|
213 modelHandle = cast(GtkWidget*)OS.gtk_list_store_newv (types.length, cast(uint*)types.ptr);
|
|
214 if (modelHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
215 handle = OS.gtk_tree_view_new_with_model (modelHandle);
|
|
216 if (handle is null) error (SWT.ERROR_NO_HANDLES);
|
|
217 auto textRenderer = OS.gtk_cell_renderer_text_new ();
|
|
218 if (textRenderer is null) error (SWT.ERROR_NO_HANDLES);
|
|
219 auto columnHandle = OS.gtk_tree_view_column_new ();
|
|
220 if (columnHandle is null) error (SWT.ERROR_NO_HANDLES);
|
|
221 OS.gtk_tree_view_column_pack_start (cast(GtkTreeViewColumn*)columnHandle, textRenderer, true);
|
|
222 OS.gtk_tree_view_column_add_attribute (cast(GtkTreeViewColumn*)columnHandle, textRenderer, OS.text.ptr, TEXT_COLUMN);
|
|
223 OS.gtk_tree_view_insert_column (cast(GtkTreeView*)handle, columnHandle, index);
|
|
224 OS.gtk_container_add (cast(GtkContainer*)fixedHandle, scrolledHandle);
|
|
225 OS.gtk_container_add (cast(GtkContainer*)scrolledHandle, handle);
|
|
226
|
|
227 int mode = (style & SWT.MULTI) !is 0 ? OS.GTK_SELECTION_MULTIPLE : OS.GTK_SELECTION_BROWSE;
|
|
228 auto selectionHandle = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
229 OS.gtk_tree_selection_set_mode (selectionHandle, mode);
|
|
230 OS.gtk_tree_view_set_headers_visible (cast(GtkTreeView*)handle, false);
|
|
231 int hsp = (style & SWT.H_SCROLL) !is 0 ? OS.GTK_POLICY_AUTOMATIC : OS.GTK_POLICY_NEVER;
|
|
232 int vsp = (style & SWT.V_SCROLL) !is 0 ? OS.GTK_POLICY_AUTOMATIC : OS.GTK_POLICY_NEVER;
|
|
233 OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp);
|
|
234 if ((style & SWT.BORDER) !is 0) OS.gtk_scrolled_window_set_shadow_type (cast(GtkScrolledWindow*)scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
|
|
235 /*
|
|
236 * Bug in GTK. When a treeview is the child of an override shell,
|
|
237 * and if the user has ever invokes the interactive search field,
|
|
238 * and the treeview is disposed on a focus out event, it segment
|
|
239 * faults. The fix is to disable the search field in an override
|
|
240 * shell.
|
|
241 */
|
|
242 if ((getShell ().style & SWT.ON_TOP) !is 0) {
|
|
243 /*
|
|
244 * Bug in GTK. Until GTK 2.6.5, calling gtk_tree_view_set_enable_search(FALSE)
|
|
245 * would prevent the user from being able to type in text to search the tree.
|
|
246 * After 2.6.5, GTK introduced Ctrl+F as being the key binding for interactive
|
|
247 * search. This meant that even if FALSE was passed to enable_search, the user
|
|
248 * can still bring up the search pop up using the keybinding. GTK also introduced
|
|
249 * the notion of passing a -1 to gtk_set_search_column to disable searching
|
|
250 * (including the search key binding). The fix is to use the right calls
|
|
251 * for the right version.
|
|
252 */
|
|
253 if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 5)) {
|
|
254 OS.gtk_tree_view_set_search_column (cast(GtkTreeView*)handle, -1);
|
|
255 } else {
|
|
256 OS.gtk_tree_view_set_enable_search (cast(GtkTreeView*)handle, false);
|
|
257 }
|
|
258 }
|
|
259 }
|
|
260
|
|
261 public override Point computeSize (int wHint, int hHint, bool changed) {
|
|
262 checkWidget ();
|
|
263 if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0;
|
|
264 if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0;
|
|
265 Point size = computeNativeSize (handle, wHint, hHint, changed);
|
|
266 Rectangle trim = computeTrim (0, 0, size.x, size.y);
|
|
267 size.x = trim.width;
|
|
268 size.y = trim.height;
|
|
269 return size;
|
|
270 }
|
|
271
|
|
272 override void deregister() {
|
|
273 super.deregister ();
|
|
274 display.removeWidget (cast(GtkWidget*)OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle));
|
|
275 }
|
|
276
|
|
277 /**
|
|
278 * Deselects the item at the given zero-relative index in the receiver.
|
|
279 * If the item at the index was already deselected, it remains
|
|
280 * deselected. Indices that are out of range are ignored.
|
|
281 *
|
|
282 * @param index the index of the item to deselect
|
|
283 *
|
|
284 * @exception SWTException <ul>
|
|
285 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
286 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
287 * </ul>
|
|
288 */
|
|
289 public void deselect (int index) {
|
|
290 checkWidget();
|
|
291 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) return;
|
|
292 GtkTreeIter iter;
|
|
293 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
294 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
295 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
296 OS.gtk_tree_selection_unselect_iter (selection, &iter);
|
|
297 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
298 }
|
|
299
|
|
300 /**
|
|
301 * Deselects the items at the given zero-relative indices in the receiver.
|
|
302 * If the item at the given zero-relative index in the receiver
|
|
303 * is selected, it is deselected. If the item at the index
|
|
304 * was not selected, it remains deselected. The range of the
|
|
305 * indices is inclusive. Indices that are out of range are ignored.
|
|
306 *
|
|
307 * @param start the start index of the items to deselect
|
|
308 * @param end the end index of the items to deselect
|
|
309 *
|
|
310 * @exception SWTException <ul>
|
|
311 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
312 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
313 * </ul>
|
|
314 */
|
|
315 public void deselect (int start, int end) {
|
|
316 checkWidget();
|
|
317 if (start < 0 && end < 0) return;
|
|
318 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
319 if (start >= count && end >= count) return;
|
|
320 start = Math.min (count - 1, Math.max (0, start));
|
|
321 end = Math.min (count - 1, Math.max (0, end));
|
|
322 GtkTreeIter iter;
|
|
323 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
324 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
325 for (int index=start; index<=end; index++) {
|
|
326 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
327 OS.gtk_tree_selection_unselect_iter (selection, &iter);
|
|
328 }
|
|
329 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
330 }
|
|
331
|
|
332 /**
|
|
333 * Deselects the items at the given zero-relative indices in the receiver.
|
|
334 * If the item at the given zero-relative index in the receiver
|
|
335 * is selected, it is deselected. If the item at the index
|
|
336 * was not selected, it remains deselected. Indices that are out
|
|
337 * of range and duplicate indices are ignored.
|
|
338 *
|
|
339 * @param indices the array of indices for the items to deselect
|
|
340 *
|
|
341 * @exception SWTException <ul>
|
|
342 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
343 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
344 * </ul>
|
|
345 */
|
|
346 public void deselect (int [] indices) {
|
|
347 checkWidget();
|
|
348 // SWT extension: allow null for zero length string
|
|
349 //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
350 GtkTreeIter iter;
|
|
351 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
352 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
353 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
354 for (int i=0; i<indices.length; i++) {
|
|
355 int index = indices [i];
|
|
356 if (index < 0 || index > count - 1) continue;
|
|
357 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
358 OS.gtk_tree_selection_unselect_iter (selection, &iter);
|
|
359 }
|
|
360 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
361 }
|
|
362
|
|
363 /**
|
|
364 * Deselects all selected items in the receiver.
|
|
365 *
|
|
366 * @exception SWTException <ul>
|
|
367 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
368 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
369 * </ul>
|
|
370 */
|
|
371 public void deselectAll () {
|
|
372 checkWidget();
|
|
373 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
374 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
375 OS.gtk_tree_selection_unselect_all (selection);
|
|
376 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
377 }
|
|
378
|
|
379 override bool dragDetect (int x, int y, bool filter, bool* consume) {
|
|
380 bool selected = false;
|
|
381 if (filter) {
|
|
382 GtkTreePath* path;
|
|
383 if (OS.gtk_tree_view_get_path_at_pos (cast(GtkTreeView*)handle, x, y, &path, null, null, null)) {
|
|
384 if (path !is null) {
|
|
385 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
386 if (OS.gtk_tree_selection_path_is_selected (selection, path)) selected = true;
|
|
387 OS.gtk_tree_path_free (path);
|
|
388 }
|
|
389 } else {
|
|
390 return false;
|
|
391 }
|
|
392 }
|
|
393 bool dragDetect = super.dragDetect (x, y, filter, consume);
|
|
394 if (dragDetect && selected && consume !is null) *consume = true;
|
|
395 return dragDetect;
|
|
396 }
|
|
397
|
|
398 override GdkDrawable* eventWindow () {
|
|
399 return paintWindow ();
|
|
400 }
|
|
401
|
|
402 override GdkColor* getBackgroundColor () {
|
|
403 return getBaseColor ();
|
|
404 }
|
|
405
|
|
406 /**
|
|
407 * Returns the zero-relative index of the item which currently
|
|
408 * has the focus in the receiver, or -1 if no item has focus.
|
|
409 *
|
|
410 * @return the index of the selected item
|
|
411 *
|
|
412 * @exception SWTException <ul>
|
|
413 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
414 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
415 * </ul>
|
|
416 */
|
|
417 public int getFocusIndex () {
|
|
418 checkWidget();
|
|
419 GtkTreePath * path;
|
|
420 OS.gtk_tree_view_get_cursor (cast(GtkTreeView*)handle, &path, null);
|
|
421 if (path is null) return -1;
|
|
422 int* indices = OS.gtk_tree_path_get_indices (path);
|
|
423 int index;
|
|
424 if (indices !is null) index = indices[0];
|
|
425 OS.gtk_tree_path_free (path);
|
|
426 return index;
|
|
427 }
|
|
428
|
|
429 GdkColor* getForegroundColor () {
|
|
430 return getTextColor ();
|
|
431 }
|
|
432
|
|
433 /**
|
|
434 * Returns the item at the given, zero-relative index in the
|
|
435 * receiver. Throws an exception if the index is out of range.
|
|
436 *
|
|
437 * @param index the index of the item to return
|
|
438 * @return the item at the given index
|
|
439 *
|
|
440 * @exception IllegalArgumentException <ul>
|
|
441 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
|
|
442 * </ul>
|
|
443 * @exception SWTException <ul>
|
|
444 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
445 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
446 * </ul>
|
|
447 */
|
|
448 public String getItem (int index) {
|
|
449 checkWidget();
|
|
450 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) {
|
|
451 error (SWT.ERROR_INVALID_RANGE);
|
|
452 }
|
|
453 char* ptr;
|
|
454 GtkTreeIter iter;
|
|
455 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
456 OS.gtk_tree_model_get1 (cast(GtkTreeStore*)modelHandle, &iter, 0, cast(void**)&ptr );
|
|
457 if (ptr is null) return null;
|
|
458 String res = fromStringz( ptr ).dup;
|
|
459 OS.g_free (ptr);
|
|
460 return res;
|
|
461 }
|
|
462
|
|
463 /**
|
|
464 * Returns the number of items contained in the receiver.
|
|
465 *
|
|
466 * @return the number of items
|
|
467 *
|
|
468 * @exception SWTException <ul>
|
|
469 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
470 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
471 * </ul>
|
|
472 */
|
|
473 public int getItemCount () {
|
|
474 checkWidget();
|
|
475 return OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
476 }
|
|
477
|
|
478 /**
|
|
479 * Returns the height of the area which would be used to
|
|
480 * display <em>one</em> of the items in the list.
|
|
481 *
|
|
482 * @return the height of one item
|
|
483 *
|
|
484 * @exception SWTException <ul>
|
|
485 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
486 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
487 * </ul>
|
|
488 */
|
|
489 public int getItemHeight () {
|
|
490 checkWidget();
|
|
491 int itemCount = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
492 auto column = OS.gtk_tree_view_get_column (cast(GtkTreeView*)handle, 0);
|
|
493 if (itemCount is 0) {
|
|
494 int w, h;
|
|
495 OS.gtk_tree_view_column_cell_get_size (cast(GtkTreeViewColumn*)column, null, null, null, &w, &h);
|
|
496 return h;
|
|
497 } else {
|
|
498 GtkTreeIter iter;
|
|
499 OS.gtk_tree_model_get_iter_first (cast(GtkTreeStore*)modelHandle, &iter);
|
|
500 OS.gtk_tree_view_column_cell_set_cell_data (cast(GtkTreeViewColumn*)column, modelHandle, &iter, false, false);
|
|
501 int w, h;
|
|
502 OS.gtk_tree_view_column_cell_get_size (cast(GtkTreeViewColumn*)column, null, null, null, &w, &h);
|
|
503 return h;
|
|
504 }
|
|
505 }
|
|
506
|
|
507 /**
|
|
508 * Returns a (possibly empty) array of <code>String</code>s which
|
|
509 * are the items in the receiver.
|
|
510 * <p>
|
|
511 * Note: This is not the actual structure used by the receiver
|
|
512 * to maintain its list of items, so modifying the array will
|
|
513 * not affect the receiver.
|
|
514 * </p>
|
|
515 *
|
|
516 * @return the items in the receiver's list
|
|
517 *
|
|
518 * @exception SWTException <ul>
|
|
519 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
520 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
521 * </ul>
|
|
522 */
|
|
523 public String [] getItems () {
|
|
524 checkWidget();
|
|
525 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
526 char* ptr;
|
|
527 String [] result = new String[]( count );
|
|
528 GtkTreeIter iter;
|
|
529 for (int index=0; index<count; index++) {
|
|
530 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
531 OS.gtk_tree_model_get1 (cast(GtkTreeStore*)modelHandle, &iter, 0, cast(void**)&ptr);
|
|
532 if (ptr !is null) {
|
|
533 String res = fromStringz( ptr ).dup;
|
|
534 OS.g_free (ptr);
|
|
535 result [index] = res;
|
|
536 }
|
|
537 }
|
|
538 return result;
|
|
539 }
|
|
540
|
|
541 /**
|
|
542 * Returns an array of <code>String</code>s that are currently
|
|
543 * selected in the receiver. The order of the items is unspecified.
|
|
544 * An empty array indicates that no items are selected.
|
|
545 * <p>
|
|
546 * Note: This is not the actual structure used by the receiver
|
|
547 * to maintain its selection, so modifying the array will
|
|
548 * not affect the receiver.
|
|
549 * </p>
|
|
550 * @return an array representing the selection
|
|
551 *
|
|
552 * @exception SWTException <ul>
|
|
553 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
554 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
555 * </ul>
|
|
556 */
|
|
557 public String [] getSelection () {
|
|
558 checkWidget();
|
|
559 int [] indices = getSelectionIndices ();
|
|
560 String [] result = new String[](indices.length);
|
|
561 for (int i=0; i<indices.length; i++) {
|
|
562 result [i] = getItem (indices [i]);
|
|
563 }
|
|
564 return result;
|
|
565 }
|
|
566
|
|
567 /**
|
|
568 * Returns the number of selected items contained in the receiver.
|
|
569 *
|
|
570 * @return the number of selected items
|
|
571 *
|
|
572 * @exception SWTException <ul>
|
|
573 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
574 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
575 * </ul>
|
|
576 */
|
|
577 public int getSelectionCount () {
|
|
578 checkWidget();
|
|
579 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
580 if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) {
|
|
581 display.treeSelectionLength = 0;
|
|
582 display.treeSelection = null;
|
|
583 display.doTreeSelectionProcConnect( &treeSelectionProcCallbackData, handle, selection );
|
|
584 return display.treeSelectionLength;
|
|
585 }
|
|
586 return OS.gtk_tree_selection_count_selected_rows (selection);
|
|
587 }
|
|
588
|
|
589 /**
|
|
590 * Returns the zero-relative index of the item which is currently
|
|
591 * selected in the receiver, or -1 if no item is selected.
|
|
592 *
|
|
593 * @return the index of the selected item or -1
|
|
594 *
|
|
595 * @exception SWTException <ul>
|
|
596 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
597 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
598 * </ul>
|
|
599 */
|
|
600 public int getSelectionIndex () {
|
|
601 checkWidget();
|
|
602 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
603 if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) {
|
|
604 int itemCount = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
605 display.treeSelectionLength = 0;
|
|
606 display.treeSelection = new int [itemCount];
|
|
607 display.doTreeSelectionProcConnect( &treeSelectionProcCallbackData, handle, selection );
|
|
608 if (display.treeSelectionLength is 0) return -1;
|
|
609 return display.treeSelection [0];
|
|
610 }
|
|
611 /*
|
|
612 * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults
|
|
613 * in versions smaller than 2.2.4 if the model is NULL. The fix is
|
|
614 * to give a valid pointer instead.
|
|
615 */
|
|
616 int dummy;
|
|
617 int* model = OS.GTK_VERSION < OS.buildVERSION (2, 2, 4) ? &dummy : null;
|
|
618 auto list = OS.gtk_tree_selection_get_selected_rows (selection, cast(void**)model);
|
|
619 if (list !is null) {
|
|
620 int count = OS.g_list_length (list);
|
|
621 int index;
|
|
622 for (int i=0; i<count; i++) {
|
|
623 auto data = OS.g_list_nth_data (list, i);
|
|
624 auto indices = OS.gtk_tree_path_get_indices (data);
|
|
625 if (indices !is null) {
|
|
626 index = indices[0];
|
|
627 break;
|
|
628 }
|
|
629 }
|
|
630 OS.g_list_free (list);
|
|
631 return index;
|
|
632 }
|
|
633 return -1;
|
|
634 }
|
|
635
|
|
636 /**
|
|
637 * Returns the zero-relative indices of the items which are currently
|
|
638 * selected in the receiver. The order of the indices is unspecified.
|
|
639 * The array is empty if no items are selected.
|
|
640 * <p>
|
|
641 * Note: This is not the actual structure used by the receiver
|
|
642 * to maintain its selection, so modifying the array will
|
|
643 * not affect the receiver.
|
|
644 * </p>
|
|
645 * @return the array of indices of the selected items
|
|
646 *
|
|
647 * @exception SWTException <ul>
|
|
648 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
649 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
650 * </ul>
|
|
651 */
|
|
652 public int [] getSelectionIndices () {
|
|
653 checkWidget();
|
|
654 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
655 if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) {
|
|
656 int itemCount = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
657 display.treeSelectionLength = 0;
|
|
658 display.treeSelection = new int [itemCount];
|
|
659 display.doTreeSelectionProcConnect( &treeSelectionProcCallbackData, handle, selection );
|
|
660 if (display.treeSelectionLength is display.treeSelection.length) return display.treeSelection;
|
|
661 int [] result = new int [display.treeSelectionLength];
|
|
662 System.arraycopy (display.treeSelection, 0, result, 0, display.treeSelectionLength);
|
|
663 return result;
|
|
664 }
|
|
665 /*
|
|
666 * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults
|
|
667 * in versions smaller than 2.2.4 if the model is NULL. The fix is
|
|
668 * to give a valid pointer instead.
|
|
669 */
|
|
670 int dummy;
|
|
671 int* model = OS.GTK_VERSION < OS.buildVERSION (2, 2, 4) ? &dummy : null;
|
|
672 auto list = OS.gtk_tree_selection_get_selected_rows (selection, cast(void**)model);
|
|
673 if (list !is null) {
|
|
674 int count = OS.g_list_length (list);
|
|
675 int [] treeSelection = new int [count];
|
|
676 int len = 0;
|
|
677 for (int i=0; i<count; i++) {
|
|
678 auto data = OS.g_list_nth_data (list, i);
|
|
679 auto indices = OS.gtk_tree_path_get_indices (data);
|
|
680 if (indices !is null) {
|
|
681 treeSelection [len] = indices [0];
|
|
682 len++;
|
|
683 }
|
|
684 }
|
|
685 OS.g_list_free (list);
|
|
686 int [] result = treeSelection[0..len].dup;
|
|
687 return result;
|
|
688 }
|
|
689 return [0];
|
|
690 }
|
|
691
|
|
692 /**
|
|
693 * Returns the zero-relative index of the item which is currently
|
|
694 * at the top of the receiver. This index can change when items are
|
|
695 * scrolled or new items are added or removed.
|
|
696 *
|
|
697 * @return the index of the top item
|
|
698 *
|
|
699 * @exception SWTException <ul>
|
|
700 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
701 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
702 * </ul>
|
|
703 */
|
|
704 public int getTopIndex () {
|
|
705 checkWidget();
|
|
706 GtkTreePath* path;
|
|
707 OS.gtk_widget_realize (handle);
|
|
708 if (!OS.gtk_tree_view_get_path_at_pos (cast(GtkTreeView*)handle, 1, 1, &path, null, null, null)) return 0;
|
|
709 if (path is null) return 0;
|
|
710 auto indices = OS.gtk_tree_path_get_indices (path);
|
|
711 int index;
|
|
712 if (indices !is null) index = indices[0];
|
|
713 OS.gtk_tree_path_free (path);
|
|
714 return index;
|
|
715 }
|
|
716
|
|
717 override int /*long*/ gtk_changed (GtkWidget* widget) {
|
|
718 postEvent (SWT.Selection);
|
|
719 return 0;
|
|
720 }
|
|
721
|
|
722 override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* gdkEvent) {
|
|
723 auto result = super.gtk_button_press_event (widget, gdkEvent);
|
|
724 if (result !is 0) return result;
|
|
725 /*
|
|
726 * Feature in GTK. In a multi-select list view, when multiple items are already
|
|
727 * selected, the selection state of the item is toggled and the previous selection
|
|
728 * is cleared. This is not the desired behaviour when bringing up a popup menu.
|
|
729 * Also, when an item is reselected with the right button, the tree view issues
|
|
730 * an unwanted selection event. The workaround is to detect that case and not
|
|
731 * run the default handler when the item is already part of the current selection.
|
|
732 */
|
|
733 int button = gdkEvent.button;
|
|
734 if (button is 3 && gdkEvent.type is OS.GDK_BUTTON_PRESS) {
|
|
735 GtkTreePath* path;
|
|
736 if (OS.gtk_tree_view_get_path_at_pos (cast(GtkTreeView*)handle, cast(int)gdkEvent.x, cast(int)gdkEvent.y, &path, null, null, null)) {
|
|
737 if (path !is null) {
|
|
738 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
739 if (OS.gtk_tree_selection_path_is_selected (selection, path)) result = 1;
|
|
740 OS.gtk_tree_path_free (path);
|
|
741 }
|
|
742 }
|
|
743 }
|
|
744
|
|
745 /*
|
|
746 * Feature in GTK. When the user clicks in a single selection GtkTreeView
|
|
747 * and there are no selected items, the first item is selected automatically
|
|
748 * before the click is processed, causing two selection events. The is fix
|
|
749 * is the set the cursor item to be same as the clicked item to stop the
|
|
750 * widget from automatically selecting the first item.
|
|
751 */
|
|
752 if ((style & SWT.SINGLE) !is 0 && getSelectionCount () is 0) {
|
|
753 GtkTreePath* path;
|
|
754 if (OS.gtk_tree_view_get_path_at_pos (cast(GtkTreeView*)handle, cast(int)gdkEvent.x, cast(int)gdkEvent.y, &path, null, null, null)) {
|
|
755 if (path !is null) {
|
|
756 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
757 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
758 OS.gtk_tree_view_set_cursor (cast(GtkTreeView*)handle, path, null, false);
|
|
759 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
760 OS.gtk_tree_path_free (path);
|
|
761 }
|
|
762 }
|
|
763 }
|
|
764 /*
|
|
765 * Bug in GTK. GTK segments fault, if the GtkTreeView widget is
|
|
766 * not in focus and all items in the widget are disposed before
|
|
767 * it finishes processing a button press. The fix is to give
|
|
768 * focus to the widget before it starts processing the event.
|
|
769 */
|
|
770 if (!OS.GTK_WIDGET_HAS_FOCUS (handle)) {
|
|
771 OS.gtk_widget_grab_focus (handle);
|
|
772 }
|
|
773 return result;
|
|
774 }
|
|
775
|
|
776 override int /*long*/ gtk_key_press_event (GtkWidget* widget, GdkEventKey* keyEvent) {
|
|
777 auto result = super.gtk_key_press_event (widget, keyEvent);
|
|
778 if (result !is 0) return result;
|
|
779 if (OS.GTK_VERSION < OS.buildVERSION (2, 2 ,0)) {
|
|
780 /*
|
|
781 * Feature in GTK 2.0.x. When an item is default selected using
|
|
782 * the return key, GTK does not issue notification. The fix is
|
|
783 * to issue this notification when the return key is pressed.
|
|
784 */
|
|
785 int key = keyEvent.keyval;
|
|
786 switch (key) {
|
|
787 case OS.GDK_Return:
|
|
788 case OS.GDK_KP_Enter: {
|
|
789 postEvent (SWT.DefaultSelection);
|
|
790 break;
|
|
791 }
|
|
792 default:
|
|
793 }
|
|
794 }
|
|
795 return result;
|
|
796 }
|
|
797
|
|
798 override int /*long*/ gtk_popup_menu (GtkWidget* widget) {
|
|
799 auto result = super.gtk_popup_menu (widget);
|
|
800 /*
|
|
801 * Bug in GTK. The context menu for the typeahead in GtkTreeViewer
|
|
802 * opens in the bottom right corner of the screen when Shift+F10
|
|
803 * is pressed and the typeahead window was not visible. The fix is
|
|
804 * to prevent the context menu from opening by stopping the default
|
|
805 * handler.
|
|
806 *
|
|
807 * NOTE: The bug only happens in GTK 2.6.5 and lower.
|
|
808 */
|
|
809 return OS.GTK_VERSION < OS.buildVERSION (2, 6, 5) ? 1 : result;
|
|
810 }
|
|
811
|
|
812 override void gtk_row_activated (GtkTreeView* tree, GtkTreePath* path, GtkTreeViewColumn* column){
|
|
813 postEvent (SWT.DefaultSelection);
|
|
814 }
|
|
815
|
|
816 override void hookEvents () {
|
|
817 super.hookEvents();
|
|
818 auto selection = OS.gtk_tree_view_get_selection(cast(GtkTreeView*)handle);
|
|
819 OS.g_signal_connect_closure (selection, OS.changed.ptr, display.closures [CHANGED], false);
|
|
820 OS.g_signal_connect_closure (handle, OS.row_activated.ptr, display.closures [ROW_ACTIVATED], false);
|
|
821 }
|
|
822
|
|
823 /**
|
|
824 * Gets the index of an item.
|
|
825 * <p>
|
|
826 * The list is searched starting at 0 until an
|
|
827 * item is found that is equal to the search item.
|
|
828 * If no item is found, -1 is returned. Indexing
|
|
829 * is zero based.
|
|
830 *
|
|
831 * @param string the search item
|
|
832 * @return the index of the item
|
|
833 *
|
|
834 * @exception SWTException <ul>
|
|
835 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
836 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
837 * </ul>
|
|
838 */
|
|
839 public int indexOf (String string) {
|
|
840 checkWidget();
|
|
841 return indexOf (string, 0);
|
|
842 }
|
|
843
|
|
844 /**
|
|
845 * Searches the receiver's list starting at the given,
|
|
846 * zero-relative index until an item is found that is equal
|
|
847 * to the argument, and returns the index of that item. If
|
|
848 * no item is found or the starting index is out of range,
|
|
849 * returns -1.
|
|
850 *
|
|
851 * @param string the search item
|
|
852 * @param start the zero-relative index at which to start the search
|
|
853 * @return the index of the item
|
|
854 *
|
|
855 * @exception SWTException <ul>
|
|
856 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
857 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
858 * </ul>
|
|
859 */
|
|
860 public int indexOf (String string, int start) {
|
|
861 checkWidget();
|
|
862 // SWT extension: allow null for zero length string
|
|
863 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
864 String [] items = getItems ();
|
|
865 for (int i=start; i<items.length; i++) {
|
|
866 if (items [i].equals (string)) return i;
|
|
867 }
|
|
868 return -1;
|
|
869 }
|
|
870
|
|
871 /**
|
|
872 * Returns <code>true</code> if the item is selected,
|
|
873 * and <code>false</code> otherwise. Indices out of
|
|
874 * range are ignored.
|
|
875 *
|
|
876 * @param index the index of the item
|
|
877 * @return the selection state of the item at the index
|
|
878 *
|
|
879 * @exception SWTException <ul>
|
|
880 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
881 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
882 * </ul>
|
|
883 */
|
|
884 public bool isSelected (int index) {
|
|
885 checkWidget();
|
|
886 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
887 char* buffer = toStringz(tango.text.convert.Integer.toString(index));
|
|
888 auto path = OS.gtk_tree_path_new_from_string (buffer);
|
|
889 bool answer = cast(bool)OS.gtk_tree_selection_path_is_selected (selection, path);
|
|
890 OS.gtk_tree_path_free (path);
|
|
891 return answer;
|
|
892 }
|
|
893
|
|
894 override GdkDrawable* paintWindow () {
|
|
895 OS.gtk_widget_realize (handle);
|
|
896 return OS.gtk_tree_view_get_bin_window (cast(GtkTreeView*)handle);
|
|
897 }
|
|
898
|
|
899 override void register () {
|
|
900 super.register ();
|
|
901 display.addWidget (cast(GtkWidget*)OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle), this);
|
|
902 }
|
|
903
|
|
904 override void releaseWidget () {
|
|
905 super.releaseWidget ();
|
|
906 if (modelHandle !is null) OS.g_object_unref (modelHandle);
|
|
907 modelHandle = null;
|
|
908 }
|
|
909
|
|
910 /**
|
|
911 * Removes the item from the receiver at the given
|
|
912 * zero-relative index.
|
|
913 *
|
|
914 * @param index the index for the item
|
|
915 *
|
|
916 * @exception IllegalArgumentException <ul>
|
|
917 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
|
|
918 * </ul>
|
|
919 * @exception SWTException <ul>
|
|
920 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
921 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
922 * </ul>
|
|
923 */
|
|
924 public void remove (int index) {
|
|
925 checkWidget();
|
|
926 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) {
|
|
927 error (SWT.ERROR_INVALID_RANGE);
|
|
928 }
|
|
929 GtkTreeIter iter;
|
|
930 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
931 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
932 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
933 OS.gtk_list_store_remove (cast(GtkListStore*)modelHandle, &iter);
|
|
934 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
935 }
|
|
936
|
|
937 /**
|
|
938 * Removes the items from the receiver which are
|
|
939 * between the given zero-relative start and end
|
|
940 * indices (inclusive).
|
|
941 *
|
|
942 * @param start the start of the range
|
|
943 * @param end the end of the range
|
|
944 *
|
|
945 * @exception IllegalArgumentException <ul>
|
|
946 * <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>
|
|
947 * </ul>
|
|
948 * @exception SWTException <ul>
|
|
949 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
950 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
951 * </ul>
|
|
952 */
|
|
953 public void remove (int start, int end) {
|
|
954 checkWidget();
|
|
955 if (start > end) return;
|
|
956 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
957 if (!(0 <= start && start <= end && end < count)) {
|
|
958 error (SWT.ERROR_INVALID_RANGE);
|
|
959 }
|
|
960 GtkTreeIter iter;
|
|
961 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
962 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
963 for (int index=end; index>=start; index--) {
|
|
964 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
965 OS.gtk_list_store_remove (cast(GtkListStore*)modelHandle, &iter);
|
|
966 }
|
|
967 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
968 }
|
|
969
|
|
970 /**
|
|
971 * Searches the receiver's list starting at the first item
|
|
972 * until an item is found that is equal to the argument,
|
|
973 * and removes that item from the list.
|
|
974 *
|
|
975 * @param string the item to remove
|
|
976 *
|
|
977 * @exception IllegalArgumentException <ul>
|
|
978 * <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li>
|
|
979 * </ul>
|
|
980 * @exception SWTException <ul>
|
|
981 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
982 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
983 * </ul>
|
|
984 */
|
|
985 public void remove (String string) {
|
|
986 checkWidget();
|
|
987 // SWT extension: allow null for zero length string
|
|
988 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
989 int index = indexOf (string, 0);
|
|
990 if (index is -1) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
991 remove (index);
|
|
992 }
|
|
993
|
|
994 /**
|
|
995 * Removes the items from the receiver at the given
|
|
996 * zero-relative indices.
|
|
997 *
|
|
998 * @param indices the array of indices of the items
|
|
999 *
|
|
1000 * @exception IllegalArgumentException <ul>
|
|
1001 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
|
|
1002 * </ul>
|
|
1003 * @exception SWTException <ul>
|
|
1004 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1005 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1006 * </ul>
|
|
1007 */
|
|
1008 public void remove (int [] indices) {
|
|
1009 checkWidget();
|
|
1010 // SWT extension: allow null for zero length string
|
|
1011 //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1012 if (indices.length is 0) return;
|
|
1013 int [] newIndices = new int []( indices.length );
|
|
1014 System.arraycopy (indices, 0, newIndices, 0, indices.length);
|
|
1015 sort (newIndices);
|
|
1016 int start = newIndices [newIndices.length - 1], end = newIndices [0];
|
|
1017 int count = getItemCount();
|
|
1018 if (!(0 <= start && start <= end && end < count)) {
|
|
1019 error (SWT.ERROR_INVALID_RANGE);
|
|
1020 }
|
|
1021 GtkTreeIter iter;
|
|
1022 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1023 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1024 int last = -1;
|
|
1025 for (int i=0; i<newIndices.length; i++) {
|
|
1026 int index = newIndices [i];
|
|
1027 if (index !is last) {
|
|
1028 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1029 OS.gtk_list_store_remove (cast(GtkListStore*)modelHandle, &iter);
|
|
1030 last = index;
|
|
1031 }
|
|
1032 }
|
|
1033 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1034 }
|
|
1035
|
|
1036 /**
|
|
1037 * Removes all of the items from the receiver.
|
|
1038 * <p>
|
|
1039 * @exception SWTException <ul>
|
|
1040 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1041 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1042 * </ul>
|
|
1043 */
|
|
1044 public void removeAll () {
|
|
1045 checkWidget();
|
|
1046 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1047 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1048 OS.gtk_list_store_clear (cast(GtkListStore*)modelHandle);
|
|
1049 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1050 }
|
|
1051
|
|
1052 /**
|
|
1053 * Removes the listener from the collection of listeners who will
|
|
1054 * be notified when the user changes the receiver's selection.
|
|
1055 *
|
|
1056 * @param listener the listener which should no longer be notified
|
|
1057 *
|
|
1058 * @exception IllegalArgumentException <ul>
|
|
1059 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
1060 * </ul>
|
|
1061 * @exception SWTException <ul>
|
|
1062 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1063 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1064 * </ul>
|
|
1065 *
|
|
1066 * @see SelectionListener
|
|
1067 * @see #addSelectionListener
|
|
1068 */
|
|
1069 public void removeSelectionListener(SelectionListener listener) {
|
|
1070 checkWidget();
|
|
1071 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1072 if (eventTable is null) return;
|
|
1073 eventTable.unhook (SWT.Selection, listener);
|
|
1074 eventTable.unhook (SWT.DefaultSelection,listener);
|
|
1075 }
|
|
1076
|
|
1077 /**
|
|
1078 * Selects the item at the given zero-relative index in the receiver's
|
|
1079 * list. If the item at the index was already selected, it remains
|
|
1080 * selected. Indices that are out of range are ignored.
|
|
1081 *
|
|
1082 * @param index the index of the item to select
|
|
1083 *
|
|
1084 * @exception SWTException <ul>
|
|
1085 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1086 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1087 * </ul>
|
|
1088 */
|
|
1089 public void select (int index) {
|
|
1090 checkWidget();
|
|
1091 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) return;
|
|
1092 GtkTreeIter iter;
|
|
1093 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1094 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1095 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1096 OS.gtk_tree_selection_select_iter (selection, &iter);
|
|
1097 if ((style & SWT.SINGLE) !is 0) {
|
|
1098 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1099 OS.gtk_tree_view_set_cursor (cast(GtkTreeView*)handle, path, null, false);
|
|
1100 OS.gtk_tree_path_free (path);
|
|
1101 }
|
|
1102 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1103 }
|
|
1104
|
|
1105 /**
|
|
1106 * Selects the items in the range specified by the given zero-relative
|
|
1107 * indices in the receiver. The range of indices is inclusive.
|
|
1108 * The current selection is not cleared before the new items are selected.
|
|
1109 * <p>
|
|
1110 * If an item in the given range is not selected, it is selected.
|
|
1111 * If an item in the given range was already selected, it remains selected.
|
|
1112 * Indices that are out of range are ignored and no items will be selected
|
|
1113 * if start is greater than end.
|
|
1114 * If the receiver is single-select and there is more than one item in the
|
|
1115 * given range, then all indices are ignored.
|
|
1116 *
|
|
1117 * @param start the start of the range
|
|
1118 * @param end the end of the range
|
|
1119 *
|
|
1120 * @exception SWTException <ul>
|
|
1121 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1122 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1123 * </ul>
|
|
1124 *
|
|
1125 * @see List#setSelection(int,int)
|
|
1126 */
|
|
1127 public void select (int start, int end) {
|
|
1128 checkWidget ();
|
|
1129 if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
|
|
1130 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
1131 if (count is 0 || start >= count) return;
|
|
1132 start = Math.max (0, start);
|
|
1133 end = Math.min (end, count - 1);
|
|
1134 GtkTreeIter iter;
|
|
1135 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1136 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1137 for (int index=start; index<=end; index++) {
|
|
1138 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1139 OS.gtk_tree_selection_select_iter (selection, &iter);
|
|
1140 if ((style & SWT.SINGLE) !is 0) {
|
|
1141 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1142 OS.gtk_tree_view_set_cursor (cast(GtkTreeView*)handle, path, null, false);
|
|
1143 OS.gtk_tree_path_free (path);
|
|
1144 }
|
|
1145 }
|
|
1146 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1147 }
|
|
1148
|
|
1149 /**
|
|
1150 * Selects the items at the given zero-relative indices in the receiver.
|
|
1151 * The current selection is not cleared before the new items are selected.
|
|
1152 * <p>
|
|
1153 * If the item at a given index is not selected, it is selected.
|
|
1154 * If the item at a given index was already selected, it remains selected.
|
|
1155 * Indices that are out of range and duplicate indices are ignored.
|
|
1156 * If the receiver is single-select and multiple indices are specified,
|
|
1157 * then all indices are ignored.
|
|
1158 *
|
|
1159 * @param indices the array of indices for the items to select
|
|
1160 *
|
|
1161 * @exception SWTException <ul>
|
|
1162 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1163 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1164 * </ul>
|
|
1165 *
|
|
1166 * @see List#setSelection(int[])
|
|
1167 */
|
|
1168 public void select (int [] indices) {
|
|
1169 checkWidget ();
|
|
1170 // SWT extension: allow null for zero length string
|
|
1171 //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1172 int length = indices.length;
|
|
1173 if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
|
|
1174 GtkTreeIter iter;
|
|
1175 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
1176 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1177 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1178 for (int i=0; i<length; i++) {
|
|
1179 int index = indices [i];
|
|
1180 if (!(0 <= index && index < count)) continue;
|
|
1181 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1182 OS.gtk_tree_selection_select_iter (selection, &iter);
|
|
1183 if ((style & SWT.SINGLE) !is 0) {
|
|
1184 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1185 OS.gtk_tree_view_set_cursor (cast(GtkTreeView*)handle, path, null, false);
|
|
1186 OS.gtk_tree_path_free (path);
|
|
1187 }
|
|
1188 }
|
|
1189 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1190 }
|
|
1191
|
|
1192 /**
|
|
1193 * Selects all of the items in the receiver.
|
|
1194 * <p>
|
|
1195 * If the receiver is single-select, do nothing.
|
|
1196 *
|
|
1197 * @exception SWTException <ul>
|
|
1198 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1199 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1200 * </ul>
|
|
1201 */
|
|
1202 public void selectAll () {
|
|
1203 checkWidget();
|
|
1204 if ((style & SWT.SINGLE) !is 0) return;
|
|
1205 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1206 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1207 OS.gtk_tree_selection_select_all (selection);
|
|
1208 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1209 }
|
|
1210
|
|
1211 void selectFocusIndex (int index) {
|
|
1212 /*
|
|
1213 * Note that this method both selects and sets the focus to the
|
|
1214 * specified index, so any previous selection in the list will be lost.
|
|
1215 * gtk does not provide a way to just set focus to a specified list item.
|
|
1216 */
|
|
1217 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
1218 if (!(0 <= index && index < count)) return;
|
|
1219 GtkTreeIter iter;
|
|
1220 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1221 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1222 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1223 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1224 OS.gtk_tree_view_set_cursor (cast(GtkTreeView*)handle, path, null, false);
|
|
1225 /*
|
|
1226 * Bug in GTK. For some reason, when an event loop is run from
|
|
1227 * within a key pressed handler and a dialog is displayed that
|
|
1228 * contains a GtkTreeView, gtk_tree_view_set_cursor() does
|
|
1229 * not set the cursor or select the item. The fix is to select the
|
|
1230 * item with gtk_tree_selection_select_iter() as well.
|
|
1231 *
|
|
1232 * NOTE: This happens in GTK 2.2.1 and is fixed in GTK 2.2.4.
|
|
1233 */
|
|
1234 OS.gtk_tree_selection_select_iter (selection, &iter);
|
|
1235 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1236 OS.gtk_tree_path_free (path);
|
|
1237 }
|
|
1238
|
|
1239 override void setBackgroundColor (GdkColor* color) {
|
|
1240 super.setBackgroundColor (color);
|
|
1241 OS.gtk_widget_modify_base (handle, 0, color);
|
|
1242 }
|
|
1243
|
|
1244 override int setBounds (int x, int y, int width, int height, bool move, bool resize) {
|
|
1245 int result = super.setBounds (x, y, width, height, move, resize);
|
|
1246 /*
|
|
1247 * Bug on GTK. The tree view sometimes does not get a paint
|
|
1248 * event or resizes to a one pixel square when resized in a new
|
|
1249 * shell that is not visible after any event loop has been run. The
|
|
1250 * problem is intermittent. It doesn't seem to happen the first time
|
|
1251 * a new shell is created. The fix is to ensure the tree view is realized
|
|
1252 * after it has been resized.
|
|
1253 */
|
|
1254 OS.gtk_widget_realize (handle);
|
|
1255 /*
|
|
1256 * Bug in GTK. An empty GtkTreeView fails to repaint the focus rectangle
|
|
1257 * correctly when resized on versions before 2.6.0. The fix is to force
|
|
1258 * the widget to redraw.
|
|
1259 */
|
|
1260 if (OS.GTK_VERSION < OS.buildVERSION (2, 6, 0) && OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null) is 0) {
|
|
1261 redraw (false);
|
|
1262 }
|
|
1263 return result;
|
|
1264 }
|
|
1265
|
|
1266 /**
|
|
1267 * Sets the text of the item in the receiver's list at the given
|
|
1268 * zero-relative index to the string argument.
|
|
1269 *
|
|
1270 * @param index the index for the item
|
|
1271 * @param string the new text for the item
|
|
1272 *
|
|
1273 * @exception IllegalArgumentException <ul>
|
|
1274 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
|
|
1275 * </ul>
|
|
1276 * @exception SWTException <ul>
|
|
1277 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1278 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1279 * </ul>
|
|
1280 */
|
|
1281 public void setItem (int index, String string) {
|
|
1282 checkWidget();
|
|
1283 // SWT extension: allow null for zero length string
|
|
1284 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1285 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) {
|
|
1286 error (SWT.ERROR_INVALID_RANGE);
|
|
1287 }
|
|
1288 GtkTreeIter iter;
|
|
1289 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1290 char* buffer = string.toStringzValidPtr();
|
|
1291 OS.gtk_list_store_set1 (cast(GtkListStore*)modelHandle, &iter, TEXT_COLUMN, buffer);
|
|
1292 }
|
|
1293
|
|
1294 /**
|
|
1295 * Sets the receiver's items to be the given array of items.
|
|
1296 *
|
|
1297 * @param items the array of items
|
|
1298 *
|
|
1299 * @exception IllegalArgumentException <ul>
|
|
1300 * <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li>
|
|
1301 * </ul>
|
|
1302 * @exception SWTException <ul>
|
|
1303 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1304 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1305 * </ul>
|
|
1306 */
|
|
1307 public void setItems (String [] items) {
|
|
1308 checkWidget();
|
|
1309 // SWT extension, allow null a null length list.
|
|
1310 //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1311 for (int i=0; i<items.length; i++) {
|
|
1312 if (items [i] is null) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
1313 }
|
|
1314 auto selection = OS.gtk_tree_view_get_selection (cast(GtkTreeView*)handle);
|
|
1315 OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1316 OS.gtk_list_store_clear (cast(GtkListStore*)modelHandle);
|
|
1317 OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED);
|
|
1318 GtkTreeIter iter;
|
|
1319 for (int i=0; i<items.length; i++) {
|
|
1320 String string = items [i];
|
|
1321 char* buffer = toStringz(string);
|
|
1322 OS.gtk_list_store_append (cast(GtkListStore*)modelHandle, &iter);
|
|
1323 OS.gtk_list_store_set1 (cast(GtkListStore*)modelHandle, &iter, TEXT_COLUMN, buffer);
|
|
1324 }
|
|
1325 }
|
|
1326
|
|
1327 /**
|
|
1328 * Selects the item at the given zero-relative index in the receiver.
|
|
1329 * If the item at the index was already selected, it remains selected.
|
|
1330 * The current selection is first cleared, then the new item is selected.
|
|
1331 * Indices that are out of range are ignored.
|
|
1332 *
|
|
1333 * @param index the index of the item to select
|
|
1334 *
|
|
1335 * @exception SWTException <ul>
|
|
1336 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1337 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1338 * </ul>
|
|
1339 * @see List#deselectAll()
|
|
1340 * @see List#select(int)
|
|
1341 */
|
|
1342 public void setSelection (int index) {
|
|
1343 checkWidget ();
|
|
1344 deselectAll ();
|
|
1345 selectFocusIndex (index);
|
|
1346 showSelection ();
|
|
1347 }
|
|
1348
|
|
1349 /**
|
|
1350 * Selects the items in the range specified by the given zero-relative
|
|
1351 * indices in the receiver. The range of indices is inclusive.
|
|
1352 * The current selection is cleared before the new items are selected.
|
|
1353 * <p>
|
|
1354 * Indices that are out of range are ignored and no items will be selected
|
|
1355 * if start is greater than end.
|
|
1356 * If the receiver is single-select and there is more than one item in the
|
|
1357 * given range, then all indices are ignored.
|
|
1358 *
|
|
1359 * @param start the start index of the items to select
|
|
1360 * @param end the end index of the items to select
|
|
1361 *
|
|
1362 * @exception SWTException <ul>
|
|
1363 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1364 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1365 * </ul>
|
|
1366 *
|
|
1367 * @see List#deselectAll()
|
|
1368 * @see List#select(int,int)
|
|
1369 */
|
|
1370 public void setSelection (int start, int end) {
|
|
1371 checkWidget ();
|
|
1372 deselectAll ();
|
|
1373 if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
|
|
1374 int count = OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null);
|
|
1375 if (count is 0 || start >= count) return;
|
|
1376 start = Math.max (0, start);
|
|
1377 end = Math.min (end, count - 1);
|
|
1378 selectFocusIndex (start);
|
|
1379 if ((style & SWT.MULTI) !is 0) {
|
|
1380 select (start, end);
|
|
1381 }
|
|
1382 showSelection ();
|
|
1383 }
|
|
1384
|
|
1385 /**
|
|
1386 * Selects the items at the given zero-relative indices in the receiver.
|
|
1387 * The current selection is cleared before the new items are selected.
|
|
1388 * <p>
|
|
1389 * Indices that are out of range and duplicate indices are ignored.
|
|
1390 * If the receiver is single-select and multiple indices are specified,
|
|
1391 * then all indices are ignored.
|
|
1392 *
|
|
1393 * @param indices the indices of the items to select
|
|
1394 *
|
|
1395 * @exception SWTException <ul>
|
|
1396 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1397 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1398 * </ul>
|
|
1399 *
|
|
1400 * @see List#deselectAll()
|
|
1401 * @see List#select(int[])
|
|
1402 */
|
|
1403 public void setSelection(int[] indices) {
|
|
1404 checkWidget ();
|
|
1405 // SWT extension: allow null for zero length string
|
|
1406 //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1407 deselectAll ();
|
|
1408 int length = indices.length;
|
|
1409 if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
|
|
1410 selectFocusIndex (indices [0]);
|
|
1411 if ((style & SWT.MULTI) !is 0) {
|
|
1412 select (indices);
|
|
1413 }
|
|
1414 showSelection ();
|
|
1415 }
|
|
1416
|
|
1417 /**
|
|
1418 * Sets the receiver's selection to be the given array of items.
|
|
1419 * The current selection is cleared before the new items are selected.
|
|
1420 * <p>
|
|
1421 * Items that are not in the receiver are ignored.
|
|
1422 * If the receiver is single-select and multiple items are specified,
|
|
1423 * then all items are ignored.
|
|
1424 *
|
|
1425 * @param items the array of items
|
|
1426 *
|
|
1427 * @exception SWTException <ul>
|
|
1428 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1429 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1430 * </ul>
|
|
1431 *
|
|
1432 * @see List#deselectAll()
|
|
1433 * @see List#select(int[])
|
|
1434 * @see List#setSelection(int[])
|
|
1435 */
|
|
1436 public void setSelection (String [] items) {
|
|
1437 checkWidget ();
|
|
1438 // SWT extension: allow null for zero length string
|
|
1439 //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1440 deselectAll ();
|
|
1441 int length = items.length;
|
|
1442 if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
|
|
1443 bool first = true;
|
|
1444 for (int i = 0; i < length; i++) {
|
|
1445 int index = 0;
|
|
1446 String string = items [i];
|
|
1447 if (string !is null) {
|
|
1448 while ((index = indexOf (string, index)) !is -1) {
|
|
1449 if ((style & SWT.MULTI) !is 0) {
|
|
1450 if (first) {
|
|
1451 first = false;
|
|
1452 selectFocusIndex (index);
|
|
1453 } else {
|
|
1454 select (index);
|
|
1455 }
|
|
1456 } else {
|
|
1457 selectFocusIndex (index);
|
|
1458 break;
|
|
1459 }
|
|
1460 index++;
|
|
1461 }
|
|
1462 }
|
|
1463 }
|
|
1464 showSelection ();
|
|
1465 }
|
|
1466
|
|
1467 /**
|
|
1468 * Sets the zero-relative index of the item which is currently
|
|
1469 * at the top of the receiver. This index can change when items
|
|
1470 * are scrolled or new items are added and removed.
|
|
1471 *
|
|
1472 * @param index the index of the top item
|
|
1473 *
|
|
1474 * @exception SWTException <ul>
|
|
1475 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1476 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1477 * </ul>
|
|
1478 */
|
|
1479 public void setTopIndex (int index) {
|
|
1480 checkWidget();
|
|
1481 if (!(0 <= index && index < OS.gtk_tree_model_iter_n_children (cast(GtkTreeStore*)modelHandle, null))) return;
|
|
1482 GtkTreeIter iter;
|
|
1483 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1484 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1485 OS.gtk_tree_view_scroll_to_cell (cast(GtkTreeView*)handle, path, null, true, 0, 0);
|
|
1486 if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 0)) {
|
|
1487 /*
|
|
1488 * Bug in GTK. According to the documentation, gtk_tree_view_scroll_to_cell
|
|
1489 * should vertically scroll the cell to the top if use_align is true and row_align is 0.
|
|
1490 * However, prior to version 2.8 it does not scroll at all. The fix is to determine
|
|
1491 * the new location and use gtk_tree_view_scroll_to_point.
|
|
1492 * If the widget is a pinhead, calling gtk_tree_view_scroll_to_point
|
|
1493 * will have no effect. Therefore, it is still neccessary to call
|
|
1494 * gtk_tree_view_scroll_to_cell.
|
|
1495 */
|
|
1496 OS.gtk_widget_realize (handle);
|
|
1497 GdkRectangle cellRect;
|
|
1498 OS.gtk_tree_view_get_cell_area (cast(GtkTreeView*)handle, path, null, &cellRect);
|
|
1499 int tx, ty;
|
|
1500 OS.gtk_tree_view_widget_to_tree_coords(cast(GtkTreeView*)handle, cellRect.x, cellRect.y, &tx, &ty);
|
|
1501 OS.gtk_tree_view_scroll_to_point (cast(GtkTreeView*)handle, -1, ty);
|
|
1502 }
|
|
1503 OS.gtk_tree_path_free (path);
|
|
1504 }
|
|
1505
|
|
1506 /**
|
|
1507 * Shows the selection. If the selection is already showing in the receiver,
|
|
1508 * this method simply returns. Otherwise, the items are scrolled until
|
|
1509 * the selection is visible.
|
|
1510 *
|
|
1511 * @exception SWTException <ul>
|
|
1512 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
|
|
1513 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1514 * </ul>
|
|
1515 */
|
|
1516 public void showSelection () {
|
|
1517 checkWidget();
|
|
1518 int index = getSelectionIndex ();
|
|
1519 if (index is -1) return;
|
|
1520 GtkTreeIter iter;
|
|
1521 OS.gtk_tree_model_iter_nth_child (cast(GtkTreeStore*)modelHandle, &iter, null, index);
|
|
1522 auto path = OS.gtk_tree_model_get_path (cast(GtkTreeStore*)modelHandle, &iter);
|
|
1523 /*
|
|
1524 * This code intentionally commented.
|
|
1525 * Bug in GTK. According to the documentation, gtk_tree_view_scroll_to_cell
|
|
1526 * should scroll the minimum amount to show the cell if use_align is false.
|
|
1527 * However, what actually happens is the cell is scrolled to the top.
|
|
1528 * The fix is to determine the new location and use gtk_tree_view_scroll_to_point.
|
|
1529 * If the widget is a pinhead, calling gtk_tree_view_scroll_to_point
|
|
1530 * will have no effect. Therefore, it is still neccessary to
|
|
1531 * call gtk_tree_view_scroll_to_cell.
|
|
1532 */
|
|
1533 // OS.gtk_tree_view_scroll_to_cell (handle, path, 0, false, 0, 0);
|
|
1534 OS.gtk_widget_realize (handle);
|
|
1535 GdkRectangle visibleRect;
|
|
1536 OS.gtk_tree_view_get_visible_rect (cast(GtkTreeView*)handle, &visibleRect);
|
|
1537 GdkRectangle cellRect;
|
|
1538 OS.gtk_tree_view_get_cell_area (cast(GtkTreeView*)handle, path, null, &cellRect);
|
|
1539 int tx, ty;
|
|
1540 OS.gtk_tree_view_widget_to_tree_coords(cast(GtkTreeView*)handle, cellRect.x, cellRect.y, &tx, &ty);
|
|
1541 if (ty < visibleRect.y ) {
|
|
1542 OS.gtk_tree_view_scroll_to_cell (cast(GtkTreeView*)handle, path, null, true, 0f, 0f);
|
|
1543 OS.gtk_tree_view_scroll_to_point (cast(GtkTreeView*)handle, -1, ty);
|
|
1544 } else {
|
|
1545 int height = Math.min (visibleRect.height, cellRect.height);
|
|
1546 if (ty + height > visibleRect.y + visibleRect.height) {
|
|
1547 OS.gtk_tree_view_scroll_to_cell (cast(GtkTreeView*)handle, path, null, true, 1f, 0f);
|
|
1548 ty += cellRect.height - visibleRect.height;
|
|
1549 OS.gtk_tree_view_scroll_to_point (cast(GtkTreeView*)handle, -1, ty);
|
|
1550 }
|
|
1551 }
|
|
1552 OS.gtk_tree_path_free (path);
|
|
1553 }
|
|
1554
|
|
1555 override void treeSelectionProc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, int[] selection, int length_) {
|
|
1556 if (selection !is null) {
|
|
1557 auto indices = OS.gtk_tree_path_get_indices (path);
|
|
1558 if (indices !is null) {
|
|
1559 selection [length_] = indices[0];
|
|
1560 }
|
|
1561 }
|
|
1562 return 0;
|
|
1563 }
|
|
1564
|
|
1565 }
|