.
1 /*
2 Copyright (C) 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
15 using Cairo;
16 using Math;
17
18 namespace BirdFont {
19
20 /** A list of recently edited fonts. */
21 public class RecentFiles : Table {
22 Gee.ArrayList<Row> rows = new Gee.ArrayList<Row> ();
23
24 const int CURRENT_FONT = -4;
25 const int RECENT_FONT = -3;
26 const int BACKUP = -2;
27
28 public RecentFiles () {
29 }
30
31 public override Gee.ArrayList<Row> get_rows () {
32 return rows;
33 }
34
35 public override void selected_row (Row row, int column, bool delete_button) {
36 Font f;
37
38 if (row.get_index () == RECENT_FONT) {
39 return_if_fail (row.get_row_data () is Font);
40 f = (Font) row.get_row_data ();
41 load_font (f.get_path ());
42 }
43
44 if (row.get_index () == BACKUP) {
45 return_if_fail (row.get_row_data () is Font);
46 f = (Font) row.get_row_data ();
47 delete_backup (f.get_file_name ());
48 }
49 }
50
51 public override void update_rows () {
52 Row row;
53 Gee.ArrayList<Font> recent_fonts = get_recent_font_files ();
54 Gee.ArrayList<Font> backups = get_backups ();
55 Font current_font = BirdFont.get_current_font ();
56
57 rows.clear ();
58
59 if (current_font.font_file != null) {
60 row = new Row.headline (current_font.get_file_name ());
61 rows.add (row);
62
63 row = new Row.columns_1 (t_("Folder") + ": " + (!) current_font.get_folder ().get_path (), CURRENT_FONT, false);
64 rows.add (row);
65
66 row = new Row.columns_1 (t_("Glyphs") + @": $(current_font.length ())", CURRENT_FONT, false);
67 rows.add (row);
68 }
69
70 if (recent_fonts.size > 0) {
71 row = new Row.headline (t_("Recent Files"));
72 rows.add (row);
73 }
74
75 foreach (Font font in recent_fonts) {
76 row = new Row.columns_1 (font.get_file_name (), RECENT_FONT, false);
77 row.set_row_data (font);
78 rows.add (row);
79 }
80
81 if (backups.size > 0) {
82 row = new Row.headline (t_("Backups"));
83 rows.add (row);
84 }
85
86 foreach (Font font in backups) {
87 row = new Row.columns_1 (font.get_file_name (), BACKUP, true);
88 row.set_row_data (font);
89 rows.add (row);
90 }
91
92 GlyphCanvas.redraw ();
93 }
94
95 public override string get_label () {
96 return t_("Files");
97 }
98
99 public override string get_name () {
100 return "Files";
101 }
102
103 public Gee.ArrayList<Font> get_recent_font_files () {
104 File file;
105 Font font;
106 bool unique;
107 Gee.ArrayList<Font> fonts = new Gee.ArrayList<Font> ();
108
109 foreach (string f in Preferences.get_recent_files ()) {
110 if (f == "") {
111 continue;
112 }
113
114 file = File.new_for_path (f);
115
116 font = new Font ();
117 font.set_font_file (f);
118
119 unique = true;
120 foreach (Font recent_font in fonts) {
121 if (recent_font.get_path () == f) {
122 unique = false;
123 }
124 }
125
126 if (unique && file.query_exists ()) {
127 fonts.insert (0, font);
128 }
129 }
130
131 return fonts;
132 }
133
134 public Gee.ArrayList<Font> get_backups () {
135 FileEnumerator enumerator;
136 string file_name;
137 FileInfo? file_info;
138 Gee.ArrayList<Font> backups = new Gee.ArrayList<Font> ();
139 File dir = BirdFont.get_backup_directory ();
140 Font font = BirdFont.get_current_font ();
141 Font backup_font;
142
143 try {
144 enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, 0);
145 while ((file_info = enumerator.next_file ()) != null) {
146 file_name = ((!) file_info).get_name ();
147
148 // ignore old backup files
149 if (file_name.has_prefix ("current_font_")) {
150 continue;
151 }
152
153 // ignore backup of the current font
154 if (file_name == @"$(font.get_name ()).bf") {
155 continue;
156 }
157
158 backup_font = new Font ();
159 backup_font.set_font_file ((!) get_child (dir, file_name).get_path ());
160 backups.insert (0, backup_font);
161 }
162 } catch (Error e) {
163 warning (e.message);
164 }
165
166 return backups;
167 }
168
169 public void delete_backup (string file_name) {
170 File backup_file;
171
172 try {
173 backup_file = BirdFont.get_backup_directory ();
174 backup_file = get_child (backup_file, file_name);
175 if (backup_file.query_exists ()) {
176 backup_file.delete ();
177 }
178 } catch (GLib.Error e) {
179 warning (e.message);
180 }
181
182 selected_canvas ();
183 }
184
185 public static void load_font (string fn) {
186 Font font;
187 SaveDialogListener dialog = new SaveDialogListener ();
188
189 if (MenuTab.suppress_event) {
190 return;
191 }
192
193 font = BirdFont.get_current_font ();
194
195 MenuTab.load_callback = new LoadCallback ();
196 MenuTab.load_callback.file_loaded.connect (() => {
197 Font f;
198
199 if (MenuTab.suppress_event) {
200 return;
201 }
202
203 f = BirdFont.get_current_font ();
204
205 MainWindow.get_drawing_tools ().remove_all_grid_buttons ();
206 foreach (string v in f.grid_width) {
207 MainWindow.get_drawing_tools ().parse_grid (v);
208 }
209
210 DrawingTools.background_scale.set_value (f.background_scale);
211 KerningTools.update_kerning_classes ();
212 MenuTab.show_all_available_characters ();
213 });
214
215 dialog.signal_discard.connect (() => {
216 Font f;
217
218 if (MenuTab.suppress_event) {
219 return;
220 }
221
222 f = BirdFont.new_font ();
223
224 MainWindow.clear_glyph_cache ();
225 MainWindow.close_all_tabs ();
226
227 f.set_file (fn);
228 Preferences.add_recent_files (fn);
229
230 MainWindow.native_window.load (); // background thread
231 });
232
233 dialog.signal_save.connect (() => {
234 if (MenuTab.suppress_event) {
235 warn_if_test ("Event suppressed.");
236 return;
237 }
238
239 MenuTab.set_save_callback (new SaveCallback ());
240 MenuTab.save_callback.file_saved.connect (() => {
241 dialog.signal_discard ();
242 });
243 MenuTab.save_callback.save (); // background thread
244 });
245
246 dialog.signal_cancel.connect (() => {
247 MainWindow.hide_dialog ();
248 });
249
250 if (!font.is_modified ()) {
251 dialog.signal_discard ();
252 } else {
253 MainWindow.show_dialog (new SaveDialog (dialog));
254 }
255 }
256 }
257
258 }
259