.
1 /*
2 Copyright (C) 2014 2015 Johan Mattsson
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 3 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13 */
14 using Cairo;
15 using Math;
16
17 namespace BirdFont {
18
19 public class FileDialogTab : Table {
20 Gee.ArrayList<Row> rows;
21
22 const int DIRECTORY = -3;
23 const int FILE = -2;
24
25 Gee.ArrayList<string> files;
26 Gee.ArrayList<string> directories;
27
28 string title;
29 FileChooser action;
30
31 File current_dir;
32
33 string selected_filename;
34 TextListener listener;
35
36 private static bool has_drive_letters = false;
37 private static Gee.ArrayList<string> drive_letters;
38
39 bool select_folder = false;
40
41 #if LINUX
42 public static const string path_separator = "/";
43 #else
44 public static const string path_separator = "\\";
45 #endif
46
47 public FileDialogTab (string title, FileChooser action, bool folder) {
48 this.title = title;
49 this.action = action;
50
51 select_folder = folder;
52 rows = new Gee.ArrayList<Row> ();
53 files = new Gee.ArrayList<string> ();
54 directories = new Gee.ArrayList<string> ();
55
56 selected_filename = "";
57 selected_canvas ();
58 }
59
60 public static void add_drive_letter (char c) {
61 if (!has_drive_letters) {
62 drive_letters = new Gee.ArrayList<string> ();
63 has_drive_letters = true;
64 }
65
66 drive_letters.add (@"$((!) c.to_string ()):\\");
67 }
68
69 public override void update_rows () {
70 Row row;
71
72 rows.clear ();
73
74 // add empty rows under the text area
75 row = new Row.headline ("");
76 rows.add (row);
77
78 if (select_folder) {
79 row = new Row.headline (t_("Select a Folder"));
80 }
81
82 if (directories.size > 0) {
83 row = new Row.headline (t_("Folders"));
84 rows.add (row);
85 }
86
87 foreach (string dir in directories) {
88 row = new Row.columns_1 (dir, DIRECTORY, false);
89 row.set_row_data (new SelectedFile (dir));
90 rows.add (row);
91 }
92
93 if (files.size > 0) {
94 row = new Row.headline (t_("Files"));
95 rows.add (row);
96 }
97
98 foreach (string f in files) {
99 row = new Row.columns_1 (f, FILE, false);
100 row.set_row_data (new SelectedFile (f));
101 rows.add (row);
102 }
103
104 GlyphCanvas.redraw ();
105 }
106
107 public override Gee.ArrayList<Row> get_rows () {
108 return rows;
109 }
110
111 public override void selected_row (Row row, int column, bool delete_button) {
112 SelectedFile f;
113
114 if (row.get_index () == FILE) {
115 if (!select_folder) {
116 return_if_fail (row.get_row_data () is SelectedFile);
117 f = (SelectedFile) row.get_row_data ();
118 selected_filename = f.file_name;
119 }
120 } else if (row.get_index () == DIRECTORY) {
121 return_if_fail (row.get_row_data () is SelectedFile);
122 f = (SelectedFile) row.get_row_data ();
123
124 if (select_folder && f.file_name != "..") {
125 selected_filename = f.file_name;
126 } else {
127 if (f.file_name.index_of (":") > -1) {
128 propagate_files (f.file_name);
129 } else {
130 string d = (!) current_dir.get_path ();
131 printd (@"Subdir: $(f.file_name) in $d path_separator: $path_separator\n");
132 string p = d + path_separator + f.file_name;
133
134 while (p.index_of ("\\\\") != -1) {
135 p = p.replace ("\\\\", "\\");
136 }
137
138 propagate_files (p);
139 }
140
141 selected_filename = "";
142 }
143 }
144
145 show_text_area (selected_filename);
146 }
147
148 public override void selected_canvas () {
149 string d;
150 show_text_area ("");
151
152 d = Preferences.get ("file_dialog_dir");
153
154 if (d == "") {
155 d = Environment.get_home_dir ();
156 }
157
158 propagate_files (d);
159 base.selected_canvas ();
160 }
161
162 public void propagate_files (string dir) {
163 FileEnumerator enumerator;
164 FileInfo? file_info;
165 string fn;
166
167 printd (@"Propagate_files in directory: $dir\n");
168
169 files.clear ();
170 directories.clear ();
171
172 current_dir = File.new_for_path (dir);
173
174 Preferences.set ("file_dialog_dir", dir);
175
176 if (current_dir.get_parent () != null) {
177 directories.add ("..");
178 }
179
180 try {
181 enumerator = current_dir.enumerate_children (FileAttribute.STANDARD_NAME + "," + FileAttribute.STANDARD_TYPE, 0);
182
183 while ((file_info = enumerator.next_file ()) != null) {
184 fn = ((!)file_info).get_name ();
185 if (!fn.has_prefix (".")) {
186 if (((!)file_info).get_file_type () == FileType.DIRECTORY) {
187 directories.add (fn);
188 } else {
189 files.add (fn);
190 }
191 }
192 }
193 } catch (Error e) {
194 warning (e.message);
195 }
196
197 directories.sort ();
198
199 if (has_drive_letters) {
200 for (int i = drive_letters.size - 1; i >= 0; i--) {
201 directories.insert (0, drive_letters.get (i));
202 }
203 }
204
205 files.sort ();
206
207 layout ();
208 base.selected_canvas ();
209 scroll_to (0);
210 MainWindow.show_scrollbar ();
211 }
212
213 public void show_text_area (string text) {
214 listener = new TextListener ("", text, this.title);
215
216 listener.signal_text_input.connect ((text) => {
217 selected_filename = text;
218 });
219
220 listener.signal_submit.connect (() => {
221 File f;
222
223 MainWindow.get_tab_bar ().close_display (this);
224
225 if (selected_filename == "") {
226 action.cancel ();
227 } else {
228 if (selected_filename.index_of (":\\") != -1) {
229 f = File.new_for_path (selected_filename);
230 } else {
231 f = get_child (current_dir, selected_filename);
232 }
233
234 action.file_selected ((!)f.get_path ());
235 }
236 });
237
238 TabContent.show_text_input (listener);
239 }
240
241 public override void double_click (uint button, double ex, double ey) {
242 File f;
243
244 button_release ((int) button, ex, ey);
245
246 if (is_null (selected_filename)) {
247 warning ("No file.");
248 return;
249 }
250
251 if (select_folder) {
252 if (selected_filename.index_of (":") > -1) {
253 propagate_files (selected_filename);
254 } else {
255 propagate_files (((!) current_dir.get_path ()) + path_separator + selected_filename);
256 }
257 } else {
258 if (selected_filename != "") {
259 f = get_child (current_dir, selected_filename);
260 action.file_selected ((!) f.get_path ());
261 }
262 }
263
264 MainWindow.show_scrollbar ();
265 }
266
267 public override string get_label () {
268 return title;
269 }
270
271 public override string get_name () {
272 return "FileDialogTab";
273 }
274
275 public override void button_release (int button, double ex, double ey) {
276 base.button_release (button, ex, ey);
277 show_text_area (selected_filename);
278 MainWindow.show_scrollbar ();
279 }
280
281 class SelectedFile : GLib.Object {
282 public string file_name;
283
284 public SelectedFile (string fn) {
285 file_name = fn;
286 }
287 }
288 }
289
290 }
291