comparison dwt/widgets/FileDialog.d @ 240:ce446666f5a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Mon, 12 May 2008 19:13:01 +0200
parents 380bad9f6852
children 5a30aa9820f3
comparison
equal deleted inserted replaced
239:06a1f6829310 240:ce446666f5a2
47 String [] filterExtensions; 47 String [] filterExtensions;
48 String filterPath = ""; 48 String filterPath = "";
49 String fileName = ""; 49 String fileName = "";
50 String[] fileNames; 50 String[] fileNames;
51 String fullPath = ""; 51 String fullPath = "";
52 int filterIndex = -1;
53 bool overwrite = false;
52 GtkWidget* handle; 54 GtkWidget* handle;
53 static final char SEPARATOR = tango.io.FileConst.FileConst.PathSeparatorChar; 55 static final char SEPARATOR = tango.io.FileConst.FileConst.PathSeparatorChar;
54 static final char EXTENSION_SEPARATOR = ';'; 56 static final char EXTENSION_SEPARATOR = ';';
55 57
56 /** 58 /**
65 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 67 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
66 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 68 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
67 * </ul> 69 * </ul>
68 */ 70 */
69 public this (Shell parent) { 71 public this (Shell parent) {
70 this (parent, DWT.PRIMARY_MODAL); 72 this (parent, DWT.APPLICATION_MODAL);
71 } 73 }
72 /** 74 /**
73 * Constructs a new instance of this class given its parent 75 * Constructs a new instance of this class given its parent
74 * and a style value describing its behavior and appearance. 76 * and a style value describing its behavior and appearance.
75 * <p> 77 * <p>
92 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 94 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
93 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 95 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
94 * </ul> 96 * </ul>
95 */ 97 */
96 public this (Shell parent, int style) { 98 public this (Shell parent, int style) {
97 super (parent, style); 99 super (parent, checkStyle (parent, style));
98 checkSubclass (); 100 checkSubclass ();
99 } 101 }
100 String computeResultChooserDialog () { 102 String computeResultChooserDialog () {
101 /* MULTI is only valid if the native dialog's action is Open */ 103 /* MULTI is only valid if the native dialog's action is Open */
102 fullPath = null; 104 fullPath = null;
140 fileNames[0] = fullPath[ start + 1 .. $ ]; 142 fileNames[0] = fullPath[ start + 1 .. $ ];
141 OS.g_free (utf8Ptr); 143 OS.g_free (utf8Ptr);
142 } 144 }
143 } 145 }
144 } 146 }
147 filterIndex = -1;
148 auto filter = OS.gtk_file_chooser_get_filter (handle);
149 if (filter !is null) {
150 auto filterNamePtr = OS.gtk_file_filter_get_name (filter);
151 if (filterNamePtr !is null) {
152 String filterName = tango.stdc.stringz.fromStringz(filterNamePtr).dup;
153 //OS.g_free (filterNamePtr); //GTK owns this pointer - do not free
154 for (int i = 0; i < filterExtensions.length; i++) {
155 if (filterNames.length > 0) {
156 if (filterNames[i].equals(filterName)) {
157 filterIndex = i;
158 break;
159 }
160 } else {
161 if (filterExtensions[i].equals(filterName)) {
162 filterIndex = i;
163 break;
164 }
165 }
166 }
167 }
168 }
145 if (fullPath !is null) { 169 if (fullPath !is null) {
146 int separatorIndex = tango.text.Util.locatePrior( fullPath, SEPARATOR); 170 int separatorIndex = tango.text.Util.locatePrior( fullPath, SEPARATOR);
147 if( separatorIndex is fullPath.length ) separatorIndex = -1; 171 if( separatorIndex is fullPath.length ) separatorIndex = -1;
148 fileName = fullPath[separatorIndex + 1 .. $ ]; 172 fileName = fullPath[separatorIndex + 1 .. $ ];
149 filterPath = fullPath[0 .. separatorIndex ]; 173 filterPath = fullPath[0 .. separatorIndex ];
150 } 174 }
151 return fullPath; 175 return fullPath;
152 } 176 }
153 String computeResultClassicDialog () { 177 String computeResultClassicDialog () {
178 filterIndex = -1;
154 GtkFileSelection* selection = cast(GtkFileSelection*)handle; 179 GtkFileSelection* selection = cast(GtkFileSelection*)handle;
155 auto entry = selection.selection_entry; 180 auto entry = selection.selection_entry;
156 auto entryText = OS.gtk_entry_get_text (entry); 181 auto entryText = OS.gtk_entry_get_text (entry);
157 String txt = tango.stdc.stringz.fromStringz( entryText ); 182 String txt = tango.stdc.stringz.fromStringz( entryText );
158 if (txt.length is 0) { 183 if (txt.length is 0) {
246 */ 271 */
247 public String [] getFilterExtensions () { 272 public String [] getFilterExtensions () {
248 return filterExtensions; 273 return filterExtensions;
249 } 274 }
250 /** 275 /**
276 * Get the 0-based index of the file extension filter
277 * which was selected by the user, or -1 if no filter
278 * was selected.
279 * <p>
280 * This is an index into the FilterExtensions array and
281 * the FilterNames array.
282 * </p>
283 *
284 * @return index the file extension filter index
285 *
286 * @see #getFilterExtensions
287 * @see #getFilterNames
288 *
289 * @since 3.4
290 */
291 public int getFilterIndex () {
292 return filterIndex;
293 }
294 /**
251 * Returns the names that describe the filter extensions 295 * Returns the names that describe the filter extensions
252 * which the dialog will use to filter the files it shows. 296 * which the dialog will use to filter the files it shows.
253 * 297 *
254 * @return the list of filter names 298 * @return the list of filter names
255 */ 299 */
265 * 309 *
266 * @see #setFilterExtensions 310 * @see #setFilterExtensions
267 */ 311 */
268 public String getFilterPath () { 312 public String getFilterPath () {
269 return filterPath; 313 return filterPath;
314 }
315 /**
316 * Returns the flag that the dialog will use to
317 * determine whether to prompt the user for file
318 * overwrite if the selected file already exists.
319 *
320 * @return true if the dialog will prompt for file overwrite, false otherwise
321 *
322 * @since 3.4
323 */
324 public bool getOverwrite () {
325 return overwrite;
270 } 326 }
271 /** 327 /**
272 * Makes the dialog visible and brings it to the front 328 * Makes the dialog visible and brings it to the front
273 * of the display. 329 * of the display.
274 * 330 *
307 } 363 }
308 presetChooserDialog (); 364 presetChooserDialog ();
309 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); 365 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent ();
310 display.addIdleProc (); 366 display.addIdleProc ();
311 String answer = null; 367 String answer = null;
312 if (OS.gtk_dialog_run (handle) is OS.GTK_RESPONSE_OK) { 368 Dialog oldModal = null;
369 if (OS.gtk_window_get_modal (handle)) {
370 oldModal = display.getModalDialog ();
371 display.setModalDialog (this);
372 }
373 uint signalId = 0;
374 uint /*long*/ hookId = 0;
375 CallbackData emissionData;
376 emissionData.display = display;
377 if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
378 signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET());
379 emissionData.data = handle;
380 hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null);
381 }
382 int response = OS.gtk_dialog_run (handle);
383 if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
384 OS.g_signal_remove_emission_hook (signalId, hookId);
385 }
386 if (OS.gtk_window_get_modal (handle)) {
387 display.setModalDialog (oldModal);
388 }
389 if (response is OS.GTK_RESPONSE_OK) {
313 answer = computeResultChooserDialog (); 390 answer = computeResultChooserDialog ();
314 } 391 }
315 display.removeIdleProc (); 392 display.removeIdleProc ();
316 OS.gtk_widget_destroy (handle); 393 OS.gtk_widget_destroy (handle);
317 return answer; 394 return answer;
330 } 407 }
331 presetClassicDialog (); 408 presetClassicDialog ();
332 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); 409 Display display = parent !is null ? parent.getDisplay (): Display.getCurrent ();
333 display.addIdleProc (); 410 display.addIdleProc ();
334 String answer = null; 411 String answer = null;
335 if (OS.gtk_dialog_run (handle) is OS.GTK_RESPONSE_OK) { 412 Dialog oldModal = null;
413 if (OS.gtk_window_get_modal (handle)) {
414 oldModal = display.getModalDialog ();
415 display.setModalDialog (this);
416 }
417 int signalId = 0;
418 int /*long*/ hookId = 0;
419 CallbackData emissionData;
420 emissionData.display = display;
421 if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
422 signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET());
423 emissionData.data = handle;
424 hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null);
425 }
426 int response = OS.gtk_dialog_run (handle);
427 if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
428 OS.g_signal_remove_emission_hook (signalId, hookId);
429 }
430 if (OS.gtk_window_get_modal (handle)) {
431 display.setModalDialog (oldModal);
432 }
433 if (response is OS.GTK_RESPONSE_OK) {
336 answer = computeResultClassicDialog (); 434 answer = computeResultClassicDialog ();
337 } 435 }
338 display.removeIdleProc (); 436 display.removeIdleProc ();
339 OS.gtk_widget_destroy (handle); 437 OS.gtk_widget_destroy (handle);
340 return answer; 438 return answer;
351 /* filename must be a full path */ 449 /* filename must be a full path */
352 if (filterPath[0] !is SEPARATOR) { 450 if (filterPath[0] !is SEPARATOR) {
353 stringBuffer.append (SEPARATOR); 451 stringBuffer.append (SEPARATOR);
354 } 452 }
355 stringBuffer.append (filterPath); 453 stringBuffer.append (filterPath);
356 if (filterPath[filterPath.length - 1 ] !is SEPARATOR) { 454 if (fileName.length > 0 && (style & DWT.SAVE) is 0) {
357 stringBuffer.append (SEPARATOR); 455 if (filterPath[filterPath.length - 1 ] !is SEPARATOR) {
358 } 456 stringBuffer.append (SEPARATOR);
359 if (fileName.length > 0) { 457 }
360 stringBuffer.append (fileName); 458 stringBuffer.append (fileName);
361 } else {
362 /* go into the specified directory */
363 stringBuffer.append ('.');
364 }
365 char* buffer = tango.stdc.stringz.toStringz( stringBuffer.toString ()); 459 char* buffer = tango.stdc.stringz.toStringz( stringBuffer.toString ());
366 /* 460 /*
367 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 461 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6
368 * when setting a file name that is not a true canonical path. 462 * when setting a file name that is not a true canonical path.
369 * The fix is to use the canonical path. 463 * The fix is to use the canonical path.
370 */ 464 */
371 auto ptr = OS.realpath (buffer, null); 465 auto ptr = OS.realpath (buffer, null);
372 if (ptr !is null) { 466 if (ptr !is null) {
373 OS.gtk_file_chooser_set_filename (handle, ptr); 467 OS.gtk_file_chooser_set_filename (handle, ptr);
374 OS.g_free (ptr); 468 OS.g_free (ptr);
469 }
470 } else {
471 char* buffer = tango.stdc.stringz.toStringz( stringBuffer.toString () );
472 /*
473 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6
474 * when setting a file name that is not a true canonical path.
475 * The fix is to use the canonical path.
476 */
477 auto ptr = OS.realpath (buffer, null);
478 if (ptr !is null) {
479 OS.gtk_file_chooser_set_current_folder (handle, ptr);
480 OS.g_free (ptr);
481 }
375 } 482 }
376 } else { 483 } else {
377 if (fileName.length > 0) { 484 if (fileName.length > 0) {
378 if (fileName[0] is SEPARATOR) { 485 if (fileName[0] is SEPARATOR) {
379 char* buffer = tango.stdc.stringz.toStringz(fileName); 486 char* buffer = tango.stdc.stringz.toStringz(fileName);
487
380 /* 488 /*
381 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 489 * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6
382 * when setting a file name that is not a true canonical path. 490 * when setting a file name that is not a true canonical path.
383 * The fix is to use the canonical path. 491 * The fix is to use the canonical path.
384 */ 492 */
392 } 500 }
393 if ((style & DWT.SAVE) !is 0 && fileName.length > 0) { 501 if ((style & DWT.SAVE) !is 0 && fileName.length > 0) {
394 char* buffer = tango.stdc.stringz.toStringz(fileName); 502 char* buffer = tango.stdc.stringz.toStringz(fileName);
395 OS.gtk_file_chooser_set_current_name (handle, buffer); 503 OS.gtk_file_chooser_set_current_name (handle, buffer);
396 } 504 }
505 if ((style & DWT.SAVE) !is 0) {
506 if (OS.GTK_VERSION >= OS.buildVERSION (2, 8, 0)) {
507 OS.gtk_file_chooser_set_do_overwrite_confirmation (handle, overwrite);
508 }
509 }
397 510
398 /* Set the extension filters */ 511 /* Set the extension filters */
399 if (filterNames is null) filterNames = null; 512 if (filterNames is null) filterNames = null;
400 if (filterExtensions is null) filterExtensions = null; 513 if (filterExtensions is null) filterExtensions = null;
514 GtkFileFilter* initialFilter = null;
401 for (int i = 0; i < filterExtensions.length; i++) { 515 for (int i = 0; i < filterExtensions.length; i++) {
402 if (filterExtensions [i] !is null) { 516 if (filterExtensions [i] !is null) {
403 auto filter = OS.gtk_file_filter_new (); 517 auto filter = OS.gtk_file_filter_new ();
404 if (filterNames.length > i && filterNames [i] !is null) { 518 if (filterNames.length > i && filterNames [i] !is null) {
405 char* name = tango.stdc.stringz.toStringz(filterNames [i]); 519 char* name = tango.stdc.stringz.toStringz(filterNames [i]);
419 } 533 }
420 String current = filterExtensions [i][ start .. $ ]; 534 String current = filterExtensions [i][ start .. $ ];
421 char* filterString = tango.stdc.stringz.toStringz(current); 535 char* filterString = tango.stdc.stringz.toStringz(current);
422 OS.gtk_file_filter_add_pattern (filter, filterString); 536 OS.gtk_file_filter_add_pattern (filter, filterString);
423 OS.gtk_file_chooser_add_filter (handle, filter); 537 OS.gtk_file_chooser_add_filter (handle, filter);
424 } 538 if (i is filterIndex) {
539 initialFilter = filter;
540 }
541 }
542 }
543 if (initialFilter !is null) {
544 OS.gtk_file_chooser_set_filter(handle, initialFilter);
425 } 545 }
426 fullPath = null; 546 fullPath = null;
427 fileNames = null; 547 fileNames = null;
428 } 548 }
429 void presetClassicDialog () { 549 void presetClassicDialog () {
482 * @see #setFilterNames to specify the user-friendly 602 * @see #setFilterNames to specify the user-friendly
483 * names corresponding to the extensions 603 * names corresponding to the extensions
484 */ 604 */
485 public void setFilterExtensions (String [] extensions) { 605 public void setFilterExtensions (String [] extensions) {
486 filterExtensions = extensions; 606 filterExtensions = extensions;
607 }
608 /**
609 * Set the 0-based index of the file extension filter
610 * which the dialog will use initially to filter the files
611 * it shows to the argument.
612 * <p>
613 * This is an index into the FilterExtensions array and
614 * the FilterNames array.
615 * </p>
616 *
617 * @param index the file extension filter index
618 *
619 * @see #setFilterExtensions
620 * @see #setFilterNames
621 *
622 * @since 3.4
623 */
624 public void setFilterIndex (int index) {
625 filterIndex = index;
487 } 626 }
488 /** 627 /**
489 * Sets the the names that describe the filter extensions 628 * Sets the the names that describe the filter extensions
490 * which the dialog will use to filter the files it shows 629 * which the dialog will use to filter the files it shows
491 * to the argument, which may be null. 630 * to the argument, which may be null.
520 * @see #setFilterExtensions 659 * @see #setFilterExtensions
521 */ 660 */
522 public void setFilterPath (String string) { 661 public void setFilterPath (String string) {
523 filterPath = string; 662 filterPath = string;
524 } 663 }
525 } 664
665 /**
666 * Sets the flag that the dialog will use to
667 * determine whether to prompt the user for file
668 * overwrite if the selected file already exists.
669 *
670 * @param overwrite true if the dialog will prompt for file overwrite, false otherwise
671 *
672 * @since 3.4
673 */
674 public void setOverwrite (bool overwrite) {
675 this.overwrite = overwrite;
676 }
677 }