1 //------------------------------------------------------------------------------
2 // emFileSelectionBox.h
3 //
4 // Copyright (C) 2015-2016 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20
21 #ifndef emFileSelectionBox_h
22 #define emFileSelectionBox_h
23
24 #ifndef emCheckBox_h
25 #include <emCore/emCheckBox.h>
26 #endif
27
28 #ifndef emListBox_h
29 #include <emCore/emListBox.h>
30 #endif
31
32 #ifndef emTextField_h
33 #include <emCore/emTextField.h>
34 #endif
35
36
37 //==============================================================================
38 //============================= emFileSelectionBox =============================
39 //==============================================================================
40
41 class emFileSelectionBox : public emBorder {
42
43 public:
44
45 // Class for a file selection box. This allows the user to walk through
46 // the file system, view the contents of a directory, and select one or
47 // optionally more files in it. He may also enter a new file name. The
48 // file selection box is an emBorder whith the following child panels:
49 // - An editable text field for the path of the directory.
50 // - A check box for switching the showing of hidden files on and off.
51 // - A list box which shows the contents of the directory. It has one
52 // item for each file or sub-directory, and the item ".." for the
53 // parent directory. Each item shows the name and an icon (if it's a
54 // directory) or preview (if it's a file).
55 // - An editable text field for the file name.
56 // - A list box for file type filters.
57
58 emFileSelectionBox(
59 ParentArg parent, const emString & name,
60 const emString & caption=emString(),
61 const emString & description=emString(),
62 const emImage & icon=emImage()
63 );
64 // Constructor.
65 // Arguments:
66 // parent - Parent for this panel (emPanel or emView).
67 // name - The name for this panel.
68 // caption - The label's caption, or empty.
69 // description - The label's description, or empty.
70 // icon - The label's icon, or empty.
71
72 virtual ~emFileSelectionBox();
73 // Destructor.
74
75 bool IsMultiSelectionEnabled() const;
76 // Ask whether the user is allowed to select multiple entries.
77
78 void SetMultiSelectionEnabled(bool enabled=true);
79 // Set whether the user is allowed to select multiple entries.
80 // The default is false.
81
82 const emString & GetParentDirectory() const;
83 // Get the absolute path of the parent directory.
84
85 void SetParentDirectory(const emString & parentDirectory);
86 // Set the parent directory.
87
88 emString GetSelectedName() const;
89 // Get the name of the selected entry. If nothing is selected,
90 // an empty string is returned. If multiple entries are
91 // selected, the first one is returned.
92
93 const emArray<emString> & GetSelectedNames() const;
94 // Get an array with the names of all the selected entries.
95
96 void SetSelectedName(const emString & selectedName);
97 // Select a single entry. An empty string means to clear the
98 // selection.
99
100 void SetSelectedNames(const emArray<emString> & selectedNames);
101 // Select any number of entries.
102
103 void ClearSelection();
104 // Clear the selection.
105
106 emString GetSelectedPath() const;
107 // Get the absolute path of the selected entry. If nothing is
108 // selected, the absolute path of the parent directory is
109 // returned. If multiple entries are selected, the absolute path
110 // of the first selected one is returned.
111
112 void SetSelectedPath(const emString & selectedPath);
113 // Change the parent directory and the selection in one call. If
114 // the given path is a directory, the parent directory is set to
115 // that directory, and the selection is cleared. Otherwise the
116 // parent directory is set to the parent path of the given path,
117 // and the selection is set to the final name in the given path.
118
119 const emSignal & GetSelectionSignal() const;
120 // Signaled when the selection or the parent directory has
121 // changed.
122
123 const emArray<emString> & GetFilters() const;
124 // Get the file type filters. See SetFilters for more.
125
126 void SetFilters(const emArray<emString> & filters);
127 // Set the file type filters, from which the user can choose
128 // one. The default is to have no filters, which means to show
129 // all entries. If no filter is selected at the time of calling
130 // SetFilters with a non-empty array, the first filter is
131 // selected automatically. Each filter is a string of the form:
132 // <description>'('<pattern>[<separator><pattern>...]')'
133 // With:
134 // <description> = Any text.
135 // <pattern> = A pattern for the file name. The only supported
136 // meta character is an asterisk ('*'). It
137 // means to match any sequence (including the
138 // empty sequence). Everything else is taken
139 // literal, but case-insensitive.
140 // <separator> = A space char, a semicolon, a comma, or a
141 // vertical bar.
142 // Examples:
143 // "All files (*)"
144 // "Targa files (*.tga)"
145 // "HTML files (*.htm *.html)"
146
147 int GetSelectedFilterIndex() const;
148 // Get the index of the selected filter, or -1 if none is
149 // selected.
150
151 void SetSelectedFilterIndex(int selectedFilterIndex);
152 // Set the index of the selected filter. -1 means to select none.
153
154 bool AreHiddenFilesShown() const;
155 // Ask whether hidden files are shown.
156
157 void SetHiddenFilesShown(bool hiddenFilesShown=true);
158 // Set whether hidden files are shown. The default is false.
159
160 const emSignal & GetFileTriggerSignal() const;
161 // This signal is signaled when the user double-clicks an item
162 // or presses enter in the name field - but only if it is not a
163 // directory. (If it is a directory, the parent directory is
164 // changed instead of sending the signal). The associated name
165 // can be get with GetTriggeredFileName().
166
167 const emString & GetTriggeredFileName() const;
168 // Get the name of the file which was triggered by a
169 // double-click or enter key press.
170
171 void TriggerFile(const emString & name);
172 // Trigger a file name programmatically.
173
174 void EnterSubDir(const emString & name);
175 // Enter a sub-directory programmatically. This is like
176 // SetParentDirectory, but the given string is the name of a
177 // sub-directory instead of a path, and some checks are
178 // performed whether it is really a directory and whether it is
179 // readable.
180
181 bool IsParentDirFieldHidden() const;
182 // Ask whether the text field for the parent directory is
183 // hidden.
184
185 void SetParentDirFieldHidden(bool parentDirFieldHidden=true);
186 // Set whether to hide the text field for the parent directory.
187 // The default is false.
188
189 bool IsHiddenCheckBoxHidden() const;
190 // Ask whether the "show hidden files" check box is hidden.
191
192 void SetHiddenCheckBoxHidden(bool hiddenCheckBoxHidden=true);
193 // Set whether to hide the "show hidden files" check box. The
194 // default is false.
195
196 bool IsNameFieldHidden() const;
197 // Ask whether the text field for the name is hidden.
198
199 void SetNameFieldHidden(bool nameFieldHidden=true);
200 // Set whether to hide the text field for the name. The default
201 // is false.
202
203 bool IsFilterHidden() const;
204 // Ask whether the list box for the filters is hidden.
205
206 void SetFilterHidden(bool filterHidden=true);
207 // Set whether to hide the list box for the filters. The default
208 // is false.
209
210 protected:
211
212 virtual bool Cycle();
213 virtual void Input(emInputEvent & event, const emInputState & state,
214 double mx, double my);
215 virtual void AutoExpand();
216 virtual void AutoShrink();
217 virtual void LayoutChildren();
218
219 private:
220
221 void InvalidateListing();
222 void ReloadListing();
223 void SelectionToListBox();
224 void SelectionFromListBox();
225
226 static int CompareNames(
227 const emString * name1, const emString * name2, void * context
228 );
229
230 static bool MatchFileNameFilter(const char * fileName, const char * filter);
231 static bool MatchFileNamePattern(const char * fileName, const char * pattern,
232 const char * patternEnd);
233
234 class FilesListBox;
235 class FileItemPanel;
236 class FileOverlayPanel;
237 friend class FilesListBox;
238 friend class FileItemPanel;
239
240 class FilesListBox : public emListBox {
241 public:
242 FilesListBox(emFileSelectionBox & parent, const emString & name);
243 virtual ~FilesListBox();
244 emFileSelectionBox & GetFileSelectionBox() const;
245 const emImage & GetDirImage() const;
246 const emImage & GetDirUpImage() const;
247 protected:
248 virtual void CreateItemPanel(const emString & name, int itemIndex);
249 };
250
251 class FileItemPanel : public emPanel, public emListBox::ItemPanelInterface {
252 public:
253 FileItemPanel(FilesListBox & listBox, const emString & name, int itemIndex);
254 virtual ~FileItemPanel();
255 protected:
256 virtual void Notice(NoticeFlags flags);
257 virtual void Input(emInputEvent & event, const emInputState & state,
258 double mx, double my);
259 virtual bool IsOpaque() const;
260 virtual void Paint(const emPainter & painter, emColor canvasColor) const;
261 virtual void AutoExpand();
262 virtual void AutoShrink();
263 virtual void LayoutChildren();
264 virtual void ItemTextChanged();
265 virtual void ItemDataChanged();
266 virtual void ItemSelectionChanged();
267 private:
268 emColor GetBgColor() const;
269 emColor GetFgColor() const;
270 friend class FileOverlayPanel;
271 FilesListBox & ListBox;
272 emPanel * FilePanel;
273 emPanel * OverlayPanel;
274 };
275
276 class FileOverlayPanel : public emPanel {
277 public:
278 FileOverlayPanel(FileItemPanel & parent, const emString & name);
279 virtual ~FileOverlayPanel();
280 protected:
281 virtual void Input(emInputEvent & event, const emInputState & state,
282 double mx, double my);
283 };
284
285 struct FileItemData {
286 bool IsDirectory;
287 bool IsReadable;
288 bool IsHidden;
289 };
290
291 bool MultiSelectionEnabled;
292 emString ParentDir;
293 emArray<emString> SelectedNames;
294 emSignal SelectionSignal;
295 emArray<emString> Filters;
296 int SelectedFilterIndex;
297 bool HiddenFilesShown;
298
299 emSignal FileTriggerSignal;
300 emString TriggeredFileName;
301
302 bool ParentDirFieldHidden;
303 bool HiddenCheckBoxHidden;
304 bool NameFieldHidden;
305 bool FilterHidden;
306
307 emTextField * ParentDirField;
308 emCheckBox * HiddenCheckBox;
309 FilesListBox * FilesLB;
310 emTextField * NameField;
311 emListBox * FiltersLB;
312
313 bool ListingInvalid;
314 };
315
IsMultiSelectionEnabled()316 inline bool emFileSelectionBox::IsMultiSelectionEnabled() const
317 {
318 return MultiSelectionEnabled;
319 }
320
GetParentDirectory()321 inline const emString & emFileSelectionBox::GetParentDirectory() const
322 {
323 return ParentDir;
324 }
325
GetSelectedNames()326 inline const emArray<emString> & emFileSelectionBox::GetSelectedNames() const
327 {
328 return SelectedNames;
329 }
330
GetSelectionSignal()331 inline const emSignal & emFileSelectionBox::GetSelectionSignal() const
332 {
333 return SelectionSignal;
334 }
335
GetFilters()336 inline const emArray<emString> & emFileSelectionBox::GetFilters() const
337 {
338 return Filters;
339 }
340
GetSelectedFilterIndex()341 inline int emFileSelectionBox::GetSelectedFilterIndex() const
342 {
343 return SelectedFilterIndex;
344 }
345
AreHiddenFilesShown()346 inline bool emFileSelectionBox::AreHiddenFilesShown() const
347 {
348 return HiddenFilesShown;
349 }
350
GetFileTriggerSignal()351 inline const emSignal & emFileSelectionBox::GetFileTriggerSignal() const
352 {
353 return FileTriggerSignal;
354 }
355
GetTriggeredFileName()356 inline const emString & emFileSelectionBox::GetTriggeredFileName() const
357 {
358 return TriggeredFileName;
359 }
360
IsParentDirFieldHidden()361 inline bool emFileSelectionBox::IsParentDirFieldHidden() const
362 {
363 return ParentDirFieldHidden;
364 }
365
IsHiddenCheckBoxHidden()366 inline bool emFileSelectionBox::IsHiddenCheckBoxHidden() const
367 {
368 return HiddenCheckBoxHidden;
369 }
370
IsNameFieldHidden()371 inline bool emFileSelectionBox::IsNameFieldHidden() const
372 {
373 return NameFieldHidden;
374 }
375
IsFilterHidden()376 inline bool emFileSelectionBox::IsFilterHidden() const
377 {
378 return FilterHidden;
379 }
380
GetFileSelectionBox()381 inline emFileSelectionBox & emFileSelectionBox::FilesListBox::GetFileSelectionBox() const
382 {
383 return *((emFileSelectionBox*)GetParent());
384 }
385
GetDirImage()386 inline const emImage & emFileSelectionBox::FilesListBox::GetDirImage() const
387 {
388 return GetTkResources().ImgDir;
389 }
390
GetDirUpImage()391 inline const emImage & emFileSelectionBox::FilesListBox::GetDirUpImage() const
392 {
393 return GetTkResources().ImgDirUp;
394 }
395
396
397 #endif
398