comparison dwt/widgets/DirectoryDialog.d @ 181:52c185ec49e8

Directory Dialog ported
author Zhiguang Liang <davelzg@gmail.com>
date Mon, 10 Mar 2008 11:31:43 +0800
parents 43c42c637c9c
children 811e926196d6
comparison
equal deleted inserted replaced
178:e186b01aa62e 181:52c185ec49e8
10 * Port to the D programming language: 10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de> 11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/ 12 *******************************************************************************/
13 module dwt.widgets.DirectoryDialog; 13 module dwt.widgets.DirectoryDialog;
14 14
15 import dwt.widgets.Display;
15 import dwt.widgets.Dialog; 16 import dwt.widgets.Dialog;
16 import dwt.widgets.Shell; 17 import dwt.widgets.Shell;
17 18
18 class DirectoryDialog : Dialog {
19 public this (Shell parent, int style) {
20 super (parent, style);
21 }
22 }
23
24 /++
25 import dwt.DWT; 19 import dwt.DWT;
26 import dwt.DWTException; 20 import dwt.DWTException;
27 import dwt.internal.Callback;
28 import dwt.internal.win32.BROWSEINFO;
29 import dwt.internal.win32.OS; 21 import dwt.internal.win32.OS;
30 import dwt.internal.win32.TCHAR; 22 import dwt.internal.C;
23
24 import dwt.dwthelper.utils;
25 static import tango.text.Text;
31 26
32 /** 27 /**
33 * Instances of this class allow the user to navigate 28 * Instances of this class allow the user to navigate
34 * the file system and select a directory. 29 * the file system and select a directory.
35 * <dl> 30 * <dl>
42 * IMPORTANT: This class is intended to be subclassed <em>only</em> 37 * IMPORTANT: This class is intended to be subclassed <em>only</em>
43 * within the DWT implementation. 38 * within the DWT implementation.
44 * </p> 39 * </p>
45 */ 40 */
46 41
47 public class DirectoryDialog extends Dialog { 42 public class DirectoryDialog : Dialog {
48 String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$ 43 static char[] message = "";
49 String directoryPath; 44 static char[] filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$
45 static char[] directoryPath;
50 46
51 /** 47 /**
52 * Constructs a new instance of this class given only its parent. 48 * Constructs a new instance of this class given only its parent.
53 * 49 *
54 * @param parent a shell which will be the parent of the new instance 50 * @param parent a shell which will be the parent of the new instance
59 * @exception DWTException <ul> 55 * @exception DWTException <ul>
60 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 56 * <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> 57 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
62 * </ul> 58 * </ul>
63 */ 59 */
64 public DirectoryDialog (Shell parent) { 60 public this (Shell parent) {
65 this (parent, DWT.PRIMARY_MODAL); 61 this (parent, DWT.PRIMARY_MODAL);
66 } 62 }
67 63
68 /** 64 /**
69 * Constructs a new instance of this class given its parent 65 * Constructs a new instance of this class given its parent
87 * @exception DWTException <ul> 83 * @exception DWTException <ul>
88 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 84 * <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> 85 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
90 * </ul> 86 * </ul>
91 */ 87 */
92 public DirectoryDialog (Shell parent, int style) { 88 public this (Shell parent, int style) {
93 super (parent, style); 89 super (parent, style);
94 checkSubclass (); 90 checkSubclass ();
95 } 91 }
96 92
97 int BrowseCallbackProc (int hwnd, int uMsg, int lParam, int lpData) { 93 extern(Windows)static int BrowseCallbackProc (HWND hwnd, uint uMsg, int lParam, int lpData) {
94 DirectoryDialog pThis = cast(DirectoryDialog)cast(void*)lpData;
98 switch (uMsg) { 95 switch (uMsg) {
99 case OS.BFFM_INITIALIZED: 96 case OS.BFFM_INITIALIZED:
100 if (filterPath !is null && filterPath.length () !is 0) { 97 if (pThis.filterPath !is null && pThis.filterPath.length !is 0) {
101 /* Use the character encoding for the default locale */ 98 /* Use the character encoding for the default locale */
102 TCHAR buffer = new TCHAR (0, filterPath.replace ('/', '\\'), true); 99 TCHAR[] buffer = StrToTCHARs (0, pThis.filterPath.replace ('/', '\\'), true);
103 OS.SendMessage (hwnd, OS.BFFM_SETSELECTION, 1, buffer); 100 OS.SendMessage (hwnd, OS.BFFM_SETSELECTION, 1, buffer.ptr);
104 } 101 }
105 if (title !is null && title.length () !is 0) { 102 if (pThis.title !is null && pThis.title.length !is 0) {
106 /* Use the character encoding for the default locale */ 103 /* Use the character encoding for the default locale */
107 TCHAR buffer = new TCHAR (0, title, true); 104 TCHAR[] buffer = StrToTCHARs (0, pThis.title, true);
108 OS.SetWindowText (hwnd, buffer); 105 OS.SetWindowText (hwnd, buffer.ptr);
109 } 106 }
110 break; 107 break;
111 case OS.BFFM_VALIDATEFAILEDA: 108 case OS.BFFM_VALIDATEFAILEDA:
112 case OS.BFFM_VALIDATEFAILEDW: 109 case OS.BFFM_VALIDATEFAILEDW:
113 /* Use the character encoding for the default locale */ 110 /* Use the character encoding for the default locale */
114 int length = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam); 111 // int length = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam);
115 TCHAR buffer = new TCHAR (0, length); 112 // TCHAR buffer = new TCHAR (0, length);
116 int byteCount = buffer.length () * TCHAR.sizeof; 113 // int byteCount = buffer.length * TCHAR.sizeof;
117 OS.MoveMemory (buffer, lParam, byteCount); 114 // OS.MoveMemory (buffer, lParam, byteCount);
118 directoryPath = buffer.toString (0, length); 115 // directoryPath = buffer.toString (0, length);
116 pThis.directoryPath = TCHARzToStr( cast(TCHAR*)lParam );
119 break; 117 break;
120 default: 118 default:
121 } 119 }
122 return 0; 120 return 0;
123 } 121 }
128 * 126 *
129 * @return the filter path 127 * @return the filter path
130 * 128 *
131 * @see #setFilterPath 129 * @see #setFilterPath
132 */ 130 */
133 public String getFilterPath () { 131 public char[] getFilterPath () {
134 return filterPath; 132 return filterPath;
135 } 133 }
136 134
137 /** 135 /**
138 * Returns the dialog's message, which is a description of 136 * Returns the dialog's message, which is a description of
139 * the purpose for which it was opened. This message will be 137 * the purpose for which it was opened. This message will be
140 * visible on the dialog while it is open. 138 * visible on the dialog while it is open.
141 * 139 *
142 * @return the message 140 * @return the message
143 */ 141 */
144 public String getMessage () { 142 public char[] getMessage () {
145 return message; 143 return message;
146 } 144 }
147 145
148 /** 146 /**
149 * Makes the dialog visible and brings it to the front 147 * Makes the dialog visible and brings it to the front
155 * @exception DWTException <ul> 153 * @exception DWTException <ul>
156 * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li> 154 * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li> 155 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
158 * </ul> 156 * </ul>
159 */ 157 */
160 public String open () { 158 public char[] open () {
161 if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED); 159 if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED);
162 160
163 int hHeap = OS.GetProcessHeap (); 161 auto hHeap = OS.GetProcessHeap ();
164 162
165 /* Get the owner HWND for the dialog */ 163 /* Get the owner HWND for the dialog */
166 int hwndOwner = 0; 164 HWND hwndOwner;
167 if (parent !is null) hwndOwner = parent.handle; 165 if (parent !is null) hwndOwner = parent.handle;
168 166
169 /* Copy the message to OS memory */ 167 /* Copy the message to OS memory */
170 int lpszTitle = 0; 168 TCHAR* lpszTitle;
171 if (message.length () !is 0) { 169 if (message.length !is 0) {
172 String string = message; 170 char[] string = message;
173 if (string.indexOf ('&') !is -1) { 171 if (string.indexOf ('&') !is -1) {
174 int length = string.length (); 172 int length = string.length;
175 char [] buffer = new char [length * 2]; 173 char [] buffer = new char [length * 2];
176 int index = 0; 174 int index = 0;
177 for (int i=0; i<length; i++) { 175 for (int i=0; i<length; i++) {
178 char ch = string.charAt (i); 176 char ch = string.charAt (i);
179 if (ch is '&') buffer [index++] = '&'; 177 if (ch is '&') buffer [index++] = '&';
180 buffer [index++] = ch; 178 buffer [index++] = ch;
181 } 179 }
182 string = new String (buffer, 0, index); 180 // string = new String (buffer, 0, index);
183 } 181 }
184 /* Use the character encoding for the default locale */ 182 /* Use the character encoding for the default locale */
185 TCHAR buffer = new TCHAR (0, string, true); 183 TCHAR[] buffer = StrToTCHARs (0, string, true);
186 int byteCount = buffer.length () * TCHAR.sizeof; 184 int byteCount = buffer.length * TCHAR.sizeof;
187 lpszTitle = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); 185 lpszTitle = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
188 OS.MoveMemory (lpszTitle, buffer, byteCount); 186 OS.MoveMemory (lpszTitle, buffer.ptr, byteCount);
189 } 187 }
190 188
191 /* Create the BrowseCallbackProc */ 189 /* Create the BrowseCallbackProc */
192 Callback callback = new Callback (this, "BrowseCallbackProc", 4); //$NON-NLS-1$ 190 /+ Callback callback = new Callback (this, "BrowseCallbackProc", 4); //$NON-NLS-1$
193 int lpfn = callback.getAddress (); 191 int lpfn = callback.getAddress ();+/
194 if (lpfn is 0) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS); 192 BFFCALLBACK lpfn = &BrowseCallbackProc;
193 if (lpfn is null) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);
195 194
196 /* Make the parent shell be temporary modal */ 195 /* Make the parent shell be temporary modal */
197 Shell oldModal = null; 196 Shell oldModal = null;
198 Display display = parent.getDisplay (); 197 Display display = parent.getDisplay ();
199 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { 198 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
200 oldModal = display.getModalDialogShell (); 199 oldModal = display.getModalDialogShell ();
201 display.setModalDialogShell (parent); 200 display.setModalDialogShell (parent);
202 } 201 }
203 202
204 directoryPath = null; 203 directoryPath = null;
205 BROWSEINFO lpbi = new BROWSEINFO (); 204 BROWSEINFO lpbi;
206 lpbi.hwndOwner = hwndOwner; 205 lpbi.hwndOwner = hwndOwner;
207 lpbi.lpszTitle = lpszTitle; 206 lpbi.lpszTitle = lpszTitle;
208 lpbi.ulFlags = OS.BIF_NEWDIALOGSTYLE | OS.BIF_RETURNONLYFSDIRS | OS.BIF_EDITBOX | OS.BIF_VALIDATE; 207 lpbi.ulFlags = OS.BIF_NEWDIALOGSTYLE | OS.BIF_RETURNONLYFSDIRS | OS.BIF_EDITBOX | OS.BIF_VALIDATE;
209 lpbi.lpfn = lpfn; 208 lpbi.lpfn = lpfn;
209 lpbi.lParam = cast(int)cast(void*)this;
210 /* 210 /*
211 * Bug in Windows. On some hardware configurations, SHBrowseForFolder() 211 * Bug in Windows. On some hardware configurations, SHBrowseForFolder()
212 * causes warning dialogs with the message "There is no disk in the drive 212 * causes warning dialogs with the message "There is no disk in the drive
213 * Please insert a disk into \Device\Harddisk0\DR0". This is possibly 213 * Please insert a disk into \Device\Harddisk0\DR0". This is possibly
214 * caused by SHBrowseForFolder() calling internally GetVolumeInformation(). 214 * caused by SHBrowseForFolder() calling internally GetVolumeInformation().
237 * NOTE: This only happens in versions of the comctl32.dll 237 * NOTE: This only happens in versions of the comctl32.dll
238 * earlier than 6.0. 238 * earlier than 6.0.
239 */ 239 */
240 bool oldRunMessages = display.runMessages; 240 bool oldRunMessages = display.runMessages;
241 if (OS.COMCTL32_MAJOR < 6) display.runMessages = false; 241 if (OS.COMCTL32_MAJOR < 6) display.runMessages = false;
242 int lpItemIdList = OS.SHBrowseForFolder (lpbi); 242 ITEMIDLIST* lpItemIdList = OS.SHBrowseForFolder (&lpbi);
243 if (OS.COMCTL32_MAJOR < 6) display.runMessages = oldRunMessages; 243 if (OS.COMCTL32_MAJOR < 6) display.runMessages = oldRunMessages;
244 OS.SetErrorMode (oldErrorMode); 244 OS.SetErrorMode (oldErrorMode);
245 245
246 /* Clear the temporary dialog modal parent */ 246 /* Clear the temporary dialog modal parent */
247 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { 247 if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
248 display.setModalDialogShell (oldModal); 248 display.setModalDialogShell (oldModal);
249 } 249 }
250 250
251 bool success = lpItemIdList !is 0; 251 bool success = lpItemIdList !is null;
252 if (success) { 252 if (success) {
253 /* Use the character encoding for the default locale */ 253 /* Use the character encoding for the default locale */
254 TCHAR buffer = new TCHAR (0, OS.MAX_PATH); 254 TCHAR[OS.MAX_PATH] buffer;
255 if (OS.SHGetPathFromIDList (lpItemIdList, buffer)) { 255 if (OS.SHGetPathFromIDList (lpItemIdList, buffer.ptr)) {
256 directoryPath = buffer.toString (0, buffer.strlen ()); 256 directoryPath = TCHARzToStr (buffer.ptr);
257 filterPath = directoryPath; 257 filterPath = directoryPath;
258 } 258 }
259 } 259 }
260 260
261 /* Free the BrowseCallbackProc */ 261 /* Free the BrowseCallbackProc */
262 callback.dispose (); 262 // callback.dispose ();
263 263
264 /* Free the OS memory */ 264 /* Free the OS memory */
265 if (lpszTitle !is 0) OS.HeapFree (hHeap, 0, lpszTitle); 265 if (lpszTitle !is null) OS.HeapFree (hHeap, 0, lpszTitle);
266 266
267 /* Free the pointer to the ITEMIDLIST */ 267 /* Free the pointer to the ITEMIDLIST */
268 int [] ppMalloc = new int [1]; 268 LPVOID ppMalloc;
269 if (OS.SHGetMalloc (ppMalloc) is OS.S_OK) { 269 if (OS.SHGetMalloc (&ppMalloc) is OS.S_OK) {
270 /* void Free (struct IMalloc *this, void *pv); */ 270 /* void Free (struct IMalloc *this, void *pv); */
271 OS.VtblCall (5, ppMalloc [0], lpItemIdList); 271 OS.VtblCall (5, ppMalloc , cast(int)lpItemIdList);
272 } 272 }
273 273
274 /* 274 /*
275 * This code is intentionally commented. On some 275 * This code is intentionally commented. On some
276 * platforms, the owner window is repainted right 276 * platforms, the owner window is repainted right
295 * as a path separator. 295 * as a path separator.
296 * </p> 296 * </p>
297 * 297 *
298 * @param string the filter path 298 * @param string the filter path
299 */ 299 */
300 public void setFilterPath (String string) { 300 public void setFilterPath (char[] string) {
301 filterPath = string; 301 filterPath = string;
302 } 302 }
303 303
304 /** 304 /**
305 * Sets the dialog's message, which is a description of 305 * Sets the dialog's message, which is a description of
310 * 310 *
311 * @exception IllegalArgumentException <ul> 311 * @exception IllegalArgumentException <ul>
312 * <li>ERROR_NULL_ARGUMENT - if the string is null</li> 312 * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
313 * </ul> 313 * </ul>
314 */ 314 */
315 public void setMessage (String string) { 315 public void setMessage (char[] string) {
316 if (string is null) error (DWT.ERROR_NULL_ARGUMENT); 316 if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
317 message = string; 317 message = string;
318 } 318 }
319 319
320 } 320 }
321 ++/