.
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 }
211
212 public void show_text_area (string text) {
213 listener = new TextListener ("", text, this.title);
214
215 listener.signal_text_input.connect ((text) => {
216 selected_filename = text;
217 });
218
219 listener.signal_submit.connect (() => {
220 File f;
221
222 MainWindow.get_tab_bar ().close_display (this);
223
224 if (selected_filename == "") {
225 action.cancel ();
226 } else {
227 f = get_child (current_dir, selected_filename);
228 action.file_selected ((!)f.get_path ());
229 }
230 });
231
232 TabContent.show_text_input (listener);
233 }
234
235 public override void double_click (uint button, double ex, double ey) {
236 File f;
237
238 button_release ((int) button, ex, ey);
239
240 if (is_null (selected_filename)) {
241 warning ("No file.");
242 return;
243 }
244
245 if (select_folder) {
246 if (selected_filename.index_of (":") > -1) {
247 propagate_files (selected_filename);
248 } else {
249 propagate_files (((!) current_dir.get_path ()) + path_separator + selected_filename);
250 }
251 } else {
252 if (selected_filename != "") {
253 f = get_child (current_dir, selected_filename);
254 action.file_selected ((!) f.get_path ());
255 }
256 }
257 }
258
259 public override string get_label () {
260 return title;
261 }
262
263 public override string get_name () {
264 return "FileDialogTab";
265 }
266
267 public override void button_release (int button, double ex, double ey) {
268 base.button_release (button, ex, ey);
269 show_text_area (selected_filename);
270 }
271
272 class SelectedFile : GLib.Object {
273 public string file_name;
274
275 public SelectedFile (string fn) {
276 file_name = fn;
277 }
278 }
279 }
280
281 }
282