root/dwt/widgets/DirectoryDialog.d

Revision 246:fd9c62a2998e, 11.2 kB (checked in by Frank Benoit <benoit@tionex.de>, 5 months ago)

Updater SWT 3.4M7 to 3.4

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module dwt.widgets.DirectoryDialog;
14
15 import dwt.widgets.Display;
16 import dwt.widgets.Dialog;
17 import dwt.widgets.Shell;
18
19 import dwt.DWT;
20 import dwt.DWTException;
21 import dwt.internal.win32.OS;
22 import dwt.internal.C;
23
24 import dwt.dwthelper.utils;
25 static import tango.text.Text;
26
27 /**
28  * Instances of this class allow the user to navigate
29  * the file system and select a directory.
30  * <dl>
31  * <dt><b>Styles:</b></dt>
32  * <dd>(none)</dd>
33  * <dt><b>Events:</b></dt>
34  * <dd>(none)</dd>
35  * </dl>
36  * <p>
37  * IMPORTANT: This class is intended to be subclassed <em>only</em>
38  * within the DWT implementation.
39  * </p>
40  *
41  * @see <a href="http://www.eclipse.org/swt/snippets/#directorydialog">DirectoryDialog snippets</a>
42  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample, Dialog tab</a>
43  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
44  */
45
46 public class DirectoryDialog : Dialog {
47     static String message = "";
48     static String filterPath = "";  //$NON-NLS-1$//$NON-NLS-2$
49     static String directoryPath;
50
51 /**
52  * Constructs a new instance of this class given only its parent.
53  *
54  * @param parent a shell which will be the parent of the new instance
55  *
56  * @exception IllegalArgumentException <ul>
57  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
58  * </ul>
59  * @exception DWTException <ul>
60  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
61  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
62  * </ul>
63  */
64 public this (Shell parent) {
65     this (parent, DWT.APPLICATION_MODAL);
66 }
67
68 /**
69  * Constructs a new instance of this class given its parent
70  * and a style value describing its behavior and appearance.
71  * <p>
72  * The style value is either one of the style constants defined in
73  * class <code>DWT</code> which is applicable to instances of this
74  * class, or must be built by <em>bitwise OR</em>'ing together
75  * (that is, using the <code>int</code> "|" operator) two or more
76  * of those <code>DWT</code> style constants. The class description
77  * lists the style constants that are applicable to the class.
78  * Style bits are also inherited from superclasses.
79  * </p>
80  *
81  * @param parent a shell which will be the parent of the new instance
82  * @param style the style of dialog to construct
83  *
84  * @exception IllegalArgumentException <ul>
85  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
86  * </ul>
87  * @exception DWTException <ul>
88  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
89  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
90  * </ul>
91  */
92 public this (Shell parent, int style) {
93     super (parent, checkStyle (parent, style));
94     checkSubclass ();
95 }
96
97 extern(Windows)static int BrowseCallbackProc (HWND hwnd, uint uMsg, int lParam, int lpData) {
98     DirectoryDialog pThis = cast(DirectoryDialog)cast(void*)lpData;
99     switch (uMsg) {
100         case OS.BFFM_INITIALIZED:
101             if (pThis.filterPath !is null && pThis.filterPath.length !is 0) {
102                 /* Use the character encoding for the default locale */
103                 TCHAR[] buffer = StrToTCHARs (0, pThis.filterPath.replace ('/', '\\'), true);
104                 OS.SendMessage (hwnd, OS.BFFM_SETSELECTION, 1, buffer.ptr);
105             }
106             if (pThis.title !is null && pThis.title.length !is 0) {
107                 /* Use the character encoding for the default locale */
108                 TCHAR[] buffer = StrToTCHARs (0, pThis.title, true);
109                 OS.SetWindowText (hwnd, buffer.ptr);
110             }
111             break;
112         case OS.BFFM_VALIDATEFAILEDA:
113         case OS.BFFM_VALIDATEFAILEDW:
114             /* Use the character encoding for the default locale */
115 //            int length = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam);
116 //            TCHAR buffer = new TCHAR (0, length);
117 //            int byteCount = buffer.length * TCHAR.sizeof;
118 //            OS.MoveMemory (buffer, lParam, byteCount);
119 //            directoryPath = buffer.toString (0, length);
120             pThis.directoryPath = TCHARzToStr( cast(TCHAR*)lParam );
121             break;
122         default:
123     }
124     return 0;
125 }
126
127 /**
128  * Returns the path which the dialog will use to filter
129  * the directories it shows.
130  *
131  * @return the filter path
132  *
133  * @see #setFilterPath
134  */
135 public String getFilterPath () {
136     return filterPath;
137 }
138
139 /**
140  * Returns the dialog's message, which is a description of
141  * the purpose for which it was opened. This message will be
142  * visible on the dialog while it is open.
143  *
144  * @return the message
145  */
146 public String getMessage () {
147     return message;
148 }
149
150 /**
151  * Makes the dialog visible and brings it to the front
152  * of the display.
153  *
154  * @return a string describing the absolute path of the selected directory,
155  *         or null if the dialog was cancelled or an error occurred
156  *
157  * @exception DWTException <ul>
158  *    <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
159  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
160  * </ul>
161  */
162 public String open () {
163     if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED);
164
165     auto hHeap = OS.GetProcessHeap ();
166
167     /* Get the owner HWND for the dialog */
168     HWND hwndOwner;
169     if (parent !is null) hwndOwner = parent.handle;
170
171     /* Copy the message to OS memory */
172     TCHAR* lpszTitle;
173     if (message.length !is 0) {
174         String string = message;
175         if (string.indexOf ('&') !is -1) {
176             int length = string.length;
177             char [] buffer = new char [length * 2];
178             int index = 0;
179             for (int i=0; i<length; i++) {
180                 char ch = string.charAt (i);
181                 if (ch is '&') buffer [index++] = '&';
182                 buffer [index++] = ch;
183             }
184 //            string = new String (buffer, 0, index);
185         }
186         /* Use the character encoding for the default locale */
187         TCHAR[] buffer = StrToTCHARs (0, string, true);
188         int byteCount = buffer.length * TCHAR.sizeof;
189         lpszTitle = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
190         OS.MoveMemory (lpszTitle, buffer.ptr, byteCount);
191     }
192
193     /* Create the BrowseCallbackProc */
194 /+    Callback callback = new Callback (this, "BrowseCallbackProc", 4); //$NON-NLS-1$
195     int lpfn = callback.getAddress ();+/
196     BFFCALLBACK lpfn = &BrowseCallbackProc;
197     if (lpfn is null) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);
198
199     /* Make the parent shell be temporary modal */
200     Dialog oldModal = null;
201     Display display = parent.getDisplay ();
202     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
203         oldModal = display.getModalDialog ();
204         display.setModalDialog (this);
205     }
206
207     directoryPath = null;
208     BROWSEINFO lpbi;
209     lpbi.hwndOwner = hwndOwner;
210     lpbi.lpszTitle = lpszTitle;
211     lpbi.ulFlags = OS.BIF_NEWDIALOGSTYLE | OS.BIF_RETURNONLYFSDIRS | OS.BIF_EDITBOX | OS.BIF_VALIDATE;
212     lpbi.lpfn = lpfn;
213     lpbi.lParam = cast(int)cast(void*)this;
214     /*
215     * Bug in Windows.  On some hardware configurations, SHBrowseForFolder()
216     * causes warning dialogs with the message "There is no disk in the drive
217     * Please insert a disk into \Device\Harddisk0\DR0".  This is possibly
218     * caused by SHBrowseForFolder() calling internally GetVolumeInformation().
219     * MSDN for GetVolumeInformation() says:
220     *
221     * "If you are attempting to obtain information about a floppy drive
222     * that does not have a floppy disk or a CD-ROM drive that does not
223     * have a compact disc, the system displays a message box asking the
224     * user to insert a floppy disk or a compact disc, respectively.
225     * To prevent the system from displaying this message box, call the
226     * SetErrorMode function with SEM_FAILCRITICALERRORS."
227     *
228     * The fix is to save and restore the error mode using SetErrorMode()
229     * with the SEM_FAILCRITICALERRORS flag around SHBrowseForFolder().
230     */
231     int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
232
233     /*
234     * Bug in Windows.  When a WH_MSGFILTER hook is used to run code
235     * during the message loop for SHBrowseForFolder(), running code
236     * in the hook can cause a GP.  Specifically, SetWindowText()
237     * for static controls seemed to make the problem happen.
238     * The fix is to disable async messages while the directory
239     * dialog is open.
240     *
241     * NOTE:  This only happens in versions of the comctl32.dll
242     * earlier than 6.0.
243     */
244     bool oldRunMessages = display.runMessages;
245     if (OS.COMCTL32_MAJOR < 6) display.runMessages = false;
246     ITEMIDLIST* lpItemIdList = OS.SHBrowseForFolder (&lpbi);
247     if (OS.COMCTL32_MAJOR < 6) display.runMessages = oldRunMessages;
248     OS.SetErrorMode (oldErrorMode);
249
250     /* Clear the temporary dialog modal parent */
251     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
252         display.setModalDialog (oldModal);
253     }
254
255     bool success = lpItemIdList !is null;
256     if (success) {
257         /* Use the character encoding for the default locale */
258         TCHAR[OS.MAX_PATH] buffer;
259         if (OS.SHGetPathFromIDList (lpItemIdList, buffer.ptr)) {
260             directoryPath = TCHARzToStr (buffer.ptr);
261             filterPath = directoryPath;
262         }
263     }
264
265     /* Free the BrowseCallbackProc */
266 //    callback.dispose ();
267
268     /* Free the OS memory */
269     if (lpszTitle !is null) OS.HeapFree (hHeap, 0, lpszTitle);
270
271     /* Free the pointer to the ITEMIDLIST */
272     LPVOID ppMalloc;
273     if (OS.SHGetMalloc (&ppMalloc) is OS.S_OK) {
274         /* void Free (struct IMalloc *this, void *pv); */
275         OS.VtblCall (5, ppMalloc , cast(int)lpItemIdList);
276     }
277
278     /*
279     * This code is intentionally commented.  On some
280     * platforms, the owner window is repainted right
281     * away when a dialog window exits.  This behavior
282     * is currently unspecified.
283     */
284 //  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
285
286     /* Return the directory path */
287     if (!success) return null;
288     return directoryPath;
289 }
290
291 /**
292  * Sets the path that the dialog will use to filter
293  * the directories it shows to the argument, which may
294  * be null. If the string is null, then the operating
295  * system's default filter path will be used.
296  * <p>
297  * Note that the path string is platform dependent.
298  * For convenience, either '/' or '\' can be used
299  * as a path separator.
300  * </p>
301  *
302  * @param string the filter path
303  */
304 public void setFilterPath (String string) {
305     filterPath = string;
306 }
307
308 /**
309  * Sets the dialog's message, which is a description of
310  * the purpose for which it was opened. This message will be
311  * visible on the dialog while it is open.
312  *
313  * @param string the message
314  *
315  */
316 public void setMessage (String string) {
317     // DWT extension: allow null string
318     //if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
319     message = string;
320 }
321
322 }
Note: See TracBrowser for help on using the browser.