The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

FileTab.vala in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/FileTab.vala.
Use table in recent files tab
1 /* 2 Copyright (C) 2013 2014 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 FileTab : FontDisplay { 20 21 int scroll = 0; 22 int visible_rows = 0; 23 double row_height; 24 double top; 25 WidgetAllocation allocation = new WidgetAllocation (); 26 Gee.ArrayList<Font> recent_fonts = new Gee.ArrayList<Font> (); 27 Gee.ArrayList<string> backups = new Gee.ArrayList<string> (); // FIXME: use ref counted object 28 29 Button create_new_font; 30 31 public signal void open_file (); 32 33 public FileTab () { 34 row_height = 30 * MainWindow.units; 35 top = 2 * row_height; 36 create_new_font = new Button (t_("New Font")); 37 create_new_font.widget_x = 50 * MainWindow.units; 38 create_new_font.widget_y = top + 20 * MainWindow.units; 39 40 create_new_font.action.connect (() => { 41 MenuTab.new_file (); 42 }); 43 } 44 45 public static void load_font (string fn) { 46 Font font; 47 SaveDialogListener dialog = new SaveDialogListener (); 48 49 if (MenuTab.suppress_event) { 50 return; 51 } 52 53 font = BirdFont.get_current_font (); 54 55 MenuTab.load_callback = new LoadCallback (); 56 MenuTab.load_callback.file_loaded.connect (() => { 57 Font f; 58 59 if (MenuTab.suppress_event) { 60 return; 61 } 62 63 f = BirdFont.get_current_font (); 64 65 MainWindow.get_drawing_tools ().remove_all_grid_buttons (); 66 foreach (string v in f.grid_width) { 67 MainWindow.get_drawing_tools ().parse_grid (v); 68 } 69 70 DrawingTools.background_scale.set_value (f.background_scale); 71 KerningTools.update_kerning_classes (); 72 MenuTab.show_all_available_characters (); 73 }); 74 75 dialog.signal_discard.connect (() => { 76 Font f; 77 78 if (MenuTab.suppress_event) { 79 return; 80 } 81 82 f = BirdFont.new_font (); 83 84 MainWindow.clear_glyph_cache (); 85 MainWindow.close_all_tabs (); 86 87 f.set_file (fn); 88 Preferences.add_recent_files (fn); 89 90 MainWindow.native_window.load (); // background thread 91 }); 92 93 dialog.signal_save.connect (() => { 94 if (MenuTab.suppress_event) { 95 warn_if_test ("Event suppressed."); 96 return; 97 } 98 99 MenuTab.set_save_callback (new SaveCallback ()); 100 MenuTab.save_callback.file_saved.connect (() => { 101 dialog.signal_discard (); 102 }); 103 MenuTab.save_callback.save (); // background thread 104 }); 105 106 dialog.signal_cancel.connect (() => { 107 MainWindow.hide_dialog (); 108 }); 109 110 if (!font.is_modified ()) { 111 dialog.signal_discard (); 112 } else { 113 MainWindow.show_dialog (new SaveDialog (dialog)); 114 } 115 } 116 117 public void load_backup (string file_name) { 118 File backup_file; 119 120 if (MenuTab.suppress_event) { 121 return; 122 } 123 124 backup_file = BirdFont.get_backup_directory (); 125 backup_file = get_child (backup_file, file_name); 126 load_font ((!) backup_file.get_path ()); 127 } 128 129 public void delete_backup (string file_name) { 130 File backup_file; 131 132 if (MenuTab.suppress_event) { 133 return; 134 } 135 136 try { 137 backup_file = BirdFont.get_backup_directory (); 138 backup_file = get_child (backup_file, file_name); 139 if (backup_file.query_exists ()) { 140 backup_file.delete (); 141 } 142 } catch (GLib.Error e) { 143 warning (e.message); 144 } 145 146 selected_canvas (); 147 } 148 149 public override void button_press (uint button, double ex, double ey) { 150 if (recent_fonts.size == 0 && !has_backup ()) { 151 create_new_font.button_press (button, ex, ey); 152 } 153 } 154 155 public override void button_release (int button, double ex, double ey) { 156 int r, i; 157 158 if (MenuTab.suppress_event) { 159 return; 160 } 161 162 return_if_fail (!is_null(this)); 163 164 r = (int) rint ((ey - 17) / row_height) + scroll; 165 i = scroll; 166 167 if (scroll == 0) { 168 i += 2; // heading 169 } else { 170 i -= scroll; // no headline 171 } 172 173 if (button != 1) { 174 return; 175 } 176 177 if (is_null (recent_fonts)) { 178 warning ("No recent fonts"); 179 return; 180 } 181 182 foreach (Font font in recent_fonts) { 183 184 if (is_null (font)) { 185 warning ("Can't find font in list."); 186 break; 187 } 188 189 if (is_null (font.font_file)) { 190 warning ("File is not set for font."); 191 break; 192 } 193 194 if (i == r) { 195 load_font ((!) font.font_file); 196 open_file (); 197 198 // open_file will close this tab and the list of files 199 // will be deleted here. 200 201 return; 202 } 203 i++; 204 } 205 206 if (is_null (backups)) { 207 // FIXME: 208 // warning ("No backups"); 209 return; 210 } 211 212 i += 2; 213 foreach (string backup in backups) { 214 if (i == r) { 215 if (ex < 35) { 216 delete_backup (backup); 217 } else { 218 load_backup (backup); 219 open_file (); 220 return; 221 } 222 } 223 i++; 224 } 225 } 226 227 public override void draw (WidgetAllocation allocation, Context cr) { 228 double y = 0; 229 int s = 0; 230 bool color = (scroll % 2) == 0; 231 232 this.allocation = allocation; 233 234 if (scroll == 0) { 235 y += top; 236 } 237 238 visible_rows = (int) (allocation.height / row_height); 239 240 cr.save (); 241 Theme.color (cr, "Background 1"); 242 cr.rectangle (0, 0, allocation.width, allocation.height); 243 cr.fill (); 244 cr.restore (); 245 246 if (recent_fonts.size == 0 && !has_backup ()) { 247 cr.save (); 248 Theme.color (cr, "Foreground 2"); 249 cr.set_font_size (18 * MainWindow.units); 250 cr.move_to (50 * MainWindow.units, top - 9 * MainWindow.units); 251 cr.show_text (t_("No fonts created yet.")); 252 cr.restore (); 253 254 create_new_font.draw (cr); 255 } 256 257 if (scroll == 0 && recent_fonts.size > 0) { 258 cr.save (); 259 Theme.color (cr, "Foreground 2"); 260 cr.set_font_size (18 * MainWindow.units); 261 cr.move_to (50 * MainWindow.units, top - 9 * MainWindow.units); 262 cr.show_text (t_("Recent files")); 263 cr.restore (); 264 } 265 266 cr.save (); 267 Theme.color (cr, "Background 5"); 268 cr.set_font_size (12 * MainWindow.units); 269 270 foreach (Font font in recent_fonts) { 271 if (s++ >= scroll) { 272 draw_file_row (allocation, cr, font, color, y); 273 y += row_height; 274 color = !color; 275 } 276 } 277 278 if (has_backup ()) { 279 color = true; 280 281 if (s >= scroll) { 282 cr.save (); 283 Theme.color (cr, "Background 5"); 284 cr.set_font_size (18 * MainWindow.units); 285 cr.move_to (50 * MainWindow.units, y + 2 * row_height - 9 * MainWindow.units); 286 cr.show_text (t_("Backup")); 287 cr.restore (); 288 s += 2; 289 y += 2 * row_height; 290 } 291 292 foreach (string backup in backups) { 293 if (s++ >= scroll) { 294 draw_backup_row (allocation, cr, backup, color, y); 295 y += row_height; 296 color = !color; 297 } 298 } 299 } 300 301 cr.restore (); 302 } 303 304 private void draw_file_row (WidgetAllocation allocation, Context cr, Font font, bool color, double y) { 305 string fn = (!) font.font_file; 306 Text file; 307 308 fn = fn.substring (fn.replace ("\\", "/").last_index_of ("/") + 1); 309 draw_background (cr, allocation, y, color); 310 311 file = new Text (fn); 312 Theme.text_color (file, "Foreground 6"); 313 file.widget_x = 50 * MainWindow.units; 314 file.widget_y = y + 5 * MainWindow.units; 315 file.draw (cr); 316 } 317 318 private void draw_backup_row (WidgetAllocation allocation, Context cr, string backup, bool color, double y) { 319 File thumbnail; 320 double u = MainWindow.units; 321 322 thumbnail = get_child (BirdFont.get_thumbnail_directory (), backup); 323 324 draw_background (cr, allocation, y, color); 325 326 cr.move_to (50 * u, y + row_height / 2 + 5 * u); 327 cr.show_text (backup); 328 329 // draw x 330 cr.move_to ((35 - 5) * u, y + row_height / 2 + (12 - 14) * u); 331 cr.line_to ((35 - 10) * u, y + row_height / 2 + (12 - 9) * u); 332 333 cr.move_to ((35 - 10) * u, y + row_height / 2 + (12 - 14) * u); 334 cr.line_to ((35 - 5) * u, y + row_height / 2 + (12 - 9) * u); 335 336 cr.stroke (); 337 } 338 339 void draw_background (Context cr, WidgetAllocation allocation, double y, bool color) { 340 if (color) { 341 draw_background_color (cr, allocation, y, 1); 342 } else { 343 draw_background_color (cr, allocation, y, 0.5); 344 } 345 } 346 347 void draw_background_color (Context cr, WidgetAllocation allocation, double y, double opacity) { 348 cr.save (); 349 Theme.color_opacity (cr, "Background 10", opacity); 350 cr.rectangle (0, y, allocation.width, row_height); 351 cr.fill (); 352 cr.restore (); 353 } 354 355 public override string get_label () { 356 return t_("Files"); 357 } 358 359 public override string get_name () { 360 return "Files"; 361 } 362 363 public override bool has_scrollbar () { 364 return true; 365 } 366 367 public override void scroll_wheel_down (double x, double y) { 368 uint r = rows (); 369 370 if (r > visible_rows) { 371 scroll += 2; 372 } 373 374 if (scroll > r - visible_rows) { 375 scroll = (int) (r - visible_rows); 376 } 377 378 if (scroll < 0) { 379 scroll = 0; 380 } 381 382 update_scrollbar (); 383 redraw_area (0, 0, allocation.width, allocation.height); 384 } 385 386 public override void scroll_wheel_up (double x, double y) { 387 scroll -= 2; 388 389 if (scroll < 0) { 390 scroll = 0; 391 } 392 393 update_scrollbar (); 394 redraw_area (0, 0, allocation.width, allocation.height); 395 } 396 397 public override void selected_canvas () { 398 update_recent_files (); 399 update_scrollbar (); 400 401 backups.clear (); 402 403 backups = get_backups (); 404 redraw_area (0, 0, allocation.width, allocation.height); 405 } 406 407 public override void update_scrollbar () { 408 int r = rows (); 409 410 if (r == 0 || visible_rows == 0) { 411 MainWindow.set_scrollbar_size (0); 412 MainWindow.set_scrollbar_position (0); 413 } else { 414 MainWindow.set_scrollbar_size ((double) visible_rows / r); 415 MainWindow.set_scrollbar_position ((double) scroll / r); 416 } 417 } 418 419 public override void scroll_to (double percent) { 420 int r = rows (); 421 scroll = (int) (percent * r); 422 423 if (scroll > r - visible_rows) { 424 scroll = (int) (r - visible_rows); 425 } 426 427 redraw_area (0, 0, allocation.width, allocation.height); 428 } 429 430 int rows () { 431 int l = (int) (recent_fonts.size + backups.size); 432 433 if (has_backup ()) { 434 l += 2; 435 } 436 437 l += 2; 438 return l; 439 } 440 441 public void update_recent_files () { 442 Font font; 443 444 recent_fonts.clear (); 445 446 foreach (var f in Preferences.get_recent_files ()) { 447 if (f == "") continue; 448 449 File file = File.new_for_path (f); 450 451 font = new Font (); 452 453 font.set_font_file (f); 454 455 if (file.query_exists ()) { 456 recent_fonts.insert (0, font); 457 } 458 } 459 } 460 461 bool has_backup () { 462 return backups.size > 0; 463 } 464 465 public static void delete_backups () { 466 FileEnumerator enumerator; 467 FileInfo? file_info; 468 string file_name; 469 File backup_file; 470 File dir = BirdFont.get_backup_directory (); 471 472 try { 473 enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); 474 while ((file_info = enumerator.next_file ()) != null) { 475 file_name = ((!) file_info).get_name (); 476 backup_file = get_child (dir, file_name); 477 backup_file.delete (); 478 } 479 } catch (Error e) { 480 warning (e.message); 481 } 482 } 483 484 public Gee.ArrayList<string> get_backups () { 485 FileEnumerator enumerator; 486 string file_name; 487 FileInfo? file_info; 488 Gee.ArrayList<string> backups = new Gee.ArrayList<string> (); 489 File dir = BirdFont.get_backup_directory (); 490 Font font = BirdFont.get_current_font (); 491 492 try { 493 enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); 494 while ((file_info = enumerator.next_file ()) != null) { 495 file_name = ((!) file_info).get_name (); 496 497 // ignore old backup files 498 if (file_name.has_prefix ("current_font_")) { 499 continue; 500 } 501 502 // ignore backup of the current font 503 if (file_name == @"$(font.get_name ()).bf") { 504 continue; 505 } 506 507 backups.insert (0, file_name); 508 } 509 } catch (Error e) { 510 warning (e.message); 511 } 512 513 return backups; 514 } 515 } 516 517 } 518