comparison dwt/widgets/FileDialog.d @ 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents ab60f3309436
children fd9c62a2998e
comparison
equal deleted inserted replaced
212:ab60f3309436 213:36f5cb12e1a2
41 public class FileDialog : Dialog { 41 public class FileDialog : Dialog {
42 String [] filterNames; 42 String [] filterNames;
43 String [] filterExtensions; 43 String [] filterExtensions;
44 String [] fileNames; 44 String [] fileNames;
45 String filterPath = "", fileName = ""; 45 String filterPath = "", fileName = "";
46 static final String FILTER = "*.*"; 46 int filterIndex = 0;
47 bool overwrite = false;
48 static const String FILTER = "*.*";
47 static int BUFFER_SIZE = 1024 * 32; 49 static int BUFFER_SIZE = 1024 * 32;
48 static bool USE_HOOK; 50 static bool USE_HOOK = true;
51 static this() {
52 /*
53 * Feature in Vista. When OFN_ENABLEHOOK is set in the
54 * save or open file dialog, Vista uses the old XP look
55 * and feel. OFN_ENABLEHOOK is used to grow the file
56 * name buffer in a multi-select file dialog. The fix
57 * is to only use OFN_ENABLEHOOK when the buffer has
58 * overrun.
59 */
60 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
61 USE_HOOK = false;
62 }
63 }
49 64
50 /** 65 /**
51 * Constructs a new instance of this class given only its parent. 66 * Constructs a new instance of this class given only its parent.
52 * 67 *
53 * @param parent a shell which will be the parent of the new instance 68 * @param parent a shell which will be the parent of the new instance
59 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 74 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
60 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 75 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
61 * </ul> 76 * </ul>
62 */ 77 */
63 public this (Shell parent) { 78 public this (Shell parent) {
64 this (parent, DWT.PRIMARY_MODAL); 79 this (parent, DWT.APPLICATION_MODAL);
65 } 80 }
66 81
67 /** 82 /**
68 * Constructs a new instance of this class given its parent 83 * Constructs a new instance of this class given its parent
69 * and a style value describing its behavior and appearance. 84 * and a style value describing its behavior and appearance.
87 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 102 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
88 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 103 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
89 * </ul> 104 * </ul>
90 */ 105 */
91 public this (Shell parent, int style) { 106 public this (Shell parent, int style) {
92 super (parent, style); 107 super (parent, checkStyle (parent, style));
93 checkSubclass (); 108 checkSubclass ();
94 } 109 }
95 110
96 /** 111 /**
97 * Returns the path of the first file that was 112 * Returns the path of the first file that was
123 public String [] getFilterExtensions () { 138 public String [] getFilterExtensions () {
124 return filterExtensions; 139 return filterExtensions;
125 } 140 }
126 141
127 /** 142 /**
143 * Get the 0-based index of the file extension filter
144 * which was selected by the user, or -1 if no filter
145 * was selected.
146 * <p>
147 * This is an index into the FilterExtensions array and
148 * the FilterNames array.
149 * </p>
150 *
151 * @return index the file extension filter index
152 *
153 * @see #getFilterExtensions
154 * @see #getFilterNames
155 *
156 * @since 3.4
157 */
158 public int getFilterIndex () {
159 return filterIndex;
160 }
161
162 /**
128 * Returns the names that describe the filter extensions 163 * Returns the names that describe the filter extensions
129 * which the dialog will use to filter the files it shows. 164 * which the dialog will use to filter the files it shows.
130 * 165 *
131 * @return the list of filter names 166 * @return the list of filter names
132 */ 167 */
143 * 178 *
144 * @see #setFilterExtensions 179 * @see #setFilterExtensions
145 */ 180 */
146 public String getFilterPath () { 181 public String getFilterPath () {
147 return filterPath; 182 return filterPath;
183 }
184
185 /**
186 * Returns the flag that the dialog will use to
187 * determine whether to prompt the user for file
188 * overwrite if the selected file already exists.
189 *
190 * @return true if the dialog will prompt for file overwrite, false otherwise
191 *
192 * @since 3.4
193 */
194 public bool getOverwrite () {
195 return overwrite;
148 } 196 }
149 197
150 private static extern(Windows) uint OFNHookProc (HWND hdlg, uint uiMsg, uint wParam, int lParam) { 198 private static extern(Windows) uint OFNHookProc (HWND hdlg, uint uiMsg, uint wParam, int lParam) {
151 switch (uiMsg) { 199 switch (uiMsg) {
152 case OS.WM_NOTIFY: 200 case OS.WM_NOTIFY:
191 public String open () { 239 public String open () {
192 auto hHeap = OS.GetProcessHeap (); 240 auto hHeap = OS.GetProcessHeap ();
193 241
194 /* Get the owner HWND for the dialog */ 242 /* Get the owner HWND for the dialog */
195 HWND hwndOwner; 243 HWND hwndOwner;
196 if (parent !is null) hwndOwner = parent.handle; 244 auto hwndParent = parent.handle;
245
246 /*
247 * Feature in Windows. There is no API to set the orientation of a
248 * file dialog. It is always inherited from the parent. The fix is
249 * to create a hidden parent and set the orientation in the hidden
250 * parent for the dialog to inherit.
251 */
252 bool enabled = false;
253 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
254 int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
255 int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
256 if (dialogOrientation !is parentOrientation) {
257 int exStyle = OS.WS_EX_NOINHERITLAYOUT;
258 if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
259 hwndOwner = OS.CreateWindowEx (
260 exStyle,
261 Shell.DialogClass.ptr,
262 null,
263 0,
264 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
265 hwndParent,
266 null,
267 OS.GetModuleHandle (null),
268 null);
269 enabled = OS.IsWindowEnabled (hwndParent) !is 0;
270 if (enabled) OS.EnableWindow (hwndParent, false);
271 }
272 }
197 273
198 /* Convert the title and copy it into lpstrTitle */ 274 /* Convert the title and copy it into lpstrTitle */
199 if (title is null) title = ""; 275 if (title is null) title = "";
200 /* Use the character encoding for the default locale */ 276 /* Use the character encoding for the default locale */
201 TCHAR[] buffer3 = StrToTCHARs (0, title, true); 277 TCHAR[] buffer3 = StrToTCHARs (0, title, true);
251 327
252 /* Create the file dialog struct */ 328 /* Create the file dialog struct */
253 OPENFILENAME struct_; 329 OPENFILENAME struct_;
254 struct_.lStructSize = OPENFILENAME.sizeof; 330 struct_.lStructSize = OPENFILENAME.sizeof;
255 struct_.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR; 331 struct_.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR;
256 //Callback callback = null; 332 bool save = (style & DWT.SAVE) !is 0;
333 if (save && overwrite) struct_.Flags |= OS.OFN_OVERWRITEPROMPT;
257 if ((style & DWT.MULTI) !is 0) { 334 if ((style & DWT.MULTI) !is 0) {
258 struct_.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER; 335 struct_.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER;
259 if (!OS.IsWinCE && USE_HOOK) { 336 if (!OS.IsWinCE && USE_HOOK) {
260 //callback = new Callback (this, "OFNHookProc", 4); //$NON-NLS-1$ 337 //callback = new Callback (this, "OFNHookProc", 4); //$NON-NLS-1$
261 //int lpfnHook = callback.getAddress (); 338 //int lpfnHook = callback.getAddress ();
269 struct_.lpstrTitle = lpstrTitle; 346 struct_.lpstrTitle = lpstrTitle;
270 struct_.lpstrFile = lpstrFile; 347 struct_.lpstrFile = lpstrFile;
271 struct_.nMaxFile = nMaxFile; 348 struct_.nMaxFile = nMaxFile;
272 struct_.lpstrInitialDir = lpstrInitialDir; 349 struct_.lpstrInitialDir = lpstrInitialDir;
273 struct_.lpstrFilter = lpstrFilter; 350 struct_.lpstrFilter = lpstrFilter;
274 struct_.nFilterIndex = 0; 351 struct_.nFilterIndex = filterIndex is 0 ? filterIndex : filterIndex + 1;
275 352
276 /* 353 /*
277 * Set the default extension to an empty string. If the 354 * Set the default extension to an empty string. If the
278 * user fails to type an extension and this extension is 355 * user fails to type an extension and this extension is
279 * empty, Windows uses the current value of the filter 356 * empty, Windows uses the current value of the filter
280 * extension at the time that the dialog is closed. 357 * extension at the time that the dialog is closed.
281 */ 358 */
282 TCHAR* lpstrDefExt; 359 TCHAR* lpstrDefExt;
283 bool save = (style & DWT.SAVE) !is 0;
284 if (save) { 360 if (save) {
285 lpstrDefExt = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof); 361 lpstrDefExt = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
286 struct_.lpstrDefExt = lpstrDefExt; 362 struct_.lpstrDefExt = lpstrDefExt;
287 } 363 }
288 364
289 /* Make the parent shell be temporary modal */ 365 /* Make the parent shell be temporary modal */
290 Shell oldModal = null; 366 Dialog oldModal = null;
291 Display display = parent.getDisplay (); 367 Display display = parent.getDisplay ();
292 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { 368 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
293 oldModal = display.getModalDialogShell (); 369 oldModal = display.getModalDialog ();
294 display.setModalDialogShell (parent); 370 display.setModalDialog (this);
295 } 371 }
296 372
297 /* 373 /*
298 * Feature in Windows. For some reason, the WH_MSGFILTER filter 374 * Feature in Windows. For some reason, the WH_MSGFILTER filter
299 * does not run for GetSaveFileName() or GetOpenFileName(). The 375 * does not run for GetSaveFileName() or GetOpenFileName(). The
325 } 401 }
326 display.runMessagesInIdle = oldRunMessagesInIdle; 402 display.runMessagesInIdle = oldRunMessagesInIdle;
327 403
328 /* Clear the temporary dialog modal parent */ 404 /* Clear the temporary dialog modal parent */
329 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { 405 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
330 display.setModalDialogShell (oldModal); 406 display.setModalDialog (oldModal);
331 } 407 }
332 408
333 /* Dispose the callback and reassign the buffer */ 409 /* Dispose the callback and reassign the buffer */
334 //if (callback !is null) callback.dispose (); 410 //if (callback !is null) callback.dispose ();
335 lpstrFile = struct_.lpstrFile; 411 lpstrFile = struct_.lpstrFile;
336 412
337 /* Set the new path, file name and filter */ 413 /* Set the new path, file name and filter */
338 fileNames = new String [0]; 414 fileNames = null;
339 String fullPath = null; 415 String fullPath = null;
340 if (success) { 416 if (success) {
341 417
342 /* Use the character encoding for the default locale */ 418 /* Use the character encoding for the default locale */
343 TCHAR[] buffer = NewTCHARs (0, struct_.nMaxFile); 419 TCHAR[] buffer = NewTCHARs (0, struct_.nMaxFile);
406 String [] newFileNames = new String[]( count ); 482 String [] newFileNames = new String[]( count );
407 System.arraycopy (fileNames, 0, newFileNames, 0, count); 483 System.arraycopy (fileNames, 0, newFileNames, 0, count);
408 fileNames = newFileNames; 484 fileNames = newFileNames;
409 } 485 }
410 } 486 }
487 filterIndex = struct_.nFilterIndex - 1;
411 } 488 }
412 489
413 /* Free the memory that was allocated. */ 490 /* Free the memory that was allocated. */
414 OS.HeapFree (hHeap, 0, lpstrFile); 491 OS.HeapFree (hHeap, 0, lpstrFile);
415 OS.HeapFree (hHeap, 0, lpstrFilter); 492 OS.HeapFree (hHeap, 0, lpstrFilter);
416 OS.HeapFree (hHeap, 0, lpstrInitialDir); 493 OS.HeapFree (hHeap, 0, lpstrInitialDir);
417 OS.HeapFree (hHeap, 0, lpstrTitle); 494 OS.HeapFree (hHeap, 0, lpstrTitle);
418 if (lpstrDefExt !is null) OS.HeapFree (hHeap, 0, lpstrDefExt); 495 if (lpstrDefExt !is null) OS.HeapFree (hHeap, 0, lpstrDefExt);
496
497 /* Destroy the BIDI orientation window */
498 if (hwndParent !is hwndOwner) {
499 if (enabled) OS.EnableWindow (hwndParent, true);
500 OS.SetActiveWindow (hwndParent);
501 OS.DestroyWindow (hwndOwner);
502 }
419 503
420 /* 504 /*
421 * This code is intentionally commented. On some 505 * This code is intentionally commented. On some
422 * platforms, the owner window is repainted right 506 * platforms, the owner window is repainted right
423 * away when a dialog window exits. This behavior 507 * away when a dialog window exits. This behavior
459 public void setFilterExtensions (String [] extensions) { 543 public void setFilterExtensions (String [] extensions) {
460 filterExtensions = extensions; 544 filterExtensions = extensions;
461 } 545 }
462 546
463 /** 547 /**
464 * Sets the the names that describe the filter extensions 548 * Set the 0-based index of the file extension filter
549 * which the dialog will use initially to filter the files
550 * it shows to the argument.
551 * <p>
552 * This is an index into the FilterExtensions array and
553 * the FilterNames array.
554 * </p>
555 *
556 * @param index the file extension filter index
557 *
558 * @see #setFilterExtensions
559 * @see #setFilterNames
560 *
561 * @since 3.4
562 */
563 public void setFilterIndex (int index) {
564 filterIndex = index;
565 }
566
567 /**
568 * Sets the names that describe the filter extensions
465 * which the dialog will use to filter the files it shows 569 * which the dialog will use to filter the files it shows
466 * to the argument, which may be null. 570 * to the argument, which may be null.
467 * <p> 571 * <p>
468 * Each name is a user-friendly short description shown for 572 * Each name is a user-friendly short description shown for
469 * its corresponding filter. The <code>names</code> array must 573 * its corresponding filter. The <code>names</code> array must
497 */ 601 */
498 public void setFilterPath (String string) { 602 public void setFilterPath (String string) {
499 filterPath = string; 603 filterPath = string;
500 } 604 }
501 605
502 } 606 /**
503 607 * Sets the flag that the dialog will use to
608 * determine whether to prompt the user for file
609 * overwrite if the selected file already exists.
610 *
611 * @param overwrite true if the dialog will prompt for file overwrite, false otherwise
612 *
613 * @since 3.4
614 */
615 public void setOverwrite (bool overwrite) {
616 this.overwrite = overwrite;
617 }
618 }
619