annotate dynamin/gui/windows_file_dialog.d @ 4:fc2420d39e3c

Separate out Windows backend of FileDialog.
author Jordan Miner <jminer7@gmail.com>
date Sat, 20 Jun 2009 10:23:31 -0500
parents
children 836a064828e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
1 // Written in the D programming language
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
2 // www.digitalmars.com/d/
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
3
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
4 /*
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
5 * The contents of this file are subject to the Mozilla Public License Version
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
6 * 1.1 (the "License"); you may not use this file except in compliance with
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
7 * the License. You may obtain a copy of the License at
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
8 * http://www.mozilla.org/MPL/
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
9 *
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
10 * Software distributed under the License is distributed on an "AS IS" basis,
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
12 * for the specific language governing rights and limitations under the
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
13 * License.
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
14 *
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
15 * The Original Code is the Dynamin library.
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
16 *
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
17 * The Initial Developer of the Original Code is Jordan Miner.
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
18 * Portions created by the Initial Developer are Copyright (C) 2006-2009
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
19 * the Initial Developer. All Rights Reserved.
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
20 *
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
21 * Contributor(s):
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
22 * Jordan Miner <jminer7@gmail.com>
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
23 *
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
24 */
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
25
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
26 module dynamin.gui.windows_file_dialog;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
27
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
28 public import dynamin.c.windows;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
29 public import Utf = tango.text.convert.Utf;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
30
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
31 template FileDialogBackend() {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
32 DialogResult backend_showDialog() {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
33 OPENFILENAME ofn;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
34 ofn.lStructSize = OPENFILENAME.sizeof;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
35 //ofn.hwndOwner = ;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
36
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
37 bool allFilesFilter = false;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
38 foreach(filter; _filters)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
39 if(filter.extensions.length == 0)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
40 allFilesFilter = true;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
41 if(!allFilesFilter) addFilter("All Files (*.*)");
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
42
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
43 string filterStr;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
44 foreach(filter; _filters) {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
45 if(filter.shouldShow)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
46 continue;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
47 string[] exts = filter.extensions.dup;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
48 if(exts.length == 0)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
49 exts = [cast(string)"*.*"];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
50 else
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
51 for(int i = 0; i < exts.length; ++i)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
52 exts[i] = "*." ~ exts[i];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
53 filterStr ~= filter.name ~ "\0" ~ exts.join(";") ~ "\0";
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
54 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
55 filterStr ~= "\0";
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
56 ofn.lpstrFilter = filterStr.toWcharPtr();
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
57 ofn.nFilterIndex = _selectedFilter + 1;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
58 wchar[] filesBufferW = Utf.toString16(_initialFileName~"\0");
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
59 // TODO: should use a static buffer of 4096, passing to toString16
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
60 // avoid concat too
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
61 filesBufferW.length = 4096;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
62 scope(exit) delete filesBufferW;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
63 ofn.lpstrFile = filesBufferW.ptr;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
64 ofn.nMaxFile = filesBufferW.length;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
65 ofn.lpstrInitialDir = _directory.toWcharPtr();
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
66 ofn.lpstrTitle = _text.toWcharPtr();
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
67 ofn.Flags = OFN_EXPLORER;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
68 //if(canChooseLinks)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
69 // ofn.Flags |= OFN_NODEREFERENCELINKS;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
70 ofn.Flags |= OFN_FILEMUSTEXIST;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
71 ofn.Flags |= OFN_HIDEREADONLY;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
72 ofn.Flags |= OFN_OVERWRITEPROMPT;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
73 if(_multipleSelection)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
74 ofn.Flags |= OFN_ALLOWMULTISELECT;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
75
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
76 auto GetFileName = fileDialogType == Open ?
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
77 &GetOpenFileName : &GetSaveFileName ;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
78 if(!GetFileName(&ofn)) {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
79 if(CommDlgExtendedError() == FNERR_BUFFERTOOSMALL)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
80 MessageBoxW(null, "Too many files picked.", "Error", 0);
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
81 return DialogResult.Cancel;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
82 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
83
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
84 _selectedFilter = ofn.nFilterIndex - 1;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
85 // must zero FFFF chars here because the
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
86 // parsing here assumes the unused part of the string is zeroed
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
87 foreach(i, c; filesBufferW)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
88 if(c == 0xFFFF)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
89 filesBufferW[i] = 0;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
90 int index; // index of null char right after the last non-null char
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
91 for(index = filesBufferW.length; index > 0; --index)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
92 if(filesBufferW[index-1] != 0)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
93 break;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
94 auto filesBuffer = Utf.toString(filesBufferW[0..index]);
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
95 scope(exit) delete filesBuffer;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
96 if(filesBuffer.contains('\0')) { // multiple files
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
97 auto arr = filesBuffer.split("\0");
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
98 _directory = arr[0];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
99 // make sure directory ends with a backslash
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
100 // "C:\" does but "C:\Program Files" does not
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
101 if(!_directory.endsWith("\\"))
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
102 _directory ~= "\\";
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
103 _files = new string[arr.length-1];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
104 for(int i = 1; i < arr.length; ++i) {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
105 if(arr[i].contains('\\')) // a dereferenced link--absolute
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
106 _files[i-1] = arr[i];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
107 else
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
108 _files[i-1] = _directory ~ arr[i];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
109 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
110 } else { //single file
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
111 assert(filesBuffer.contains('\\'));
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
112 _directory = filesBuffer[0..filesBuffer.findLast("\\")].dup;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
113 _files = [filesBuffer.dup];
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
114 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
115
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
116 // if "All Files (*.*)" filter is not selected
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
117 if(_filters[selectedFilter].extensions.length > 0) {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
118 // go over every chosen file and add the selected filter's
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
119 // extension if the file doesn't already have one from the selected filter
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
120 for(int i = 0; i < _files.length; ++i) {
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
121 bool validExt = false;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
122 foreach(ext; _filters[selectedFilter].extensions)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
123 if(_files[i].downcase().endsWith(ext.downcase()))
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
124 validExt = true;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
125 if(!validExt)
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
126 _files[i] ~= "." ~ _filters[selectedFilter].extensions[0].downcase();
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
127 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
128 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
129
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
130 return DialogResult.OK;
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
131 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
132 }
fc2420d39e3c Separate out Windows backend of FileDialog.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
133