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