1 /**
2 * Dialog module.
3 *
4 * License:
5 * MIT. See LICENSE for full details.
6 */
7 module tkd.window.dialog.openfiledialog;
8
9 /**
10 * Imports.
11 */
12 import std.array;
13 import std.regex;
14 import tkd.window.dialog.filedialog;
15 import tkd.window.window;
16
17 /**
18 * Pops up a dialog box for the user to open a file.
19 *
20 * Example:
21 * ---
22 * auto dialog = new OpenFileDialog("Open a file")
23 * .setMultiSelection(false)
24 * .setDefaultExtension(".txt")
25 * .addFileType("{{All files} {*}}")
26 * .addFileType("{{Text files} {.txt}}")
27 * .setInitialDirectory("~")
28 * .setInitialFile("file.txt")
29 * .show();
30 *
31 * string fileToOpen = dialog.getResult();
32 * ---
33 *
34 * Result:
35 * The full path of the file selected.
36 *
37 * See_Also:
38 * $(LINK2 ./filedialog.html, tkd.dialog.filedialog) $(BR)
39 */
40 class OpenFileDialog : FileDialog
41 {
42 /*
43 * Allows the user to choose multiple files from the Open dialog.
44 */
45 protected bool _selectMultiple;
46
47 /**
48 * Construct the dialog.
49 *
50 * Params:
51 * parent = The parent window of the dialog.
52 * title = The title of the dialog.
53 */
54 this(Window parent, string title = "Open")
55 {
56 super(parent, title);
57 }
58
59 /**
60 * Construct the dialog.
61 *
62 * Params:
63 * title = The title of the dialog.
64 */
65 this(string title = "Open")
66 {
67 this(null, title);
68 }
69
70 /**
71 * Set whether to enable mutli-selection.
72 *
73 * Params:
74 * enable = Enables multi-selections.
75 *
76 * Returns:
77 * This dialog to aid method chaining.
78 */
79 public auto setMultiSelection(this T)(bool enable)
80 {
81 this._selectMultiple = enable;
82
83 return cast(T) this;
84 }
85
86 /**
87 * Show the dialog.
88 *
89 * Returns:
90 * This dialog to aid method chaining.
91 */
92 public auto show(this T)()
93 {
94 if (this._parent)
95 {
96 // String concatentation is used here to avoid the character escaping done on args.
97 this._tk.eval("tk_getOpenFile -parent %s -title {%s} -multiple %s -defaultextension {%s} -filetypes {" ~ this._fileTypes.join(" ") ~ "} -initialdir {%s} -initialfile {%s} -typevariable %s", this._parent.id, this._title, this._selectMultiple, this._defaultExtension, this._initialDirectory, this._initialFile, this._typeVariable);
98 }
99 else
100 {
101 // String concatentation is used here to avoid the character escaping done on args.
102 this._tk.eval("tk_getOpenFile -title {%s} -multiple %s -defaultextension {%s} -filetypes {" ~ this._fileTypes.join(" ") ~ "} -initialdir {%s} -initialfile {%s} -typevariable %s", this._title, this._selectMultiple, this._defaultExtension, this._initialDirectory, this._initialFile, this._typeVariable);
103 }
104
105 string result = this._tk.getResult!(string);
106
107 if (match(result, r"^bad window path name").empty)
108 {
109 if (this._selectMultiple)
110 {
111 auto regexResult = matchAll(result, r"\{.*?\}");
112 result = result.replaceAll(regex(r"\{.*?\}"), "");
113 this._results ~= result.split();
114
115 foreach (match; regexResult)
116 {
117 this._results ~= match.hit;
118 }
119
120 this.removeBracesFromResults;
121 }
122 else
123 {
124 this._results = [result];
125 }
126 }
127
128 return cast(T) this;
129 }
130
131 /**
132 * Get multiple dialog results.
133 *
134 * Returns:
135 * The multiple results of the dialog.
136 */
137 public string[] getResults()
138 {
139 assert(this._selectMultiple, "You need to set multi-selection on to retrieve more than one result.");
140
141 return this._results;
142 }
143 }