The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

GtkWindow.vala in birdfont

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 birdfont/GtkWindow.vala.
Fix selection in overview
1 /* 2 Copyright (C) 2012, 2013, 2014 Johan Mattsson 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 using Cairo; 19 using Gtk; 20 using Gdk; 21 using BirdFont; 22 using WebKit; 23 using Gdk; 24 using Notify; 25 26 namespace BirdFont { 27 28 public class GtkWindow : Gtk.Window, NativeWindow { 29 30 Box list_box; 31 Box canvas_box; 32 33 WebView html_canvas; 34 ScrolledWindow html_box; 35 36 Box tab_box; 37 38 GlyphCanvasArea glyph_canvas_area; 39 40 Clipboard clipboard; 41 string clipboard_svg = ""; 42 string inkscape_clipboard = ""; 43 44 Scrollbar scrollbar; 45 bool scrollbar_supress_signal = false; 46 47 DescriptionForm description; 48 49 /** Text input and callbacks. */ 50 public static bool text_input_is_active = false; 51 TextListener text_listener = new TextListener ("", "", ""); 52 Label text_input_label; 53 Entry text_entry; 54 Box text_box; 55 Gtk.Button submit_text_button; 56 57 Gtk.Window tooltip_window = new Gtk.Window (); 58 59 ToolboxCanvas toolbox; 60 61 Task background_task = new Task (); 62 63 public GtkWindow (string title) { 64 scrollbar = new Scrollbar (Orientation.VERTICAL, new Adjustment (0, 0, 1, 1, 0.01, 0.1)); 65 ((Gtk.Window)this).set_title ("BirdFont"); 66 } 67 68 public void init () { 69 Notify.init ("Fonts have been exported."); 70 71 description = new DescriptionForm (); 72 73 clipboard = Clipboard.get_for_display (get_display (), Gdk.SELECTION_CLIPBOARD); 74 75 scrollbar.value_changed.connect (() => { 76 double p; 77 78 if (!scrollbar_supress_signal) { 79 p = scrollbar.get_value () / (1 - scrollbar.adjustment.page_size); 80 FontDisplay display = MainWindow.get_current_display (); 81 display.scroll_to (p); 82 } 83 }); 84 85 delete_event.connect (() => { 86 MenuTab.quit (); 87 return true; 88 }); 89 90 set_size_and_position (); 91 92 glyph_canvas_area = new GlyphCanvasArea (MainWindow.glyph_canvas); 93 94 html_canvas = new WebView (); 95 WebKit.set_cache_model (CacheModel.DOCUMENT_VIEWER); 96 html_canvas.get_settings ().enable_default_context_menu = false; 97 98 html_box = new ScrolledWindow (null, null); 99 html_box.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC); 100 html_box.add (html_canvas); 101 html_canvas.set_editable (true); 102 103 MainWindow.get_tab_bar ().signal_tab_selected.connect ((f, tab) => { 104 string uri = ""; 105 string html = ""; 106 FontDisplay fd = tab.get_display (); 107 108 scrollbar.set_visible (fd.has_scrollbar ()); 109 110 if (fd.get_name () == "Preview") { 111 uri = Preview.get_uri (); 112 html = Preview.get_html_with_absolute_paths (); 113 114 try { 115 html_canvas.load_html_string (html, uri); 116 } catch (Error e) { 117 warning (e.message); 118 warning ("Failed to load html into canvas."); 119 } 120 121 // show the webview when loading has finished 122 html_box.set_visible (true); 123 glyph_canvas_area.set_visible (false); 124 description.canvas.set_visible (false); 125 126 } else { 127 html_box.set_visible (false); 128 glyph_canvas_area.set_visible (true); 129 description.canvas.set_visible (false); 130 } 131 }); 132 133 // Hide this canvas when window is realized and flip canvas 134 // visibility in tab selection signal. 135 html_canvas.draw.connect ((t, e) => { 136 glyph_canvas_area.set_visible (false); 137 return false; 138 }); 139 140 canvas_box = new Box (Orientation.HORIZONTAL, 0); 141 canvas_box.pack_start (glyph_canvas_area, true, true, 0); 142 canvas_box.pack_start (html_box, true, true, 0); 143 canvas_box.pack_start (description.canvas, true, true, 0); 144 canvas_box.pack_start (scrollbar, false, true, 0); 145 146 submit_text_button = new Gtk.Button (); 147 submit_text_button.set_label ("Submit"); 148 text_input_label = new Label (" " + "Text"); 149 text_entry = new Entry (); 150 text_box = new Box (Orientation.HORIZONTAL, 6); 151 text_box.pack_start (text_input_label, false, false, 0); 152 text_box.pack_start (text_entry, true, true, 0); 153 text_box.pack_start (submit_text_button, false, false, 0); 154 155 text_entry.changed.connect (() => { 156 text_listener.signal_text_input (text_entry.text); 157 }); 158 159 submit_text_button.clicked.connect (() => { 160 text_listener.signal_submit (text_entry.text); 161 text_input_is_active = false; 162 }); 163 164 tab_box = new Box (Orientation.VERTICAL, 0); 165 166 tab_box.pack_start (new TabbarCanvas (MainWindow.get_tab_bar ()), false, false, 0); 167 tab_box.pack_start (text_box, false, false, 5); 168 tab_box.pack_start (canvas_box, true, true, 0); 169 170 toolbox = new ToolboxCanvas (MainWindow.get_toolbox ()); 171 list_box = new Box (Orientation.HORIZONTAL, 0); 172 list_box.pack_start (toolbox, false, false, 0); 173 list_box.pack_start (tab_box, true, true, 0); 174 175 Box vbox = new Box (Orientation.VERTICAL, 0); 176 vbox.pack_start(list_box, true, true, 0); 177 add (vbox); 178 179 try { 180 set_icon_from_file ((!) Icons.find_icon ("window_icon.png").get_path ()); 181 } catch (GLib.Error e) { 182 warning (e.message); 183 } 184 185 key_press_event.connect ((t, event) => { 186 if (!GtkWindow.text_input_is_active) { 187 TabContent.key_press (event.keyval); 188 } 189 190 return false; 191 }); 192 193 key_release_event.connect ((t, event) => { 194 if (!GtkWindow.text_input_is_active) { 195 TabContent.key_release (event.keyval); 196 } 197 198 return false; 199 }); 200 201 show_all (); 202 203 scrollbar.set_visible (false); 204 description.canvas.set_visible (false); 205 206 hide_text_input (); 207 208 MainWindow.open_recent_files_tab (); 209 } 210 211 public void font_loaded () { 212 Font f = BirdFont.get_current_font (); 213 set_title (@"$(f.full_name)"); 214 } 215 216 public void set_overwrite_dialog (OverWriteDialogListener d) { 217 Gtk.Dialog dialog = new Gtk.Dialog.with_buttons (d.message, null, 0); 218 219 dialog.add_button (d.overwrite_message, 0); 220 dialog.add_button (d.cancel_message, 1); 221 dialog.add_button (d.dont_ask_again_message, 2); 222 223 dialog.response.connect ((respons) => { 224 switch (respons) { 225 case 0: 226 d.overwrite (); 227 break; 228 case 1: 229 d.cancel (); 230 break; 231 case 2: 232 d.overwrite_dont_ask_again (); 233 break; 234 } 235 dialog.destroy (); 236 }); 237 238 dialog.show_all (); 239 } 240 241 public void set_scrollbar_size (double size) { 242 scrollbar.adjustment.page_size = size; 243 scrollbar.set_visible (size != 0); 244 } 245 246 public void set_scrollbar_position (double position) { 247 scrollbar_supress_signal = true; 248 scrollbar.adjustment.value = position * (1 - scrollbar.adjustment.page_size); 249 scrollbar_supress_signal = false; 250 } 251 252 public void color_selection (ColorTool color_tool) { 253 new ColorWindow (color_tool); 254 } 255 256 class ColorWindow : Gtk.Window { 257 258 ColorChooserWidget color_selection; 259 260 public ColorWindow (ColorTool color_tool) { 261 Gtk.Button set_button; 262 263 title = t_("Select color"); 264 window_position = Gtk.WindowPosition.CENTER; 265 266 Box box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); 267 add (box); 268 269 color_selection = new Gtk.ColorChooserWidget (); 270 box.add (color_selection); 271 272 color_selection.show_editor = true; 273 274 color_selection.color_activated.connect ((color) => { 275 Gdk.RGBA c = color_selection.rgba; 276 color_tool.color_r = c.red; 277 color_tool.color_g = c.green; 278 color_tool.color_b = c.blue; 279 color_tool.color_a = c.alpha; 280 color_tool.color_updated (); 281 }); 282 283 color_selection.color_activated.connect (() => { 284 Gdk.RGBA c = new Gdk.RGBA (); 285 c.red = color_tool.color_r; 286 c.green = color_tool.color_g; 287 c.blue = color_tool.color_b; 288 c.alpha = color_tool.color_a; 289 color_selection.rgba = c; 290 }); 291 292 set_button = new Gtk.Button.with_label (_("Set")); 293 box.add (set_button); 294 295 set_button.clicked.connect (() => { 296 Gdk.RGBA c = color_selection.rgba; 297 color_tool.color_r = c.red; 298 color_tool.color_g = c.green; 299 color_tool.color_b = c.blue; 300 color_tool.color_a = c.alpha; 301 color_tool.color_updated (); 302 }); 303 304 show_all (); 305 } 306 } 307 308 public void dump_clipboard_content (Clipboard clipboard, SelectionData selection_data) { 309 string d; 310 return_if_fail (!is_null (selection_data)); 311 d = (string) ((!) selection_data); 312 stdout.printf (d); 313 } 314 315 public void dump_clipboard_target (Clipboard clipboard, Atom[] atoms) { 316 foreach (Atom target in atoms) { 317 print ("Target: " + target.name () + "\n"); 318 clipboard.request_contents (target, dump_clipboard_content); 319 } 320 } 321 322 public void dump_clipboard () { 323 clipboard.request_targets (dump_clipboard_target); 324 } 325 326 public string get_clipboard_data () { 327 SelectionData? selection_data; 328 Atom target; 329 string? t; 330 331 target = Atom.intern_static_string ("image/x-inkscape-svg"); 332 selection_data = clipboard.wait_for_contents (target); 333 334 if (!is_null (selection_data)) { 335 return (string) (((!) selection_data).get_data ()); 336 } 337 338 t = clipboard.wait_for_text (); 339 if (t != null) { 340 return (!) t; 341 } 342 343 return ""; 344 } 345 346 public void set_inkscape_clipboard (string inkscape_clipboard_data) { 347 if (BirdFont.mac) { 348 clipboard.set_text (inkscape_clipboard_data, -1); 349 } else { 350 TargetEntry t = { "image/x-inkscape-svg", 0, 0 }; 351 TargetEntry[] targets = { t }; 352 inkscape_clipboard = inkscape_clipboard_data; 353 354 // we can not add data to this closure because the third argument 355 // is owner and not private data. 356 clipboard.set_with_owner (targets, 357 358 // obtain clipboard data 359 (clipboard, selection_data, info, owner) => { 360 Atom type; 361 uchar[] data = (uchar[])(!)((GtkWindow*)owner)->inkscape_clipboard.to_utf8 (); 362 type = Atom.intern_static_string ("image/x-inkscape-svg"); 363 selection_data.set (type, 8, data); 364 }, 365 366 // clear clipboard data 367 (clipboard, user_data) => { 368 }, 369 370 this); 371 } 372 } 373 374 public void set_clipboard_text (string text) { 375 clipboard.set_text (text, -1); 376 } 377 378 public string get_clipboard_text () { 379 string? t; 380 381 t = clipboard.wait_for_text (); 382 if (t != null) { 383 return ((!) t).dup (); 384 } 385 386 return "".dup (); 387 } 388 389 public void set_clipboard (string svg) { 390 TargetEntry t = { "image/svg+xml", 0, 0 }; 391 TargetEntry[] targets = { t }; 392 clipboard_svg = svg; 393 clipboard.set_with_owner (targets, 394 395 // obtain clipboard data 396 (clipboard, selection_data, info, owner) => { 397 Atom type; 398 uchar[] data = (uchar[])(!)((GtkWindow*)owner)->clipboard_svg.to_utf8 (); 399 type = Atom.intern_static_string ("image/svg+xml"); 400 selection_data.set (type, 0, data); 401 }, 402 403 // clear clipboard data 404 (clipboard, user_data) => { 405 }, 406 407 this); 408 } 409 410 public void update_window_size () { 411 int w, h; 412 get_size (out w, out h); 413 414 Preferences.set ("window_width", @"$w"); 415 Preferences.set ("window_height", @"$h"); 416 } 417 418 private void set_size_and_position () { 419 int w = Preferences.get_window_width (); 420 int h = Preferences.get_window_height (); 421 set_default_size (w, h); 422 } 423 424 public void quit () { 425 Gtk.main_quit (); 426 } 427 428 public void file_chooser (string title, FileChooser fc, uint flags) { 429 string? fn = null; 430 431 if (BirdFont.get_arguments () .has_argument ("--windows")) { 432 MenuTab.show_file_dialog_tab (title, fc); 433 } else { 434 if ((flags & FileChooser.LOAD) > 0) { 435 fn = show_file_chooser (title, FileChooserAction.OPEN, Stock.OPEN); 436 } else if ((flags & FileChooser.SAVE) > 0) { 437 fn = show_file_chooser (title, FileChooserAction.SAVE, Stock.SAVE); 438 } else { 439 warning ("Unknown type"); 440 } 441 } 442 443 fc.selected (fn); 444 } 445 446 public string? show_file_chooser (string title, FileChooserAction action, string label) { 447 string? fn = null; 448 FileChooserDialog file_chooser = new FileChooserDialog (title, this, action, Stock.CANCEL, ResponseType.CANCEL, label, ResponseType.ACCEPT); 449 Font font = BirdFont.get_current_font (); 450 int i; 451 string last_folder; 452 453 last_folder = Preferences.get ("last_folder"); 454 455 try { 456 if (last_folder == "") { 457 file_chooser.set_current_folder_file (font.get_folder ()); 458 } else { 459 file_chooser.set_current_folder_file (File.new_for_path (last_folder)); 460 } 461 } catch (GLib.Error e) { 462 stderr.printf (e.message); 463 } 464 465 if (file_chooser.run () == ResponseType.ACCEPT) { 466 GlyphCanvas.redraw (); 467 fn = file_chooser.get_filename (); 468 } 469 470 file_chooser.destroy (); 471 472 if (fn != null) { 473 i = ((!) fn).last_index_of ("/"); 474 if (i > -1) { 475 last_folder = ((!) fn).substring (0, i); 476 Preferences.set ("last_folder", @"$last_folder"); 477 } 478 } 479 480 return fn; 481 } 482 483 public void hide_text_input () { 484 text_listener = new TextListener ("", "", ""); 485 text_box.hide (); 486 text_input_is_active = false; 487 } 488 489 public void set_text_listener (TextListener listener) { 490 text_listener = listener; 491 text_input_label.set_text (" " + listener.label); 492 submit_text_button.set_label (listener.button_label); 493 text_box.show (); 494 text_entry.set_text (listener.default_text); 495 text_entry.activate.connect (() => { 496 text_listener.signal_submit (text_entry.text); 497 text_input_is_active = false; 498 }); 499 text_entry.grab_focus (); 500 text_input_is_active = true; 501 } 502 503 public bool convert_to_png (string from, string to) { 504 Pixbuf pixbuf; 505 string folder; 506 int i; 507 508 try { 509 i = to.last_index_of ("/"); 510 if (i != -1) { 511 folder = to.substring (0, i); 512 DirUtils.create (folder, 0xFFFFFF); 513 } 514 515 pixbuf = new Pixbuf.from_file (from); 516 pixbuf.save (to, "png"); 517 } catch (GLib.Error e) { 518 warning (e.message); 519 return false; 520 } 521 522 return true; 523 } 524 525 public void run_background_thread (Task t) { 526 unowned Thread<void*> bg; 527 528 MenuTab.start_background_thread (); 529 background_task = t; 530 531 try { 532 bg = Thread.create<void*> (this.background_thread, true); 533 } catch (GLib.Error e) { 534 warning (e.message); 535 } 536 } 537 538 public void* background_thread () { 539 background_task.run (); 540 MenuTab.stop_background_thread (); 541 return null; 542 } 543 544 /** Run export in a background thread. */ 545 public void export_font () { 546 unowned Thread<void*> export_thread; 547 548 MenuTab.start_background_thread (); 549 550 try { 551 export_thread = Thread.create<void*> (this.export_thread, true); 552 } catch (GLib.Error e) { 553 warning (e.message); 554 } 555 } 556 557 public void* export_thread () { 558 IdleSource idle = new IdleSource (); 559 560 ExportCallback.export_fonts (); 561 MenuTab.stop_background_thread (); 562 MenuTab.signal_file_exported (); 563 564 idle.set_callback (() => { 565 Notify.Notification export_notification; 566 export_notification = new Notify.Notification ("BirdFont", t_("Your fonts have been exported."), null); 567 export_notification.show (); 568 return false; 569 }); 570 idle.attach (null); 571 572 return null; 573 } 574 575 /** Load font in a background thread. */ 576 public void load () { 577 unowned Thread<void*> thread; 578 579 MenuTab.start_background_thread (); 580 581 try { 582 thread = Thread.create<void*> (this.loading_thread, true); 583 } catch (GLib.Error e) { 584 warning (e.message); 585 } 586 } 587 588 public void* loading_thread () { 589 BirdFont.get_current_font ().load (); 590 MenuTab.stop_background_thread (); 591 MenuTab.signal_file_loaded (); 592 return null; 593 } 594 595 /** Save font in a background thread. */ 596 public void save () { 597 unowned Thread<void*> thread; 598 599 MenuTab.start_background_thread (); 600 601 try { 602 thread = Thread.create<void*> (this.saving_thread, true); 603 } catch (GLib.Error e) { 604 warning (e.message); 605 } 606 } 607 608 public void* saving_thread () { 609 BirdFont.get_current_font ().save (); 610 MenuTab.stop_background_thread (); 611 MenuTab.signal_file_saved (); 612 return null; 613 } 614 615 public void load_background_image () { 616 unowned Thread<void*> thread; 617 618 MenuTab.start_background_thread (); 619 620 try { 621 thread = Thread.create<void*> (this.background_image_thread, true); 622 } catch (GLib.Error e) { 623 warning (e.message); 624 } 625 } 626 627 public void* background_image_thread () { 628 BackgroundTool.load_background_image (); 629 MenuTab.stop_background_thread (); 630 return null; 631 } 632 633 public bool can_export () { 634 return true; 635 } 636 } 637 638 class TabbarCanvas : DrawingArea { 639 TabBar tabbar; 640 641 public TabbarCanvas (TabBar tb) { 642 tabbar = tb; 643 644 // FIXME: DELETE set_extension_events (ExtensionMode.CURSOR | EventMask.POINTER_MOTION_MASK); 645 add_events (EventMask.BUTTON_PRESS_MASK | EventMask.POINTER_MOTION_MASK | EventMask.LEAVE_NOTIFY_MASK); 646 647 motion_notify_event.connect ((t, e)=> { 648 Gtk.Allocation alloc; 649 tabbar.motion (e.x, e.y); 650 get_allocation (out alloc); 651 queue_draw_area (0, 0, alloc.width, alloc.height); 652 return true; 653 }); 654 655 button_press_event.connect ((t, e)=> { 656 Gtk.Allocation alloc; 657 get_allocation (out alloc); 658 tabbar.select_tab_click (e.x, e.y, alloc.width, alloc.height); 659 queue_draw_area (0, 0, alloc.width, alloc.height); 660 return true; 661 }); 662 663 draw.connect ((t, e)=> { 664 Gtk.Allocation alloc; 665 Context cr; 666 StyleContext context; 667 Gdk.RGBA color; 668 669 cr = cairo_create (get_window ()); 670 get_allocation (out alloc); 671 672 context = get_style_context (); 673 context.add_class (STYLE_CLASS_BUTTON); 674 color = context.get_background_color (Gtk.StateFlags.NORMAL); 675 676 if (color.alpha > 0) { 677 tabbar.set_background_color (color.red, color.green, color.blue); 678 } 679 680 tabbar.draw (cr, alloc.width, alloc.height); 681 return true; 682 }); 683 684 tabbar.signal_tab_selected.connect ((t) => { 685 Gtk.Allocation alloc; 686 get_allocation (out alloc); 687 queue_draw_area (0, 0, alloc.width, alloc.height); 688 }); 689 690 tabbar.redraw_tab_bar.connect ((x, y, w, h) => { 691 queue_draw_area (x, y, w, h); 692 }); 693 694 set_size_request (20, 38); 695 } 696 697 } 698 699 class ToolboxCanvas : DrawingArea { 700 Toolbox tb; 701 702 public ToolboxCanvas (Toolbox toolbox) { 703 tb = toolbox; 704 705 realize.connect (() => { 706 Gtk.Allocation allocation; 707 get_allocation (out allocation); 708 Toolbox.allocation_width = allocation.width; 709 Toolbox.allocation_height = allocation.height; 710 Toolbox.redraw_tool_box (); 711 }); 712 713 tb.redraw.connect ((x, y, w, h) => { 714 queue_draw_area (x, y, w, h); 715 }); 716 717 button_press_event.connect ((se, e)=> { 718 if (e.type != EventType.2BUTTON_PRESS) { 719 tb.press (e.button, e.x, e.y); 720 } 721 return true; 722 }); 723 724 button_release_event.connect ((se, e)=> { 725 tb.release (e.button, e.x, e.y); 726 return true; 727 }); 728 729 motion_notify_event.connect ((sen, e)=> { 730 tb.move (e.x, e.y); 731 return true; 732 }); 733 734 draw.connect ((t, e)=> { 735 Gtk.Allocation allocation; 736 get_allocation (out allocation); 737 738 Context cw = cairo_create(get_window()); 739 Toolbox.allocation_width = allocation.width; 740 Toolbox.allocation_height = allocation.height; 741 tb.draw (allocation.width, allocation.height, cw); 742 743 return true; 744 }); 745 746 scroll_event.connect ((t, e)=> { 747 if (e.direction == Gdk.ScrollDirection.UP) { 748 tb.scroll_up (e.x, e.y); 749 } else if (e.direction == Gdk.ScrollDirection.DOWN) { 750 tb.scroll_down (e.x, e.y); 751 } 752 return true; 753 }); 754 755 add_events (EventMask.BUTTON_PRESS_MASK | EventMask.BUTTON_RELEASE_MASK | EventMask.POINTER_MOTION_MASK | EventMask.LEAVE_NOTIFY_MASK | EventMask.SCROLL_MASK); 756 757 set_size_request (170, 100); 758 759 leave_notify_event.connect ((t, e)=> { 760 tb.reset_active_tool (); 761 return true; 762 }); 763 764 } 765 } 766 767 public class GlyphCanvasArea : DrawingArea { 768 GlyphCanvas glyph_canvas; 769 WidgetAllocation alloc = new WidgetAllocation (); 770 771 public GlyphCanvasArea (GlyphCanvas gc) { 772 int event_flags; 773 774 glyph_canvas = gc; 775 776 event_flags = EventMask.BUTTON_PRESS_MASK; 777 event_flags |= EventMask.BUTTON_RELEASE_MASK; 778 event_flags |= EventMask.POINTER_MOTION_MASK; 779 event_flags |= EventMask.LEAVE_NOTIFY_MASK; 780 event_flags |= EventMask.SCROLL_MASK; 781 782 add_events (event_flags); 783 784 glyph_canvas.signal_redraw_area.connect ((x, y, w, h) => { 785 queue_draw_area ((int)x, (int)y, (int)w, (int)h); 786 }); 787 788 draw.connect ((t, e)=> { 789 Gtk.Allocation allocation; 790 get_allocation (out allocation); 791 792 alloc = new WidgetAllocation (); 793 794 alloc.width = allocation.width; 795 alloc.height = allocation.height; 796 alloc.x = allocation.x; 797 alloc.y = allocation.y; 798 799 Context cw = cairo_create (get_window()); 800 801 Surface s = new Surface.similar (cw.get_target (), Cairo.Content.COLOR_ALPHA, alloc.width, alloc.height); 802 Context c = new Context (s); 803 804 TabContent.draw (alloc, c); 805 806 cw.save (); 807 cw.set_source_surface (c.get_target (), 0, 0); 808 cw.paint (); 809 cw.restore (); 810 811 return true; 812 }); 813 814 button_press_event.connect ((t, e)=> { 815 if (e.type == EventType.BUTTON_PRESS) { 816 TabContent.button_press (e.button, e.x, e.y); 817 } else if (e.type == EventType.2BUTTON_PRESS) { 818 TabContent.double_click (e.button, e.x, e.y); 819 } 820 821 return true; 822 }); 823 824 button_release_event.connect ((t, e)=> { 825 TabContent.button_release ((int) e.button, e.x, e.y); 826 return true; 827 }); 828 829 motion_notify_event.connect ((t, e)=> { 830 TabContent.motion_notify (e.x, e.y); 831 return true; 832 }); 833 834 scroll_event.connect ((t, e)=> { 835 if (e.direction == Gdk.ScrollDirection.UP) { 836 TabContent.scroll_wheel_up (e.x, e.y); 837 } else if (e.direction == Gdk.ScrollDirection.DOWN) { 838 TabContent.scroll_wheel_down (e.x, e.y) ; 839 } 840 841 TabContent.button_release (2, e.x, e.y); 842 return true; 843 }); 844 845 can_focus = true; 846 } 847 } 848 849 public class DescriptionForm : GLib.Object { 850 851 public ScrolledWindow canvas; 852 public Box box; 853 854 Entry postscript_name; 855 Entry font_name; 856 Entry style; 857 CheckButton bold; 858 CheckButton italic; 859 Entry weight; 860 Entry full_name; 861 Entry id; 862 Entry version; 863 864 TextView description; 865 TextView copyright; 866 867 public DescriptionForm () { 868 box = new Box (Orientation.VERTICAL, 6); 869 canvas = new ScrolledWindow (null, null); 870 canvas.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); 871 872 postscript_name = new Entry (); 873 add_entry (postscript_name, t_("PostScript Name")); 874 postscript_name.changed.connect (() => { 875 Font f = BirdFont.get_current_font (); 876 f.postscript_name = postscript_name.text; 877 }); 878 879 font_name = new Entry (); 880 add_entry (font_name, t_("Name")); 881 font_name.changed.connect (() => { 882 Font f = BirdFont.get_current_font (); 883 f.name = font_name.text; 884 }); 885 886 style = new Entry (); 887 add_entry (style, t_("Style")); 888 style.changed.connect (() => { 889 Font f = BirdFont.get_current_font (); 890 f.subfamily = style.text; 891 }); 892 893 bold = new CheckButton.with_label (t_("Bold")); 894 bold.toggled.connect (() => { 895 Font f = BirdFont.get_current_font (); 896 f.bold = bold.active;; 897 }); 898 box.pack_start (bold, false, false, 0); 899 900 italic = new CheckButton.with_label (t_("Italic")); 901 italic.toggled.connect (() => { 902 Font f = BirdFont.get_current_font (); 903 f.italic = italic.active;; 904 }); 905 box.pack_start (italic, false, false, 0); 906 907 weight = new Entry (); 908 add_entry (weight, t_("Weight")); 909 weight.changed.connect (() => { 910 Font f = BirdFont.get_current_font (); 911 f.set_weight (weight.text); 912 }); 913 914 full_name = new Entry (); 915 add_entry (full_name, t_("Full name (name and style)")); 916 full_name.changed.connect (() => { 917 Font f = BirdFont.get_current_font (); 918 f.full_name = full_name.text; 919 }); 920 921 id = new Entry (); 922 add_entry (id, t_("Unique identifier")); 923 id.changed.connect (() => { 924 Font f = BirdFont.get_current_font (); 925 f.unique_identifier = id.text; 926 }); 927 928 version = new Entry (); 929 add_entry (version, t_("Version")); 930 version.changed.connect (() => { 931 Font f = BirdFont.get_current_font (); 932 f.version = version.text; 933 }); 934 935 description = new TextView (); 936 add_textview (description, t_("Description")); 937 description.get_buffer ().changed.connect (() => { 938 Font f = BirdFont.get_current_font (); 939 f.description = description.get_buffer ().text; 940 }); 941 description.set_wrap_mode (Gtk.WrapMode.WORD); 942 943 copyright = new TextView (); 944 add_textview (copyright, t_("Copyright")); 945 copyright.get_buffer ().changed.connect (() => { 946 Font f = BirdFont.get_current_font (); 947 f.copyright = copyright.get_buffer ().text; 948 }); 949 copyright.set_wrap_mode (Gtk.WrapMode.WORD); 950 951 update_fields (); 952 953 canvas.add_with_viewport (box); 954 canvas.show_all (); 955 } 956 957 public void update_fields () { 958 Font font = BirdFont.get_current_font (); 959 960 return_if_fail (font.postscript_name.validate ()); 961 return_if_fail (font.name.validate ()); 962 return_if_fail (font.subfamily.validate ()); 963 return_if_fail (font.full_name.validate ()); 964 return_if_fail (font.unique_identifier.validate ()); 965 return_if_fail (font.version.validate ()); 966 return_if_fail (font.description.validate ()); 967 return_if_fail (font.copyright.validate ()); 968 969 postscript_name.set_text (font.postscript_name); 970 font_name.set_text (font.name); 971 style.set_text (font.subfamily); 972 bold.active = font.bold; 973 italic.active = font.italic; 974 weight.set_text (font.get_weight ()); 975 full_name.set_text (font.full_name); 976 id.set_text (font.unique_identifier); 977 version.set_text (font.version); 978 979 description.get_buffer ().set_text (font.description.dup ()); 980 copyright.get_buffer ().set_text (font.copyright.dup ()); 981 982 } 983 984 void add_entry (Entry e, string label) { 985 Box vb; 986 Box hb; 987 Label l; 988 Box margin; 989 990 margin = new Box (Orientation.HORIZONTAL, 6); 991 l = new Label (label); 992 vb = new Box (Orientation.VERTICAL, 2); 993 hb = new Box (Orientation.HORIZONTAL, 2); 994 hb.pack_start (l, false, false, 0); 995 vb.pack_start (hb, true, true, 5); 996 vb.pack_start (e, true, true, 0); 997 margin.pack_start (vb, true, true, 5); 998 box.pack_start (margin, false, false, 5); 999 } 1000 1001 void add_textview (TextView t, string label) { 1002 Box vb; 1003 Box hb; 1004 Label l; 1005 Box margin; 1006 1007 margin = new Box (Orientation.HORIZONTAL, 6); 1008 l = new Label (label); 1009 vb = new Box (Orientation.VERTICAL, 2); 1010 hb = new Box (Orientation.HORIZONTAL, 2); 1011 hb.pack_start (l, false, false, 0); 1012 vb.pack_start (hb, true, true, 5); 1013 vb.pack_start (t, true, true, 0); 1014 margin.pack_start (vb, true, true, 5); 1015 box.pack_start (margin, false, false, 5); 1016 } 1017 } 1018 1019 } 1020