1 /** 2 * Dialog module. 3 * 4 * License: 5 * MIT. See LICENSE for full details. 6 */ 7 module tkd.window.dialog.filedialog; 8 9 /** 10 * Imports. 11 */ 12 import std.regex; 13 import std..string; 14 import tkd.window.dialog.dialog; 15 import tkd.window.window; 16 17 /** 18 * Pops up a dialog box for the user to select a color. 19 * 20 * See_Also: 21 * $(LINK2 ./dialog.html, tkd.dialog.dialog) $(BR) 22 */ 23 abstract class FileDialog : Dialog 24 { 25 /* 26 * The default extension for the file. 27 */ 28 protected string _defaultExtension; 29 30 /* 31 * A list of allowed file types. 32 */ 33 protected string[] _fileTypes; 34 35 /* 36 * The initial directory to start in the dialog. 37 */ 38 protected string _initialDirectory; 39 40 /* 41 * The initial file to use in the dialog. 42 */ 43 protected string _initialFile; 44 45 /* 46 * A variable to hold the state of the selected file type. 47 */ 48 protected string _typeVariable; 49 50 /** 51 * Construct the dialog. 52 * 53 * Params: 54 * parent = The parent window of the dialog. 55 * title = The title of the dialog. 56 */ 57 this(Window parent, string title) 58 { 59 this._typeVariable = format("variable-%s", this.generateHash("%s%s", this._elementId, this.id)); 60 super(parent, title); 61 62 // Fix to hide hidden files by default on Posix systems. This also 63 // enables a checkbutton to show them again within the dialog. 64 version (Posix) 65 { 66 this._tk.eval("catch {tk_getOpenFile foo bar}"); 67 this._tk.eval("set ::tk::dialog::file::showHiddenVar 0"); 68 this._tk.eval("set ::tk::dialog::file::showHiddenBtn 1"); 69 } 70 } 71 72 /** 73 * Construct the dialog. 74 * 75 * Params: 76 * title = The title of the dialog. 77 */ 78 this(string title) 79 { 80 this(null, title); 81 } 82 83 /** 84 * Set the default extension. 85 * 86 * Params: 87 * extension = The default extension. 88 * 89 * Returns: 90 * This dialog to aid method chaining. 91 */ 92 public auto setDefaultExtension(this T)(string extension) 93 { 94 this._defaultExtension = extension; 95 96 return cast(T) this; 97 } 98 99 /** 100 * Add an allowed file type. If a filetype combobox exists in the file 101 * dialog on the particular platform, this adds entries to it. When the 102 * user choose a filetype in the combobox, only the files of that type are 103 * listed. If no types are added or if the filetypes combobox is not 104 * supported by the particular platform then all files are listed 105 * regardless of their types. 106 * 107 * Filetypes must be added in the correct format, i.e. all fields are 108 * enclosed within curly braces and separated by a space. Extensions must 109 * contain a dot. The format is described below in which the carats 110 * indicate essential required space. 111 * ---- 112 * {{Description} {.ext1 .ext2 .ext3 ...}} 113 * ^ ^ ^ ^ 114 * ---- 115 * 116 * Params: 117 * fileType = The file type to add. 118 * 119 * Returns: 120 * This dialog to aid method chaining. 121 */ 122 public auto addFileType(this T)(string fileType) 123 { 124 assert(!std.regex.match(fileType, r"^\{\{.*?\} \{.*?\}\}$").empty, 125 "File type must take the form of '{{Description} {.ext1 .ext2 .ext3 ...}}'. Braces and spaces are important!"); 126 127 this._fileTypes ~= fileType; 128 129 return cast(T) this; 130 } 131 132 /** 133 * Set the initial directory in the dialog. 134 * 135 * Params: 136 * directory = The initial directory. 137 * 138 * Returns: 139 * This dialog to aid method chaining. 140 */ 141 public auto setInitialDirectory(this T)(string directory) 142 { 143 this._initialDirectory = directory; 144 145 return cast(T) this; 146 } 147 148 /** 149 * Set the initial file in the dialog. 150 * 151 * Params: 152 * file = The initial file. 153 * 154 * Returns: 155 * This dialog to aid method chaining. 156 */ 157 public auto setInitialFile(this T)(string file) 158 { 159 this._initialFile = file; 160 161 return cast(T) this; 162 } 163 }