Mercurial > projects > dwt-linux
annotate dwt/widgets/FileDialog.d @ 259:c0d810de7093
Update SWT 3.4M7 to 3.4
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 29 Jun 2008 14:33:38 +0200 |
parents | 5a30aa9820f3 |
children | 07d9ed8927b6 |
rev | line source |
---|---|
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
1 /******************************************************************************* |
259 | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
80 | 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 | |
108 | 10 * Port to the D programming language: |
11 * Frank Benoit <benoit@tionex.de> | |
80 | 12 *******************************************************************************/ |
13 module dwt.widgets.FileDialog; | |
14 | |
15 | |
16 | |
17 import dwt.DWT; | |
18 import dwt.DWTException; | |
19 import dwt.internal.gtk.OS; | |
20 import dwt.widgets.Dialog; | |
21 import dwt.widgets.Shell; | |
22 import dwt.widgets.Display; | |
200
08789b28bdf3
import dwt.dwthelper.utils now explicit
Frank Benoit <benoit@tionex.de>
parents:
158
diff
changeset
|
23 import dwt.dwthelper.utils; |
80 | 24 |
25 static import tango.io.FileConst; | |
26 static import tango.text.Util; | |
27 static import tango.text.Text; | |
28 | |
29 /** | |
30 * Instances of this class allow the user to navigate | |
31 * the file system and select or enter a file name. | |
32 * <dl> | |
33 * <dt><b>Styles:</b></dt> | |
34 * <dd>SAVE, OPEN, MULTI</dd> | |
35 * <dt><b>Events:</b></dt> | |
36 * <dd>(none)</dd> | |
37 * </dl> | |
38 * <p> | |
39 * Note: Only one of the styles SAVE and OPEN may be specified. | |
40 * </p><p> | |
41 * IMPORTANT: This class is intended to be subclassed <em>only</em> | |
42 * within the DWT implementation. | |
43 * </p> | |
259 | 44 * |
45 * @see <a href="http://www.eclipse.org/swt/snippets/#filedialog">FileDialog snippets</a> | |
46 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample, Dialog tab</a> | |
47 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
80 | 48 */ |
49 public class FileDialog : Dialog { | |
238 | 50 String [] filterNames; |
51 String [] filterExtensions; | |
52 String filterPath = ""; | |
53 String fileName = ""; | |
54 String[] fileNames; | |
55 String fullPath = ""; | |
240 | 56 int filterIndex = -1; |
57 bool overwrite = false; | |
80 | 58 GtkWidget* handle; |
59 static final char SEPARATOR = tango.io.FileConst.FileConst.PathSeparatorChar; | |
60 static final char EXTENSION_SEPARATOR = ';'; | |
61 | |
62 /** | |
63 * Constructs a new instance of this class given only its parent. | |
64 * | |
65 * @param parent a shell which will be the parent of the new instance | |
66 * | |
67 * @exception IllegalArgumentException <ul> | |
68 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
69 * </ul> | |
70 * @exception DWTException <ul> | |
71 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
72 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
73 * </ul> | |
74 */ | |
75 public this (Shell parent) { | |
240 | 76 this (parent, DWT.APPLICATION_MODAL); |
80 | 77 } |
78 /** | |
79 * Constructs a new instance of this class given its parent | |
80 * and a style value describing its behavior and appearance. | |
81 * <p> | |
82 * The style value is either one of the style constants defined in | |
83 * class <code>DWT</code> which is applicable to instances of this | |
84 * class, or must be built by <em>bitwise OR</em>'ing together | |
85 * (that is, using the <code>int</code> "|" operator) two or more | |
86 * of those <code>DWT</code> style constants. The class description | |
87 * lists the style constants that are applicable to the class. | |
88 * Style bits are also inherited from superclasses. | |
89 * </p> | |
90 * | |
91 * @param parent a shell which will be the parent of the new instance | |
92 * @param style the style of dialog to construct | |
93 * | |
94 * @exception IllegalArgumentException <ul> | |
95 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
96 * </ul> | |
97 * @exception DWTException <ul> | |
98 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
99 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
100 * </ul> | |
101 */ | |
102 public this (Shell parent, int style) { | |
240 | 103 super (parent, checkStyle (parent, style)); |
80 | 104 checkSubclass (); |
105 } | |
238 | 106 String computeResultChooserDialog () { |
80 | 107 /* MULTI is only valid if the native dialog's action is Open */ |
108 fullPath = null; | |
109 if ((style & (DWT.SAVE | DWT.MULTI)) is DWT.MULTI) { | |
110 auto list = OS.gtk_file_chooser_get_filenames (handle); | |
111 int listLength = OS.g_slist_length (list); | |
238 | 112 fileNames = new String [listLength]; |
80 | 113 auto current = list; |
114 int writePos = 0; | |
115 for (int i = 0; i < listLength; i++) { | |
116 auto name = cast(char*)OS.g_slist_data (current); | |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
117 uint items_written; |
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
118 char* utf8Ptr = OS.g_filename_to_utf8 (name, -1, null, &items_written, null); |
80 | 119 OS.g_free (name); |
120 if (utf8Ptr !is null) { | |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
121 fullPath = utf8Ptr[ 0 .. items_written ].dup; |
80 | 122 int start = tango.text.Util.locatePrior( fullPath, SEPARATOR); |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
123 if( start is fullPath.length ) start = -1; |
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
124 fileNames [writePos++] = fullPath[ start + 1 .. $ ].dup; |
80 | 125 OS.g_free (utf8Ptr); |
126 } | |
127 current = OS.g_slist_next (current); | |
128 } | |
129 if (writePos !is 0 && writePos !is listLength) { | |
238 | 130 String [] validFileNames = new String [writePos]; |
80 | 131 System.arraycopy (fileNames, 0, validFileNames, 0, writePos); |
132 fileNames = validFileNames; | |
133 } | |
134 OS.g_slist_free (list); | |
135 } else { | |
136 auto path = OS.gtk_file_chooser_get_filename (handle); | |
137 if (path !is null) { | |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
138 uint items_written; |
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
139 auto utf8Ptr = OS.g_filename_to_utf8 (path, -1, null, &items_written, null); |
80 | 140 OS.g_free (path); |
141 if (utf8Ptr !is null) { | |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
142 fullPath = utf8Ptr[ 0 .. items_written ].dup; |
238 | 143 fileNames = new String [1]; |
80 | 144 int start = tango.text.Util.locatePrior( fullPath, SEPARATOR); |
145 if( start == fullPath.length ) start = -1; | |
146 fileNames[0] = fullPath[ start + 1 .. $ ]; | |
147 OS.g_free (utf8Ptr); | |
148 } | |
149 } | |
150 } | |
240 | 151 filterIndex = -1; |
152 auto filter = OS.gtk_file_chooser_get_filter (handle); | |
153 if (filter !is null) { | |
154 auto filterNamePtr = OS.gtk_file_filter_get_name (filter); | |
155 if (filterNamePtr !is null) { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
156 String filterName = fromStringz(filterNamePtr).dup; |
240 | 157 //OS.g_free (filterNamePtr); //GTK owns this pointer - do not free |
158 for (int i = 0; i < filterExtensions.length; i++) { | |
159 if (filterNames.length > 0) { | |
160 if (filterNames[i].equals(filterName)) { | |
161 filterIndex = i; | |
162 break; | |
163 } | |
164 } else { | |
165 if (filterExtensions[i].equals(filterName)) { | |
166 filterIndex = i; | |
167 break; | |
168 } | |
169 } | |
170 } | |
171 } | |
172 } | |
80 | 173 if (fullPath !is null) { |
174 int separatorIndex = tango.text.Util.locatePrior( fullPath, SEPARATOR); | |
175 if( separatorIndex is fullPath.length ) separatorIndex = -1; | |
176 fileName = fullPath[separatorIndex + 1 .. $ ]; | |
177 filterPath = fullPath[0 .. separatorIndex ]; | |
178 } | |
179 return fullPath; | |
180 } | |
238 | 181 String computeResultClassicDialog () { |
240 | 182 filterIndex = -1; |
80 | 183 GtkFileSelection* selection = cast(GtkFileSelection*)handle; |
184 auto entry = selection.selection_entry; | |
185 auto entryText = OS.gtk_entry_get_text (entry); | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
186 String txt = fromStringz( entryText ); |
80 | 187 if (txt.length is 0) { |
188 auto fileList = selection.file_list; | |
189 auto listSelection = OS.gtk_tree_view_get_selection (fileList); | |
190 void* model; | |
191 auto selectedList = OS.gtk_tree_selection_get_selected_rows (listSelection, &model); | |
192 if (selectedList is null) return null; | |
193 int listLength = OS.g_list_length (selectedList); | |
194 if (listLength is 0) { | |
195 OS.g_list_free (selectedList); | |
196 return null; | |
197 } | |
198 auto path = OS.g_list_nth_data (selectedList, 0); | |
199 char* ptr; | |
200 GtkTreeIter iter; | |
201 if (OS.gtk_tree_model_get_iter (&model, &iter, path)) { | |
202 OS.gtk_tree_model_get1 (&model, &iter, 0, cast(void**)&ptr); | |
203 } | |
204 for (int i = 0; i < listLength; i++) { | |
205 OS.gtk_tree_path_free (OS.g_list_nth_data (selectedList, i)); | |
206 } | |
207 OS.g_list_free (selectedList); | |
208 if (ptr is null) return null; | |
209 OS.gtk_entry_set_text (entry, ptr); | |
210 OS.g_free (ptr); | |
211 } | |
212 | |
213 auto fileNamePtr = OS.gtk_file_selection_get_filename (handle); | |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
214 uint items_written; |
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
215 auto utf8Ptr = OS.g_filename_to_utf8 (fileNamePtr, -1, null, &items_written, null); |
238 | 216 String osAnswer = utf8Ptr[ 0 .. items_written ].dup; |
80 | 217 OS.g_free (utf8Ptr); |
218 | |
219 if (osAnswer.length is 0) return null; | |
220 int separatorIndex = tango.text.Util.locatePrior( osAnswer, SEPARATOR); | |
221 if (separatorIndex is osAnswer.length ) separatorIndex = -1; | |
222 if (separatorIndex+1 is osAnswer.length ) return null; | |
223 | |
238 | 224 String answer = fullPath = osAnswer; |
80 | 225 fileName = fullPath[ separatorIndex+1 .. $ ]; |
226 filterPath = fullPath[ 0 .. separatorIndex ]; | |
227 if ((style & DWT.MULTI) is 0) { | |
228 fileNames = [ fileName ]; | |
229 } else { | |
230 auto namesPtr = OS.gtk_file_selection_get_selections (handle); | |
231 auto namesPtr1 = namesPtr; | |
232 char* namePtr = namesPtr1[0]; | |
233 int length_ = 0; | |
234 while (namePtr !is null) { | |
235 length_++; | |
236 namePtr = namesPtr1[length_]; | |
237 } | |
238 | 238 fileNames = new String[](length_); |
80 | 239 for (int i = 0; i < length_; i++) { |
125
1feb02b24d1c
Fix in FileDialog string convertion
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
240 utf8Ptr = OS.g_filename_to_utf8 (namesPtr [i], -1, null, &items_written, null); |
238 | 241 String name = utf8Ptr[ 0 .. items_written ].dup; |
80 | 242 int start = tango.text.Util.locatePrior( name, SEPARATOR); |
243 if( start == name.length ) start = -1; | |
244 fileNames [i] = name[ start + 1 .. $ ].dup; | |
245 OS.g_free (utf8Ptr); | |
246 } | |
247 OS.g_strfreev (namesPtr); | |
248 } | |
249 return answer; | |
250 } | |
251 /** | |
252 * Returns the path of the first file that was | |
253 * selected in the dialog relative to the filter path, or an | |
254 * empty string if no such file has been selected. | |
255 * | |
256 * @return the relative path of the file | |
257 */ | |
238 | 258 public String getFileName () { |
80 | 259 return fileName; |
260 } | |
261 /** | |
262 * Returns a (possibly empty) array with the paths of all files | |
263 * that were selected in the dialog relative to the filter path. | |
264 * | |
265 * @return the relative paths of the files | |
266 */ | |
238 | 267 public String [] getFileNames () { |
80 | 268 return fileNames; |
269 } | |
270 /** | |
271 * Returns the file extensions which the dialog will | |
272 * use to filter the files it shows. | |
273 * | |
274 * @return the file extensions filter | |
275 */ | |
238 | 276 public String [] getFilterExtensions () { |
80 | 277 return filterExtensions; |
278 } | |
279 /** | |
240 | 280 * Get the 0-based index of the file extension filter |
281 * which was selected by the user, or -1 if no filter | |
282 * was selected. | |
283 * <p> | |
284 * This is an index into the FilterExtensions array and | |
285 * the FilterNames array. | |
286 * </p> | |
287 * | |
288 * @return index the file extension filter index | |
289 * | |
290 * @see #getFilterExtensions | |
291 * @see #getFilterNames | |
292 * | |
293 * @since 3.4 | |
294 */ | |
295 public int getFilterIndex () { | |
296 return filterIndex; | |
297 } | |
298 /** | |
80 | 299 * Returns the names that describe the filter extensions |
300 * which the dialog will use to filter the files it shows. | |
301 * | |
302 * @return the list of filter names | |
303 */ | |
238 | 304 public String [] getFilterNames () { |
80 | 305 return filterNames; |
306 } | |
307 /** | |
308 * Returns the directory path that the dialog will use, or an empty | |
309 * string if this is not set. File names in this path will appear | |
310 * in the dialog, filtered according to the filter extensions. | |
311 * | |
312 * @return the directory path string | |
313 * | |
314 * @see #setFilterExtensions | |
315 */ | |
238 | 316 public String getFilterPath () { |
80 | 317 return filterPath; |
318 } | |
319 /** | |
240 | 320 * Returns the flag that the dialog will use to |
321 * determine whether to prompt the user for file | |
322 * overwrite if the selected file already exists. | |
323 * | |
324 * @return true if the dialog will prompt for file overwrite, false otherwise | |
325 * | |
326 * @since 3.4 | |
327 */ | |
328 public bool getOverwrite () { | |
329 return overwrite; | |
330 } | |
331 /** | |
80 | 332 * Makes the dialog visible and brings it to the front |
333 * of the display. | |
334 * | |
335 * @return a string describing the absolute path of the first selected file, | |
336 * or null if the dialog was cancelled or an error occurred | |
337 * | |
338 * @exception DWTException <ul> | |
339 * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li> | |
340 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li> | |
341 * </ul> | |
342 */ | |
238 | 343 public String open () { |
80 | 344 bool useChooserDialog = OS.GTK_VERSION >= OS.buildVERSION (2, 4, 10); |
345 if (useChooserDialog) { | |
346 return openChooserDialog (); | |
347 } else { | |
348 return openClassicDialog (); | |
349 } | |
350 } | |
238 | 351 String openChooserDialog () { |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
352 char* titleBytes = toStringz( title ); |
80 | 353 int action = (style & DWT.SAVE) !is 0 ? |
354 OS.GTK_FILE_CHOOSER_ACTION_SAVE : | |
355 OS.GTK_FILE_CHOOSER_ACTION_OPEN; | |
356 auto shellHandle = parent.topHandle (); | |
357 handle = OS.gtk_file_chooser_dialog_new2 ( | |
358 titleBytes, | |
359 shellHandle, | |
360 action, | |
361 OS.GTK_STOCK_CANCEL (), OS.GTK_RESPONSE_CANCEL, | |
362 OS.GTK_STOCK_OK (), OS.GTK_RESPONSE_OK); | |
363 auto pixbufs = OS.gtk_window_get_icon_list (shellHandle); | |
364 if (pixbufs !is null) { | |
365 OS.gtk_window_set_icon_list (handle, pixbufs); | |
366 OS.g_list_free (pixbufs); | |
367 } | |
368 presetChooserDialog (); | |
369 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); | |
370 display.addIdleProc (); | |
238 | 371 String answer = null; |
240 | 372 Dialog oldModal = null; |
373 if (OS.gtk_window_get_modal (handle)) { | |
374 oldModal = display.getModalDialog (); | |
375 display.setModalDialog (this); | |
376 } | |
377 uint signalId = 0; | |
378 uint /*long*/ hookId = 0; | |
379 CallbackData emissionData; | |
380 emissionData.display = display; | |
381 if ((style & DWT.RIGHT_TO_LEFT) !is 0) { | |
382 signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); | |
383 emissionData.data = handle; | |
384 hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); | |
385 } | |
386 int response = OS.gtk_dialog_run (handle); | |
387 if ((style & DWT.RIGHT_TO_LEFT) !is 0) { | |
388 OS.g_signal_remove_emission_hook (signalId, hookId); | |
389 } | |
390 if (OS.gtk_window_get_modal (handle)) { | |
391 display.setModalDialog (oldModal); | |
392 } | |
393 if (response is OS.GTK_RESPONSE_OK) { | |
80 | 394 answer = computeResultChooserDialog (); |
395 } | |
396 display.removeIdleProc (); | |
397 OS.gtk_widget_destroy (handle); | |
398 return answer; | |
399 } | |
238 | 400 String openClassicDialog () { |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
401 char* titleBytes = toStringz( title ); |
80 | 402 handle = OS.gtk_file_selection_new (titleBytes); |
403 if (parent !is null) { | |
404 auto shellHandle = parent.topHandle (); | |
405 OS.gtk_window_set_transient_for (handle, shellHandle); | |
406 auto pixbufs = OS.gtk_window_get_icon_list (shellHandle); | |
407 if (pixbufs !is null) { | |
408 OS.gtk_window_set_icon_list (handle, pixbufs); | |
409 OS.g_list_free (pixbufs); | |
410 } | |
411 } | |
412 presetClassicDialog (); | |
413 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); | |
414 display.addIdleProc (); | |
238 | 415 String answer = null; |
240 | 416 Dialog oldModal = null; |
417 if (OS.gtk_window_get_modal (handle)) { | |
418 oldModal = display.getModalDialog (); | |
419 display.setModalDialog (this); | |
420 } | |
421 int signalId = 0; | |
422 int /*long*/ hookId = 0; | |
423 CallbackData emissionData; | |
424 emissionData.display = display; | |
425 if ((style & DWT.RIGHT_TO_LEFT) !is 0) { | |
426 signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); | |
427 emissionData.data = handle; | |
428 hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); | |
429 } | |
430 int response = OS.gtk_dialog_run (handle); | |
431 if ((style & DWT.RIGHT_TO_LEFT) !is 0) { | |
432 OS.g_signal_remove_emission_hook (signalId, hookId); | |
433 } | |
434 if (OS.gtk_window_get_modal (handle)) { | |
435 display.setModalDialog (oldModal); | |
436 } | |
437 if (response is OS.GTK_RESPONSE_OK) { | |
80 | 438 answer = computeResultClassicDialog (); |
439 } | |
440 display.removeIdleProc (); | |
441 OS.gtk_widget_destroy (handle); | |
442 return answer; | |
443 } | |
444 void presetChooserDialog () { | |
445 /* MULTI is only valid if the native dialog's action is Open */ | |
446 if ((style & (DWT.SAVE | DWT.MULTI)) is DWT.MULTI) { | |
447 OS.gtk_file_chooser_set_select_multiple (handle, true); | |
448 } | |
449 if (filterPath is null) filterPath = ""; | |
450 if (fileName is null) fileName = ""; | |
451 if (filterPath.length > 0) { | |
452 tango.text.Text.Text!(char) stringBuffer = new tango.text.Text.Text!(char)(); | |
453 /* filename must be a full path */ | |
454 if (filterPath[0] !is SEPARATOR) { | |
455 stringBuffer.append (SEPARATOR); | |
456 } | |
457 stringBuffer.append (filterPath); | |
240 | 458 if (fileName.length > 0 && (style & DWT.SAVE) is 0) { |
459 if (filterPath[filterPath.length - 1 ] !is SEPARATOR) { | |
460 stringBuffer.append (SEPARATOR); | |
461 } | |
80 | 462 stringBuffer.append (fileName); |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
463 char* buffer = toStringz( stringBuffer.toString ()); |
240 | 464 /* |
465 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 | |
466 * when setting a file name that is not a true canonical path. | |
467 * The fix is to use the canonical path. | |
468 */ | |
80 | 469 auto ptr = OS.realpath (buffer, null); |
470 if (ptr !is null) { | |
240 | 471 OS.gtk_file_chooser_set_filename (handle, ptr); |
472 OS.g_free (ptr); | |
473 } | |
474 } else { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
475 char* buffer = toStringz( stringBuffer.toString () ); |
240 | 476 /* |
477 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 | |
478 * when setting a file name that is not a true canonical path. | |
479 * The fix is to use the canonical path. | |
480 */ | |
481 auto ptr = OS.realpath (buffer, null); | |
482 if (ptr !is null) { | |
483 OS.gtk_file_chooser_set_current_folder (handle, ptr); | |
484 OS.g_free (ptr); | |
485 } | |
80 | 486 } |
487 } else { | |
488 if (fileName.length > 0) { | |
489 if (fileName[0] is SEPARATOR) { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
490 char* buffer = toStringz(fileName); |
240 | 491 |
80 | 492 /* |
493 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 | |
494 * when setting a file name that is not a true canonical path. | |
495 * The fix is to use the canonical path. | |
496 */ | |
497 auto ptr = OS.realpath (buffer, null); | |
498 if (ptr !is null) { | |
499 OS.gtk_file_chooser_set_filename (handle, ptr); | |
500 OS.g_free (ptr); | |
501 } | |
502 } | |
503 } | |
504 } | |
505 if ((style & DWT.SAVE) !is 0 && fileName.length > 0) { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
506 char* buffer = toStringz(fileName); |
80 | 507 OS.gtk_file_chooser_set_current_name (handle, buffer); |
508 } | |
240 | 509 if ((style & DWT.SAVE) !is 0) { |
510 if (OS.GTK_VERSION >= OS.buildVERSION (2, 8, 0)) { | |
511 OS.gtk_file_chooser_set_do_overwrite_confirmation (handle, overwrite); | |
512 } | |
513 } | |
80 | 514 |
515 /* Set the extension filters */ | |
516 if (filterNames is null) filterNames = null; | |
517 if (filterExtensions is null) filterExtensions = null; | |
240 | 518 GtkFileFilter* initialFilter = null; |
80 | 519 for (int i = 0; i < filterExtensions.length; i++) { |
520 if (filterExtensions [i] !is null) { | |
521 auto filter = OS.gtk_file_filter_new (); | |
522 if (filterNames.length > i && filterNames [i] !is null) { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
523 char* name = toStringz(filterNames [i]); |
80 | 524 OS.gtk_file_filter_set_name (filter, name); |
525 } else { | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
526 char* name = toStringz(filterExtensions [i]); |
80 | 527 OS.gtk_file_filter_set_name (filter, name); |
528 } | |
529 int start = 0; | |
530 int index = tango.text.Util.locate( filterExtensions [i], EXTENSION_SEPARATOR ); | |
531 while (index !is filterExtensions [i].length ) { | |
238 | 532 String current = filterExtensions [i][ start .. index ]; |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
533 char* filterString = toStringz(current); |
80 | 534 OS.gtk_file_filter_add_pattern (filter, filterString); |
535 start = index + 1; | |
536 index = tango.text.Util.locate( filterExtensions [i], EXTENSION_SEPARATOR, start); | |
537 } | |
238 | 538 String current = filterExtensions [i][ start .. $ ]; |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
539 char* filterString = toStringz(current); |
80 | 540 OS.gtk_file_filter_add_pattern (filter, filterString); |
541 OS.gtk_file_chooser_add_filter (handle, filter); | |
240 | 542 if (i is filterIndex) { |
543 initialFilter = filter; | |
544 } | |
80 | 545 } |
546 } | |
240 | 547 if (initialFilter !is null) { |
548 OS.gtk_file_chooser_set_filter(handle, initialFilter); | |
549 } | |
80 | 550 fullPath = null; |
551 fileNames = null; | |
552 } | |
553 void presetClassicDialog () { | |
554 OS.gtk_file_selection_set_select_multiple(handle, (style & DWT.MULTI) !is 0); | |
555 | |
556 /* Calculate the fully-specified file name and convert to bytes */ | |
557 tango.text.Text.Text!(char) stringBuffer = new tango.text.Text.Text!(char)(); | |
558 if (filterPath is null) { | |
559 filterPath = ""; | |
560 } else { | |
561 if (filterPath.length > 0) { | |
562 stringBuffer.append (filterPath); | |
563 if (filterPath[filterPath.length - 1] !is SEPARATOR) { | |
564 stringBuffer.append (SEPARATOR); | |
565 } | |
566 } | |
567 } | |
568 if (fileName is null) { | |
569 fileName = ""; | |
570 } else { | |
571 stringBuffer.append (fileName); | |
572 } | |
573 fullPath = stringBuffer.toString (); | |
255
5a30aa9820f3
removed tango.stdc.stringz imports and allow null for arrays and string arguments.
Frank Benoit <benoit@tionex.de>
parents:
240
diff
changeset
|
574 auto fileNamePtr = OS.g_filename_from_utf8 (toStringz( fullPath ), -1, null, null, null); |
80 | 575 OS.gtk_file_selection_set_filename (handle, fileNamePtr); |
576 OS.g_free (fileNamePtr); | |
577 | |
578 if (filterNames is null) filterNames = null; | |
579 if (filterExtensions is null) filterExtensions = null; | |
580 fullPath = null; | |
581 fileNames = null; | |
582 } | |
583 /** | |
584 * Set the initial filename which the dialog will | |
585 * select by default when opened to the argument, | |
586 * which may be null. The name will be prefixed with | |
587 * the filter path when one is supplied. | |
588 * | |
589 * @param string the file name | |
590 */ | |
238 | 591 public void setFileName (String string) { |
80 | 592 fileName = string; |
593 } | |
594 /** | |
595 * Set the file extensions which the dialog will | |
596 * use to filter the files it shows to the argument, | |
597 * which may be null. | |
598 * <p> | |
599 * The strings are platform specific. For example, on | |
259 | 600 * some platforms, an extension filter string is typically |
601 * of the form "*.extension", where "*.*" matches all files. | |
602 * For filters with multiple extensions, use semicolon as | |
603 * a separator, e.g. "*.jpg;*.png". | |
80 | 604 * </p> |
605 * | |
606 * @param extensions the file extension filter | |
607 * | |
608 * @see #setFilterNames to specify the user-friendly | |
609 * names corresponding to the extensions | |
610 */ | |
238 | 611 public void setFilterExtensions (String [] extensions) { |
80 | 612 filterExtensions = extensions; |
613 } | |
614 /** | |
240 | 615 * Set the 0-based index of the file extension filter |
616 * which the dialog will use initially to filter the files | |
617 * it shows to the argument. | |
618 * <p> | |
619 * This is an index into the FilterExtensions array and | |
620 * the FilterNames array. | |
621 * </p> | |
622 * | |
623 * @param index the file extension filter index | |
624 * | |
625 * @see #setFilterExtensions | |
626 * @see #setFilterNames | |
627 * | |
628 * @since 3.4 | |
629 */ | |
630 public void setFilterIndex (int index) { | |
631 filterIndex = index; | |
632 } | |
633 /** | |
259 | 634 * Sets the names that describe the filter extensions |
80 | 635 * which the dialog will use to filter the files it shows |
636 * to the argument, which may be null. | |
637 * <p> | |
638 * Each name is a user-friendly short description shown for | |
639 * its corresponding filter. The <code>names</code> array must | |
640 * be the same length as the <code>extensions</code> array. | |
641 * </p> | |
642 * | |
643 * @param names the list of filter names, or null for no filter names | |
644 * | |
645 * @see #setFilterExtensions | |
646 */ | |
238 | 647 public void setFilterNames (String [] names) { |
80 | 648 filterNames = names; |
649 } | |
650 /** | |
651 * Sets the directory path that the dialog will use | |
652 * to the argument, which may be null. File names in this | |
653 * path will appear in the dialog, filtered according | |
654 * to the filter extensions. If the string is null, | |
655 * then the operating system's default filter path | |
656 * will be used. | |
657 * <p> | |
658 * Note that the path string is platform dependent. | |
659 * For convenience, either '/' or '\' can be used | |
660 * as a path separator. | |
661 * </p> | |
662 * | |
663 * @param string the directory path | |
664 * | |
665 * @see #setFilterExtensions | |
666 */ | |
238 | 667 public void setFilterPath (String string) { |
80 | 668 filterPath = string; |
669 } | |
240 | 670 |
671 /** | |
672 * Sets the flag that the dialog will use to | |
673 * determine whether to prompt the user for file | |
674 * overwrite if the selected file already exists. | |
675 * | |
676 * @param overwrite true if the dialog will prompt for file overwrite, false otherwise | |
677 * | |
678 * @since 3.4 | |
679 */ | |
680 public void setOverwrite (bool overwrite) { | |
681 this.overwrite = overwrite; | |
80 | 682 } |
240 | 683 } |