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