The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

DrawingTools.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/DrawingTools.vala.
Disable slow stroke on Android
1 /* 2 Copyright (C) 2012 2013 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 15 using Cairo; 16 using Math; 17 18 namespace BirdFont { 19 20 public class DrawingTools : ToolCollection { 21 GlyphCanvas glyph_canvas; 22 23 public Gee.ArrayList<Expander> expanders = new Gee.ArrayList<Expander> (); 24 25 Expander draw_tools; 26 public static Expander grid_expander; 27 Expander shape_tools; 28 public static Expander draw_tool_modifiers; 29 public static Expander stroke_expander; 30 public static Expander zoombar_tool; 31 public static Expander view_tools; 32 public static Expander guideline_tools; 33 34 public static PointType point_type = PointType.DOUBLE_CURVE; 35 36 public static Tool add_stroke; 37 public static SpinButton object_stroke; 38 Tool outline; 39 40 public static MoveTool move_tool; 41 public static PenTool pen_tool; 42 43 public static BezierTool bezier_tool; 44 PointTool point_tool; 45 public static ZoomTool zoom_tool; 46 public static ResizeTool resize_tool; 47 public static TrackTool track_tool; 48 public static BackgroundTool move_background; 49 public static Tool move_canvas; 50 51 static Tool quadratic_points; 52 static Tool cubic_points; 53 static Tool double_points; 54 static Tool convert_points; 55 56 public static CutBackgroundTool cut_background; 57 Tool show_bg; 58 Tool bg_selection; 59 SpinButton background_threshold; 60 public static SpinButton background_scale; 61 Tool high_contrast_background; 62 SpinButton auto_trace_resolution; 63 Tool auto_trace; 64 SpinButton auto_trace_simplify; 65 Tool delete_background; 66 67 Tool rectangle; 68 Tool circle; 69 70 Tool help_lines; 71 Tool xheight_help_lines; 72 Tool background_help_lines; 73 74 SpinButton x_coordinate; 75 SpinButton y_coordinate; 76 SpinButton rotation; 77 SpinButton width; 78 SpinButton height; 79 SpinButton skew; 80 81 Tool tie_handles; 82 Tool reflect_handle; 83 Tool create_line; 84 Tool close_path_tool; 85 86 Tool delete_button; 87 public Tool insert_point_on_path_tool; 88 Tool undo_tool; 89 Tool select_all_button; 90 91 OrientationTool reverse_path_tool; 92 Tool move_layer; 93 Tool flip_vertical; 94 Tool flip_horizontal; 95 96 public ZoomBar zoom_bar; 97 98 Tool line_cap_butt; 99 Tool line_cap_round; 100 Tool line_cap_square; 101 102 public DrawingTools (GlyphCanvas main_glyph_canvas) { 103 bool selected_line; 104 105 glyph_canvas = main_glyph_canvas; 106 107 background_scale = new SpinButton (); 108 109 draw_tools = new Expander (t_("Drawing Tools")); 110 draw_tool_modifiers = new Expander (t_("Control Point")); 111 stroke_expander = new Expander (t_("Stroke")); 112 shape_tools = new Expander (t_("Geometrical Shapes")); 113 zoombar_tool = new Expander (t_("Zoom")); 114 view_tools = new Expander (); 115 guideline_tools = new Expander (t_("Guidelines & Grid")); 116 117 Expander font_name = new Expander (); 118 Expander key_tools = new Expander (); // tools on android 119 Expander test_tools = new Expander (); 120 Expander grid = new Expander (t_("Grid Size")); 121 122 grid_expander = grid; 123 124 // font name 125 font_name.add_tool (new FontName ()); 126 127 // Draw tools 128 bezier_tool = new BezierTool ("bezier_tool"); 129 bezier_tool.select_action.connect ((self) => { 130 update_drawing_and_background_tools (self); 131 }); 132 draw_tools.add_tool (bezier_tool); 133 134 pen_tool = new PenTool ("pen_tool"); 135 pen_tool.select_action.connect ((self) => { 136 update_drawing_and_background_tools (self); 137 }); 138 draw_tools.add_tool (pen_tool); 139 140 point_tool = new PointTool ("point_tool"); 141 point_tool.select_action.connect ((self) => { 142 update_drawing_and_background_tools (self); 143 }); 144 draw_tools.add_tool (point_tool); 145 146 zoom_tool = new ZoomTool ("zoom_tool"); 147 zoom_tool.select_action.connect ((self) => { 148 update_drawing_and_background_tools (self); 149 }); 150 #if ANDROID == false 151 draw_tools.add_tool (zoom_tool); 152 #endif 153 move_tool = new MoveTool ("move"); 154 move_tool.select_action.connect ((self) => { 155 update_drawing_and_background_tools (self); 156 }); 157 draw_tools.add_tool (move_tool); 158 159 resize_tool = new ResizeTool ("resize"); 160 resize_tool.select_action.connect ((self) => { 161 update_drawing_and_background_tools (self); 162 }); 163 draw_tools.add_tool (resize_tool); 164 165 track_tool = new TrackTool ("track"); // draw outline on freehand 166 track_tool.select_action.connect ((self) => { 167 update_drawing_and_background_tools (self); 168 }); 169 draw_tools.add_tool (track_tool); 170 171 move_background = new BackgroundTool ("move_background"); 172 move_background.select_action.connect ((self) => { 173 update_drawing_and_background_tools (self); 174 }); 175 draw_tools.add_tool (move_background); 176 177 move_canvas = new Tool ("move_canvas", t_("Move canvas")); 178 move_canvas.select_action.connect ((self) => { 179 update_drawing_and_background_tools (self); 180 }); 181 draw_tools.add_tool (move_canvas); 182 183 // Tools on android 184 // Delete key 185 delete_button = new Tool ("delete_button", t_("Delete")); 186 delete_button.select_action.connect ((self) => { 187 TabContent.key_press (Key.DEL); 188 }); 189 key_tools.add_tool (delete_button); 190 191 // Select all points or paths 192 select_all_button = new Tool ("select_all", t_("Select all points or paths")); 193 select_all_button.select_action.connect ((self) => { 194 Glyph g = MainWindow.get_current_glyph (); 195 196 if (point_tool.is_selected () 197 || pen_tool.is_selected () 198 || track_tool.is_selected ()) { 199 pen_tool.select_all_points (); 200 g.open_path (); 201 } else { 202 DrawingTools.move_tool.select_all_paths (); 203 } 204 }); 205 key_tools.add_tool (select_all_button); 206 207 // Undo 208 undo_tool = new Tool ("undo_tool", t_("Undo")); 209 undo_tool.select_action.connect ((self) => { 210 TabContent.undo (); 211 }); 212 key_tools.add_tool (undo_tool); 213 214 bool insert_points = false; 215 insert_point_on_path_tool = new Tool ("new_point_on_path", t_("Insert new points on path")); 216 insert_point_on_path_tool.select_action.connect ((self) => { 217 insert_points = !insert_points; 218 insert_point_on_path_tool.set_selected (insert_points); 219 }); 220 insert_point_on_path_tool.set_persistent (true); 221 key_tools.add_tool (insert_point_on_path_tool); 222 223 // quadratic Bézier points 224 quadratic_points = new Tool ("quadratic_points", t_("Create quadratic Bézier curves")); 225 quadratic_points.select_action.connect ((self) => { 226 point_type = PointType.QUADRATIC; 227 Preferences.set ("point_type", "quadratic_points"); 228 update_type_selection (); 229 }); 230 draw_tool_modifiers.add_tool (quadratic_points); 231 232 // cubic Bézier points 233 cubic_points = new Tool ("cubic_points", t_("Create cubic Bézier curves")); 234 cubic_points.select_action.connect ((self) => { 235 point_type = PointType.CUBIC; 236 Preferences.set ("point_type", "cubic_points"); 237 update_type_selection (); 238 }); 239 draw_tool_modifiers.add_tool (cubic_points); 240 241 // two quadratic points off curve points for each quadratic control point 242 double_points = new Tool ("double_points", t_("Quadratic path with two line handles")); 243 double_points.select_action.connect ((self) => { 244 point_type = PointType.DOUBLE_CURVE; 245 Preferences.set ("point_type", "double_points"); 246 update_type_selection (); 247 }); 248 draw_tool_modifiers.add_tool (double_points); 249 250 // convert point 251 convert_points = new Tool ("convert_point", t_("Convert selected points")); 252 convert_points.select_action.connect ((self) => { 253 PenTool.convert_point_types (); 254 GlyphCanvas.redraw (); 255 update_type_selection (); 256 PenTool.reset_stroke (); 257 }); 258 convert_points.set_persistent (false); 259 draw_tool_modifiers.add_tool (convert_points); 260 261 // x coordinate 262 x_coordinate = new SpinButton ("x_coordinate", t_("X coordinate")); 263 x_coordinate.set_big_number (true); 264 x_coordinate.set_int_value ("0.000"); 265 x_coordinate.set_int_step (0.1); 266 x_coordinate.set_min (-999.99); 267 x_coordinate.set_max (999.99); 268 x_coordinate.show_icon (true); 269 x_coordinate.set_persistent (false); 270 x_coordinate.new_value_action.connect((self) => { 271 Glyph glyph = MainWindow.get_current_glyph (); 272 double x, y, w, h; 273 double delta; 274 275 glyph.selection_boundaries (out x, out y, out w, out h); 276 delta = x_coordinate.get_value () - x + glyph.left_limit; 277 278 foreach (Path path in glyph.active_paths) { 279 path.move (delta, 0); 280 } 281 282 GlyphCanvas.redraw (); 283 }); 284 draw_tool_modifiers.add_tool (x_coordinate); 285 286 move_tool.objects_moved.connect (() => { 287 Glyph glyph = MainWindow.get_current_glyph (); 288 x_coordinate.set_value_round (MoveTool.selection_box_center_x 289 - (MoveTool.selection_box_width / 2) 290 - glyph.left_limit, true, false); 291 }); 292 293 move_tool.selection_changed.connect (() => { 294 Glyph glyph = MainWindow.get_current_glyph (); 295 x_coordinate.set_value_round (MoveTool.selection_box_center_x 296 - (MoveTool.selection_box_width / 2) 297 - glyph.left_limit, true, false); 298 }); 299 300 move_tool.objects_deselected.connect (() => { 301 x_coordinate.set_value_round (0, true, false); 302 x_coordinate.hide_value (); 303 }); 304 305 // y coordinate 306 y_coordinate = new SpinButton ("y_coordinate", t_("Y coordinate")); 307 y_coordinate.set_big_number (true); 308 y_coordinate.set_int_value ("0.000"); 309 y_coordinate.set_int_step (0.1); 310 y_coordinate.set_min (-999.99); 311 y_coordinate.set_max (999.99); 312 y_coordinate.show_icon (true); 313 y_coordinate.set_persistent (false); 314 y_coordinate.new_value_action.connect((self) => { 315 double x, y, w, h; 316 Glyph glyph = MainWindow.get_current_glyph (); 317 Font font = BirdFont.get_current_font (); 318 319 glyph.selection_boundaries (out x, out y, out w, out h); 320 321 foreach (Path path in glyph.active_paths) { 322 path.move (0, y_coordinate.get_value () - (y - h) - font.base_line); 323 } 324 325 GlyphCanvas.redraw (); 326 }); 327 draw_tool_modifiers.add_tool (y_coordinate); 328 329 move_tool.objects_moved.connect (() => { 330 Font font = BirdFont.get_current_font (); 331 y_coordinate.set_value_round (MoveTool.selection_box_center_y 332 - (MoveTool.selection_box_height / 2) 333 + font.base_line, true, false); 334 }); 335 336 move_tool.selection_changed.connect (() => { 337 Font font = BirdFont.get_current_font (); 338 y_coordinate.set_value_round (MoveTool.selection_box_center_y 339 - (MoveTool.selection_box_height / 2) 340 + font.base_line, true, false); 341 }); 342 343 move_tool.objects_deselected.connect (() => { 344 y_coordinate.set_value_round (0, true, false); 345 y_coordinate.hide_value (); 346 }); 347 348 // rotation 349 rotation = new SpinButton ("rotation", t_("Rotation")); 350 rotation.set_big_number (true); 351 rotation.set_int_value ("0.000"); 352 rotation.set_int_step (0.1); 353 rotation.set_min (-360); 354 rotation.set_max (360); 355 rotation.show_icon (true); 356 rotation.set_persistent (false); 357 rotation.new_value_action.connect ((self) => { 358 double x, y, w, h; 359 Glyph glyph = MainWindow.get_current_glyph (); 360 double angle = (self.get_value () / 360) * 2 * PI; 361 Path last_path; 362 glyph.selection_boundaries (out x, out y, out w, out h); 363 364 x += w / 2; 365 y -= h / 2; 366 367 if (glyph.active_paths.size > 0) { 368 last_path = glyph.active_paths.get (glyph.active_paths.size - 1); 369 resize_tool.rotate_selected_paths (angle - last_path.rotation, x, y); 370 } 371 372 GlyphCanvas.redraw (); 373 }); 374 375 resize_tool.objects_rotated.connect ((angle) => { 376 rotation.set_value_round (angle, true, false); 377 PenTool.reset_stroke (); 378 }); 379 380 move_tool.objects_deselected.connect (() => { 381 rotation.set_value_round (0, true, false); 382 rotation.hide_value (); 383 }); 384 385 draw_tool_modifiers.add_tool (rotation); 386 387 // skew 388 skew = new SpinButton ("skew", t_("Skew")); 389 skew.set_big_number (true); 390 skew.set_int_value ("0.000"); 391 skew.set_int_step (1); 392 skew.set_min (-100); 393 skew.set_max (100); 394 skew.show_icon (true); 395 skew.set_persistent (false); 396 skew.new_value_action.connect ((self) => { 397 resize_tool.skew (-skew.get_value ()); 398 PenTool.reset_stroke (); 399 GlyphCanvas.redraw (); 400 }); 401 402 move_tool.objects_moved.connect (() => { 403 Glyph glyph = MainWindow.get_current_glyph (); 404 double d; 405 406 if (glyph.active_paths.size > 0) { 407 d = glyph.active_paths.get (0).skew; 408 resize_tool.last_skew = d; 409 skew.set_value_round (-d, true, false); 410 } 411 }); 412 413 move_tool.objects_deselected.connect (() => { 414 skew.set_value_round (0, true, false); 415 skew.hide_value (); 416 }); 417 418 draw_tool_modifiers.add_tool (skew); 419 420 // width 421 width = new SpinButton ("width", t_("Width")); 422 width.set_big_number (true); 423 width.set_int_value ("0.0000"); 424 width.set_int_step (0.01); 425 width.show_icon (true); 426 width.set_persistent (false); 427 width.new_value_action.connect ((self) => { 428 double x, y, w, h; 429 Glyph glyph; 430 double new_size; 431 432 glyph = MainWindow.get_current_glyph (); 433 glyph.selection_boundaries (out x, out y, out w, out h); 434 435 new_size = self.get_value () / w; 436 437 if (self.get_value () > 0 && new_size != 1) { 438 resize_tool.resize_selected_paths (new_size); 439 } 440 441 GlyphCanvas.redraw (); 442 }); 443 draw_tool_modifiers.add_tool (width); 444 445 // height 446 height = new SpinButton ("height", t_("Height")); 447 height.set_big_number (true); 448 height.set_int_value ("0.0000"); 449 height.set_int_step (0.01); 450 height.show_icon (true); 451 height.set_persistent (false); 452 height.new_value_action.connect ((self) => { 453 double x, y, w, h; 454 Glyph glyph; 455 double new_size; 456 457 glyph = MainWindow.get_current_glyph (); 458 glyph.selection_boundaries (out x, out y, out w, out h); 459 460 new_size = self.get_value () / h; 461 462 if (self.get_value () > 0 && new_size != 1) { 463 resize_tool.resize_selected_paths (new_size); 464 } 465 466 GlyphCanvas.redraw (); 467 }); 468 draw_tool_modifiers.add_tool (height); 469 470 resize_tool.objects_resized.connect ((w, h) => { 471 height.set_value_round (h, true, false); 472 width.set_value_round (w, true, false); 473 }); 474 475 move_tool.objects_deselected.connect (() => { 476 width.set_value_round (0, true, false); 477 width.hide_value (); 478 479 height.set_value_round (0, true, false); 480 height.hide_value (); 481 }); 482 483 move_tool.objects_moved.connect (() => { 484 width.set_value_round (MoveTool.selection_box_width, true, false); 485 height.set_value_round (MoveTool.selection_box_height, true, false); 486 }); 487 488 // tie edit point handles 489 tie_handles = new Tool ("tie_point", t_("Tie curve handles for the selected edit point")); 490 tie_handles.select_action.connect ((self) => { 491 bool tie, end_point; 492 EditPoint p; 493 494 if (PenTool.move_selected_handle) { 495 p = PenTool.active_handle.parent; 496 tie = !p.tie_handles; 497 498 // don't tie end points 499 foreach (Path path in MainWindow.get_current_glyph ().active_paths) { 500 if (path.is_open ()) { 501 if (p == path.get_first_point () || p == path.get_last_point ()) { 502 tie = false; 503 } 504 } 505 } 506 507 if (tie) { 508 p.process_tied_handle (); 509 p.set_reflective_handles (false); 510 } 511 512 p.set_tie_handle (tie); 513 514 PenTool.handle_selection.path.update_region_boundaries (); 515 } else { 516 foreach (PointSelection ep in PenTool.selected_points) { 517 tie = !ep.point.tie_handles; 518 519 end_point = ep.point == ep.path.get_first_point () 520 || ep.point == ep.path.get_last_point (); 521 522 if (!ep.path.is_open () || !end_point) { 523 if (tie) { 524 ep.point.process_tied_handle (); 525 ep.point.set_reflective_handles (false); 526 } 527 528 ep.point.set_tie_handle (tie); 529 ep.path.update_region_boundaries (); 530 } 531 } 532 } 533 534 MainWindow.get_current_glyph ().update_view (); 535 PenTool.reset_stroke (); 536 }); 537 draw_tool_modifiers.add_tool (tie_handles); 538 539 // symmetrical handles 540 reflect_handle = new Tool ("symmetric", t_("Symmetrical handles")); 541 reflect_handle.select_action.connect ((self) => { 542 bool symmetrical, end_point; 543 PointSelection ep; 544 if (PenTool.selected_points.size > 0) { 545 ep = PenTool.selected_points.get (0); 546 symmetrical = ep.point.reflective_point; 547 548 foreach (PointSelection p in PenTool.selected_points) { 549 end_point = p.point == p.path.get_first_point () 550 || p.point == p.path.get_last_point (); 551 552 if (!p.path.is_open () || !end_point) { 553 p.point.set_reflective_handles (!symmetrical); 554 p.point.process_symmetrical_handles (); 555 556 if (symmetrical) { 557 ep.point.set_tie_handle (false); 558 } 559 560 p.path.update_region_boundaries (); 561 } 562 } 563 MainWindow.get_current_glyph ().update_view (); 564 } 565 566 PenTool.reset_stroke (); 567 }); 568 draw_tool_modifiers.add_tool (reflect_handle); 569 570 create_line = new Tool ("create_line", t_("Convert segment to line.")); 571 create_line.select_action.connect ((self) => { 572 PenTool.convert_segment_to_line (); 573 MainWindow.get_current_glyph ().update_view (); 574 PenTool.reset_stroke (); 575 }); 576 draw_tool_modifiers.add_tool (create_line); 577 578 reverse_path_tool = new OrientationTool ("reverse_path", t_("Create counter from outline")); 579 draw_tool_modifiers.add_tool (reverse_path_tool); 580 581 // close path 582 close_path_tool = new Tool ("close_path", t_("Close path")); 583 close_path_tool.select_action.connect ((self) => { 584 Tool current; 585 Glyph g; 586 587 current = MainWindow.get_toolbox ().get_current_tool (); 588 589 if (current is BezierTool) { 590 ((BezierTool) current).stop_drawing (); 591 } 592 593 PenTool.reset_stroke (); 594 595 g = MainWindow.get_current_glyph (); 596 g.close_path (); 597 g.clear_active_paths (); 598 599 self.set_selected (false); 600 GlyphCanvas.redraw (); 601 }); 602 draw_tool_modifiers.add_tool (close_path_tool); 603 604 move_layer = new Tool ("move_layer", t_("Move to path to the bottom layer")); 605 move_layer.select_action.connect ((self) => { 606 Glyph g = MainWindow.get_current_glyph (); 607 608 foreach (Path p in g.active_paths) { 609 g.path_list.remove (p); 610 g.path_list.insert (0, p); 611 } 612 }); 613 draw_tool_modifiers.add_tool (move_layer); 614 615 flip_vertical = new Tool ("flip_vertical", t_("Flip path vertically")); 616 flip_vertical.select_action.connect ((self) => { 617 MoveTool.flip_vertical (); 618 MainWindow.get_current_glyph ().update_view (); 619 PenTool.reset_stroke (); 620 }); 621 draw_tool_modifiers.add_tool (flip_vertical); 622 623 flip_horizontal = new Tool ("flip_horizontal", t_("Flip path horizontally")); 624 flip_horizontal.select_action.connect ((self) => { 625 MoveTool.flip_horizontal (); 626 MainWindow.get_current_glyph ().update_view (); 627 PenTool.reset_stroke (); 628 }); 629 draw_tool_modifiers.add_tool (flip_horizontal); 630 631 // background tools 632 background_scale = new SpinButton ("scale_background", t_("Set size for background image")); 633 background_scale.show_icon (true); 634 background_scale.set_int_value ("1.000"); 635 636 background_scale.new_value_action.connect((self) => { 637 background_scale.select_action (self); 638 }); 639 640 background_scale.select_action.connect((self) => { 641 SpinButton sb = (SpinButton) self; 642 Glyph g = MainWindow.get_current_glyph (); 643 BackgroundImage? img = g.get_background_image (); 644 double s = sb.get_value (); 645 BackgroundImage i; 646 double xc, yc; 647 648 if (img != null) { 649 i = (!) img; 650 xc = i.img_middle_x; 651 yc = i.img_middle_y; 652 653 i.set_img_scale (s, s); 654 655 i.img_middle_x = xc; 656 i.img_middle_y = yc; 657 } 658 659 GlyphCanvas.redraw (); 660 }); 661 662 draw_tool_modifiers.add_tool (background_scale); 663 664 cut_background = new CutBackgroundTool ("cut_background"); 665 cut_background.select_action.connect ((self) => { 666 update_drawing_and_background_tools (self); 667 }); 668 draw_tool_modifiers.add_tool (cut_background); 669 670 show_bg = new Tool ("show_background", t_("Show/hide background image")); 671 show_bg.select_action.connect ((self) => { 672 update_drawing_and_background_tools (self); 673 }); 674 show_bg.select_action.connect ((self) => { 675 Glyph g = MainWindow.get_current_glyph (); 676 g.set_background_visible (!g.get_background_visible ()); 677 GlyphCanvas.redraw (); 678 }); 679 draw_tool_modifiers.add_tool (show_bg); 680 681 bg_selection = new Tool ("insert_background", t_("Insert a new background image")); 682 bg_selection.select_action.connect ((self) => { 683 update_drawing_and_background_tools (self); 684 }); 685 686 bg_selection.select_action.connect((self) => { 687 if (MainWindow.get_current_display () is Glyph) { 688 BackgroundTool.import_background_image (); 689 } 690 }); 691 692 bg_selection.set_show_background (true); 693 draw_tool_modifiers.add_tool (bg_selection); 694 695 high_contrast_background = new Tool ("high_contrast_background", t_("High contrast")); 696 high_contrast_background.select_action.connect ((self) => { 697 Glyph g = MainWindow.get_current_glyph (); 698 BackgroundImage? bg = g.get_background_image (); 699 BackgroundImage b; 700 701 if (bg != null) { 702 b = (!) bg; 703 b.set_high_contrast (!b.high_contrast); 704 b.update_background (); 705 } 706 }); 707 draw_tool_modifiers.add_tool (high_contrast_background); 708 709 background_threshold = new SpinButton ("contrast_threshold", t_("Set background threshold")); 710 background_threshold.show_icon (true); 711 background_threshold.set_value_round (1); 712 713 background_threshold.new_value_action.connect ((self) => { 714 Glyph g = MainWindow.get_current_glyph (); 715 BackgroundImage? bg = g.get_background_image (); 716 BackgroundImage b; 717 718 if (bg != null) { 719 b = (!) bg; 720 b.set_threshold (background_threshold.get_value ()); 721 b.update_background (); 722 } 723 }); 724 725 draw_tool_modifiers.add_tool (background_threshold); 726 727 auto_trace_resolution = new SpinButton ("auto_trace_resolution", t_("Amount of autotrace details")); 728 auto_trace_resolution.set_value_round (1); 729 auto_trace_resolution.show_icon (true); 730 731 auto_trace_resolution.new_value_action.connect ((self) => { 732 Glyph g = MainWindow.get_current_glyph (); 733 BackgroundImage? bg = g.get_background_image (); 734 BackgroundImage b; 735 736 if (bg != null) { 737 b = (!) bg; 738 b.set_trace_resolution (auto_trace_resolution.get_value ()); 739 b.update_background (); 740 } 741 }); 742 743 draw_tool_modifiers.add_tool (auto_trace_resolution); 744 745 auto_trace_simplify = new SpinButton ("auto_trace_simplify", t_("Autotrace simplification")); 746 auto_trace_simplify.set_value_round (0.5); 747 auto_trace_simplify.show_icon (true); 748 749 auto_trace_simplify.new_value_action.connect ((self) => { 750 Glyph g = MainWindow.get_current_glyph (); 751 BackgroundImage? bg = g.get_background_image (); 752 BackgroundImage b; 753 754 if (bg != null) { 755 b = (!) bg; 756 b.set_trace_simplification (auto_trace_simplify.get_value ()); 757 } 758 }); 759 760 draw_tool_modifiers.add_tool (auto_trace_simplify); 761 762 auto_trace = new Tool ("autotrace", t_("Autotrace background image")); 763 auto_trace.select_action.connect ((self) => { 764 Task t = new Task (); 765 t.task.connect (auto_trace_background); 766 MainWindow.native_window.run_background_thread (t); 767 }); 768 769 draw_tool_modifiers.add_tool (auto_trace); 770 771 delete_background = new Tool ("delete_background", t_("Delete background image")); 772 delete_background.select_action.connect ((self) => { 773 MainWindow.get_current_glyph ().delete_background (); 774 }); 775 776 draw_tool_modifiers.add_tool (delete_background); 777 778 // add stroke to path 779 add_stroke = new Tool ("apply_stroke", t_("Apply stroke")); 780 add_stroke.select_action.connect ((self) => { 781 Font f; 782 Glyph g = MainWindow.get_current_glyph (); 783 StrokeTool.add_stroke = !StrokeTool.add_stroke; 784 StrokeTool.stroke_width = object_stroke.get_value (); 785 786 add_stroke.selected = StrokeTool.add_stroke; 787 788 GlyphCanvas.redraw (); 789 g.store_undo_state (); 790 791 if (StrokeTool.add_stroke) { 792 foreach (Path p in g.active_paths) { 793 p.stroke = StrokeTool.stroke_width; 794 p.line_cap = StrokeTool.line_cap; 795 } 796 } else { 797 foreach (Path p in g.active_paths) { 798 p.stroke = 0; 799 } 800 } 801 802 f = BirdFont.get_current_font (); 803 f.settings.set_setting ("apply_stroke", @"$(StrokeTool.add_stroke)"); 804 805 add_stroke.selected = StrokeTool.add_stroke; 806 }); 807 stroke_expander.add_tool (add_stroke); 808 add_stroke.selected = StrokeTool.add_stroke; 809 810 // edit stroke width 811 object_stroke = new SpinButton ("object_stroke", t_("Stroke width")); 812 object_stroke.set_big_number (true); 813 object_stroke.set_value_round (2); 814 object_stroke.set_max (0.01); 815 object_stroke.set_max (50); 816 817 object_stroke.new_value_action.connect((self) => { 818 Font f; 819 Glyph g = MainWindow.get_current_glyph (); 820 821 bool tool = resize_tool.is_selected () 822 || move_tool.is_selected () 823 || pen_tool.is_selected () 824 || track_tool.is_selected () 825 || point_tool.is_selected () 826 || bezier_tool.is_selected (); 827 828 StrokeTool.stroke_width = object_stroke.get_value (); 829 830 if (tool && StrokeTool.add_stroke) { 831 foreach (Path p in g.active_paths) { 832 p.stroke = StrokeTool.stroke_width; 833 p.reset_stroke (); 834 } 835 } 836 837 f = BirdFont.get_current_font (); 838 f.settings.set_setting ("stroke_width", object_stroke.get_display_value ()); 839 840 GlyphCanvas.redraw (); 841 }); 842 stroke_expander.add_tool (object_stroke); 843 844 move_tool.selection_changed.connect (() => { 845 update_stroke_settings (); 846 }); 847 848 move_tool.objects_moved.connect (() => { 849 update_stroke_settings (); 850 }); 851 852 // create outline from path 853 outline = new Tool ("stroke_to_outline", t_("Create outline form stroke")); 854 outline.select_action.connect ((self) => { 855 StrokeTool.stroke_selected_paths (); 856 outline.set_selected (false); 857 }); 858 stroke_expander.add_tool (outline); 859 860 // set line cap 861 line_cap_butt = new Tool ("line_cap_butt", t_("Butt line cap")); 862 line_cap_butt.select_action.connect ((self) => { 863 Glyph g; 864 865 g = MainWindow.get_current_glyph (); 866 g.store_undo_state (); 867 868 foreach (Path p in g.active_paths) { 869 p.line_cap = LineCap.BUTT; 870 p.reset_stroke (); 871 } 872 873 StrokeTool.line_cap = LineCap.BUTT; 874 Font f = BirdFont.get_current_font (); 875 f.settings.set_setting ("line_cap", @"butt"); 876 877 line_cap_butt.selected = true; 878 line_cap_round.selected = false; 879 line_cap_square.selected = false; 880 881 GlyphCanvas.redraw (); 882 }); 883 stroke_expander.add_tool (line_cap_butt); 884 885 line_cap_round = new Tool ("line_cap_round", t_("Round line cap")); 886 line_cap_round.select_action.connect ((self) => { 887 Glyph g; 888 889 g = MainWindow.get_current_glyph (); 890 g.store_undo_state (); 891 892 foreach (Path p in g.active_paths) { 893 p.line_cap = LineCap.ROUND; 894 p.reset_stroke (); 895 } 896 897 StrokeTool.line_cap = LineCap.ROUND; 898 899 Font f = BirdFont.get_current_font (); 900 f.settings.set_setting ("line_cap", @"round"); 901 902 line_cap_butt.selected = false; 903 line_cap_round.selected = true; 904 line_cap_square.selected = false; 905 906 GlyphCanvas.redraw (); 907 }); 908 stroke_expander.add_tool (line_cap_round); 909 910 line_cap_square = new Tool ("line_cap_square", t_("Square line cap")); 911 line_cap_square.select_action.connect ((self) => { 912 Glyph g; 913 914 g = MainWindow.get_current_glyph (); 915 g.store_undo_state (); 916 917 foreach (Path p in g.active_paths) { 918 p.line_cap = LineCap.SQUARE; 919 p.reset_stroke (); 920 } 921 922 StrokeTool.line_cap = LineCap.SQUARE; 923 924 Font f = BirdFont.get_current_font (); 925 f.settings.set_setting ("line_cap", @"square"); 926 927 line_cap_butt.selected = false; 928 line_cap_round.selected = false; 929 line_cap_square.selected = true; 930 931 GlyphCanvas.redraw (); 932 }); 933 stroke_expander.add_tool (line_cap_square); 934 935 // tests 936 if (BirdFont.has_argument ("--test")) { 937 Tool test_case = new Tool ("test_case"); 938 test_case.select_action.connect((self) => { 939 if (self.is_selected ()) { 940 if (TestBirdFont.is_running ()) { 941 TestBirdFont.pause (); 942 } else { 943 TestBirdFont.continue (); 944 } 945 } 946 }); 947 test_tools.add_tool (test_case); 948 949 Tool slow_test = new Tool ("slow_test"); 950 slow_test.select_action.connect((self) => { 951 bool s = TestBirdFont.is_slow_test (); 952 TestBirdFont.set_slow_test (!s); 953 s = TestBirdFont.is_slow_test (); 954 self.set_selected (s); 955 }); 956 957 test_tools.add_tool (slow_test); 958 959 // Run from commad line 960 string? st = BirdFont.get_argument ("--test"); 961 if (st != null && ((!)st).char_count () > 0) { 962 IdleSource idle = new IdleSource (); 963 964 idle.set_callback (() => { 965 MainWindow.get_toolbox ().select_tool (test_case); 966 return false; 967 }); 968 969 idle.attach (null); 970 } 971 972 if (BirdFont.has_argument ("--slow")) { 973 MainWindow.get_toolbox ().select_tool (slow_test); 974 } 975 976 } 977 978 // guide lines, grid and other guidlines 979 help_lines = new Tool ("help_lines", t_("Show guidelines")); 980 help_lines.select_action.connect ((self) => { 981 bool h; 982 h = GlyphCanvas.get_current_glyph ().get_show_help_lines (); 983 GlyphCanvas.get_current_glyph ().set_show_help_lines (!h); 984 self.set_selected (!h); 985 GlyphCanvas.get_current_glyph ().redraw_help_lines (); 986 }); 987 selected_line = GlyphCanvas.get_current_glyph ().get_show_help_lines (); 988 help_lines.set_selected (selected_line); 989 guideline_tools.add_tool (help_lines); 990 991 xheight_help_lines = new Tool ("show_xheight_helplines", t_("Show more guidelines")); 992 xheight_help_lines.select_action.connect ((self) => { 993 Glyph g = MainWindow.get_current_glyph (); 994 bool v = !g.get_xheight_lines_visible (); 995 g.set_xheight_lines_visible (v); 996 self.set_selected (v); 997 GlyphCanvas.redraw (); 998 999 if (v && !help_lines.is_selected ()) { 1000 MainWindow.get_toolbox ().select_tool (help_lines); 1001 } 1002 }); 1003 selected_line = GlyphCanvas.get_current_glyph ().get_xheight_lines_visible (); 1004 xheight_help_lines.set_selected (selected_line); 1005 guideline_tools.add_tool (xheight_help_lines); 1006 1007 background_help_lines = new Tool ("background_help_lines", t_("Show guidelines at top and bottom margin")); 1008 background_help_lines.select_action.connect ((self) => { 1009 Glyph g = MainWindow.get_current_glyph (); 1010 bool v = !g.get_margin_lines_visible (); 1011 g.set_margin_lines_visible (v); 1012 self.set_selected (v); 1013 GlyphCanvas.redraw (); 1014 1015 if (v && !help_lines.is_selected ()) { 1016 MainWindow.get_toolbox ().select_tool (help_lines); 1017 } 1018 }); 1019 selected_line = GlyphCanvas.get_current_glyph ().get_margin_lines_visible (); 1020 background_help_lines.set_selected (selected_line); 1021 guideline_tools.add_tool (background_help_lines); 1022 1023 Tool new_grid = new GridTool ("show_grid"); 1024 guideline_tools.add_tool (new_grid); 1025 1026 // Zoom tools 1027 zoom_bar = new ZoomBar (); 1028 zoom_bar.new_zoom.connect ((z) => { 1029 Glyph g = MainWindow.get_current_glyph (); 1030 double zoom = 20 * z + 1; 1031 double xc, yc, nxc, nyc; 1032 1033 xc = Glyph.path_coordinate_x (Glyph.xc ()); 1034 yc = Glyph.path_coordinate_y (Glyph.yc ()); 1035 1036 g.set_zoom (zoom); 1037 1038 nxc = Glyph.path_coordinate_x (Glyph.xc ()); 1039 nyc = Glyph.path_coordinate_y (Glyph.yc ()); 1040 1041 g.view_offset_x -= nxc - xc; 1042 g.view_offset_y += nyc - yc; 1043 1044 GlyphCanvas.redraw (); 1045 }); 1046 zoombar_tool.add_tool (zoom_bar); 1047 1048 Tool reset_zoom = new Tool ("zoom_1_1", t_("Zoom Out More")); 1049 reset_zoom.select_action.connect ((self) => { 1050 zoom_tool.store_current_view (); 1051 glyph_canvas.get_current_display ().reset_zoom (); 1052 glyph_canvas.redraw_area(0, 0, GlyphCanvas.allocation.width, GlyphCanvas.allocation.height); 1053 }); 1054 view_tools.add_tool (reset_zoom); 1055 reset_zoom.set_tool_visibility (false); 1056 1057 Tool full_glyph = new Tool ("full_glyph", t_("Show full glyph")); 1058 full_glyph.select_action.connect((self) => { 1059 zoom_tool.store_current_view (); 1060 zoom_tool.zoom_full_glyph (); 1061 }); 1062 view_tools.add_tool (full_glyph); 1063 1064 Tool zoom_boundaries = new Tool ("zoom_boundaries", t_("Fit in view")); 1065 zoom_boundaries.select_action.connect((self) => { 1066 zoom_tool.store_current_view (); 1067 glyph_canvas.get_current_display ().zoom_max (); 1068 }); 1069 view_tools.add_tool (zoom_boundaries); 1070 1071 Tool zoom_bg = new Tool ("zoom_background_image", t_("Zoom in on background image")); 1072 zoom_bg.select_action.connect((self) => { 1073 if (MainWindow.get_current_glyph ().get_background_image () != null) { 1074 zoom_tool.store_current_view (); 1075 ZoomTool.zoom_full_background_image (); 1076 glyph_canvas.redraw_area(0, 0, GlyphCanvas.allocation.width, GlyphCanvas.allocation.height); 1077 } 1078 }); 1079 view_tools.add_tool (zoom_bg); 1080 1081 Tool zoom_prev = new Tool ("prev", t_("Previous view")); 1082 zoom_prev.select_action.connect((self) => { 1083 zoom_tool.previous_view (); 1084 }); 1085 view_tools.add_tool (zoom_prev); 1086 1087 Tool zoom_next = new Tool ("next", t_("Next view")); 1088 zoom_next.select_action.connect((self) => { 1089 zoom_tool.next_view (); 1090 }); 1091 view_tools.add_tool (zoom_next); 1092 zoom_next.set_tool_visibility (false); 1093 1094 // shape tools 1095 circle = new CircleTool ("circle"); 1096 circle.select_action.connect ((self) => { 1097 update_drawing_and_background_tools (self); 1098 }); 1099 shape_tools.add_tool (circle); 1100 1101 rectangle = new RectangleTool ("rectangle"); 1102 rectangle.select_action.connect ((self) => { 1103 update_drawing_and_background_tools (self); 1104 }); 1105 shape_tools.add_tool (rectangle); 1106 1107 add_expander (font_name); 1108 add_expander (draw_tools); 1109 1110 if (BirdFont.android) { 1111 add_expander (key_tools); 1112 } 1113 1114 add_expander (draw_tool_modifiers); 1115 1116 add_expander (stroke_expander); 1117 1118 add_expander (guideline_tools); 1119 add_expander (grid); 1120 add_expander (zoombar_tool); 1121 add_expander (view_tools); 1122 add_expander (shape_tools); 1123 1124 // Fixa: add_expander (trace); 1125 if (BirdFont.has_argument ("--test")) { 1126 add_expander (test_tools); 1127 } 1128 1129 draw_tools.set_persistent (true); 1130 draw_tools.set_unique (false); 1131 1132 stroke_expander.set_persistent (true); 1133 stroke_expander.set_unique (false); 1134 1135 key_tools.set_persistent (false); 1136 key_tools.set_unique (false); 1137 1138 draw_tool_modifiers.set_persistent (true); 1139 draw_tool_modifiers.set_unique (false); 1140 1141 test_tools.set_persistent (true); 1142 1143 guideline_tools.set_persistent (true); 1144 guideline_tools.set_unique (false); 1145 1146 grid.set_persistent (true); 1147 grid.set_unique (true); 1148 1149 shape_tools.set_persistent (true); 1150 shape_tools.set_unique (true); 1151 1152 // let these tools progagate events even when other tools are selected 1153 foreach (Tool t in draw_tools.tool) { 1154 t.editor_events = true; 1155 } 1156 1157 foreach (Tool t in shape_tools.tool) { 1158 t.editor_events = true; 1159 t.persistent = true; 1160 } 1161 1162 move_background.editor_events = true; 1163 cut_background.editor_events = true; 1164 move_canvas.editor_events = true; 1165 1166 move_background.persistent = true; 1167 cut_background.persistent = true; 1168 move_canvas.persistent = true; 1169 1170 // Default selection 1171 IdleSource idle = new IdleSource (); 1172 idle.set_callback (() => { 1173 Toolbox tb = MainWindow.get_toolbox (); 1174 1175 tb.reset_active_tool (); 1176 update_drawing_and_background_tools (bezier_tool); 1177 tb.select_tool (bezier_tool); 1178 tb.set_current_tool (bezier_tool); 1179 1180 set_point_type_from_preferences (); 1181 1182 if (GlyphCanvas.get_current_glyph ().get_show_help_lines ()) { 1183 help_lines.set_selected (true); 1184 help_lines.set_active (false); 1185 } 1186 1187 add_new_grid (1); 1188 add_new_grid (2); 1189 add_new_grid (4); 1190 1191 MainWindow.get_toolbox ().move (0, 0); 1192 1193 return false; 1194 }); 1195 idle.attach (null); 1196 1197 // update selelction when the user switches tab 1198 MainWindow.get_tab_bar ().signal_tab_selected.connect((tab) => { 1199 Glyph glyph; 1200 1201 if (tab.get_display () is Glyph) { 1202 glyph = (Glyph) tab.get_display (); 1203 show_bg.set_selected (glyph.get_background_visible ()); 1204 update_line_selection (glyph); 1205 } 1206 }); 1207 } 1208 1209 public static void update_stroke_settings () { 1210 bool stroke = false; 1211 Glyph g = MainWindow.get_current_glyph (); 1212 1213 foreach (Path p in g.active_paths) { 1214 if (p.stroke > 0) { 1215 stroke = true; 1216 } 1217 } 1218 1219 add_stroke.selected = stroke; 1220 StrokeTool.add_stroke = stroke; 1221 // FIXME: This is slow: Toolbox.redraw_tool_box (); 1222 } 1223 1224 void auto_trace_background () { 1225 Glyph g = MainWindow.get_current_glyph (); 1226 BackgroundImage? bg = g.get_background_image (); 1227 BackgroundImage b; 1228 PathList pl; 1229 1230 if (bg != null) { 1231 b = (!) bg; 1232 pl = b.autotrace (); 1233 foreach (Path p in pl.paths) { 1234 g.add_path (p); 1235 } 1236 } 1237 } 1238 1239 void update_line_selection (Glyph glyph) { 1240 help_lines.set_selected (glyph.get_show_help_lines ()); 1241 xheight_help_lines.set_selected (glyph.get_xheight_lines_visible ()); 1242 background_help_lines.set_selected (glyph.get_margin_lines_visible ()); 1243 } 1244 1245 public static void set_point_type_from_preferences () { 1246 string type = Preferences.get ("point_type"); 1247 if (type == "double_points") { 1248 Toolbox.select_tool_by_name ("double_points"); 1249 } else if (type == "quadratic_points") { 1250 Toolbox.select_tool_by_name ("quadratic_points"); 1251 } if (type == "cubic_points") { 1252 Toolbox.select_tool_by_name ("cubic_points"); 1253 } 1254 } 1255 1256 void hide_all_modifiers () { 1257 x_coordinate.set_tool_visibility (false); 1258 y_coordinate.set_tool_visibility (false); 1259 rotation.set_tool_visibility (false); 1260 width.set_tool_visibility (false); 1261 height.set_tool_visibility (false); 1262 skew.set_tool_visibility (false); 1263 reverse_path_tool.set_tool_visibility (false); 1264 move_layer.set_tool_visibility (false); 1265 flip_vertical.set_tool_visibility (false); 1266 flip_horizontal.set_tool_visibility (false); 1267 1268 tie_handles.set_tool_visibility (false); 1269 reflect_handle.set_tool_visibility (false); 1270 create_line.set_tool_visibility (false); 1271 close_path_tool.set_tool_visibility (false); 1272 1273 quadratic_points.set_tool_visibility (false); 1274 cubic_points.set_tool_visibility (false); 1275 double_points.set_tool_visibility (false); 1276 convert_points.set_tool_visibility (false); 1277 1278 cut_background.set_tool_visibility (false); 1279 show_bg.set_tool_visibility (false); 1280 bg_selection.set_tool_visibility (false); 1281 background_threshold.set_tool_visibility (false); 1282 background_scale.set_tool_visibility (false); 1283 high_contrast_background.set_tool_visibility (false); 1284 auto_trace_resolution.set_tool_visibility (false); 1285 auto_trace.set_tool_visibility (false); 1286 auto_trace_simplify.set_tool_visibility (false); 1287 delete_background.set_tool_visibility (false); 1288 } 1289 1290 void show_background_tool_modifiers () { 1291 draw_tool_modifiers.set_headline (t_("Background Tools")); 1292 1293 cut_background.set_tool_visibility (true); 1294 show_bg.set_tool_visibility (true); 1295 bg_selection.set_tool_visibility (true); 1296 background_threshold.set_tool_visibility (true); 1297 background_scale.set_tool_visibility (true); 1298 high_contrast_background.set_tool_visibility (true); 1299 auto_trace_resolution.set_tool_visibility (true); 1300 auto_trace.set_tool_visibility (true); 1301 auto_trace_simplify.set_tool_visibility (true); 1302 delete_background.set_tool_visibility (true); 1303 } 1304 1305 void show_point_tool_modifiers () { 1306 draw_tool_modifiers.set_headline (t_("Control Points")); 1307 1308 tie_handles.set_tool_visibility (true); 1309 reflect_handle.set_tool_visibility (true); 1310 create_line.set_tool_visibility (true); 1311 close_path_tool.set_tool_visibility (true); 1312 1313 quadratic_points.set_tool_visibility (true); 1314 cubic_points.set_tool_visibility (true); 1315 double_points.set_tool_visibility (true); 1316 convert_points.set_tool_visibility (true); 1317 1318 reverse_path_tool.set_tool_visibility (true); 1319 } 1320 1321 void show_object_tool_modifiers () { 1322 draw_tool_modifiers.set_headline (t_("Object Tools")); 1323 1324 x_coordinate.set_tool_visibility (true); 1325 y_coordinate.set_tool_visibility (true); 1326 rotation.set_tool_visibility (true); 1327 width.set_tool_visibility (true); 1328 height.set_tool_visibility (true); 1329 skew.set_tool_visibility (true); 1330 1331 reverse_path_tool.set_tool_visibility (true); 1332 move_layer.set_tool_visibility (true); 1333 flip_vertical.set_tool_visibility (true); 1334 flip_horizontal.set_tool_visibility (true); 1335 } 1336 1337 public void update_drawing_and_background_tools (Tool current_tool) { 1338 IdleSource idle = new IdleSource (); 1339 1340 idle.set_callback (() => { 1341 Glyph g = MainWindow.get_current_glyph (); 1342 1343 hide_all_modifiers (); 1344 1345 move_background.set_selected (false); 1346 cut_background.set_selected (false); 1347 1348 bezier_tool.set_selected (false); 1349 pen_tool.set_selected (false); 1350 point_tool.set_selected (false); 1351 zoom_tool.set_selected (false); 1352 move_tool.set_selected (false); 1353 resize_tool.set_selected (false); 1354 track_tool.set_selected (false); 1355 move_canvas.set_selected (false); 1356 delete_background.set_selected (false); 1357 1358 show_bg.set_selected (g.get_background_visible ()); 1359 show_bg.set_active (false); 1360 bg_selection.set_selected (false); 1361 background_scale.set_active (false); 1362 1363 rectangle.set_selected (false); 1364 circle.set_selected (false); 1365 1366 reverse_path_tool.set_selected (false); 1367 move_layer.set_selected (false); 1368 flip_vertical.set_selected (false); 1369 flip_horizontal.set_selected (false); 1370 1371 current_tool.set_selected (true); 1372 1373 if (resize_tool.is_selected () || move_tool.is_selected ()) { 1374 show_object_tool_modifiers (); 1375 } else if (bezier_tool.is_selected () 1376 || pen_tool.is_selected () 1377 || point_tool.is_selected () 1378 || track_tool.is_selected ()) { 1379 show_point_tool_modifiers (); 1380 } else if (move_background.is_selected () 1381 || cut_background.is_selected () 1382 || show_bg.is_selected () 1383 || high_contrast_background.is_selected () 1384 || auto_trace.is_selected ()) { 1385 show_background_tool_modifiers (); 1386 } 1387 1388 MainWindow.get_toolbox ().update_expanders (); 1389 Toolbox.redraw_tool_box (); 1390 1391 return false; 1392 }); 1393 1394 idle.attach (null); 1395 } 1396 1397 void update_type_selection () { 1398 IdleSource idle = new IdleSource (); 1399 1400 // Do this in idle, after the animation 1401 idle.set_callback (() => { 1402 Font f = BirdFont.get_current_font (); 1403 1404 quadratic_points.set_selected (false); 1405 cubic_points.set_selected (false); 1406 double_points.set_selected (false); 1407 1408 switch (point_type) { 1409 case PointType.QUADRATIC: 1410 quadratic_points.set_selected (true); 1411 f.settings.set_setting ("point_type", "quadratic"); 1412 break; 1413 case PointType.CUBIC: 1414 cubic_points.set_selected (true); 1415 f.settings.set_setting ("point_type", "cubic"); 1416 break; 1417 case PointType.DOUBLE_CURVE: 1418 double_points.set_selected (true); 1419 f.settings.set_setting ("point_type", "double_curve"); 1420 break; 1421 } 1422 1423 convert_points.set_selected (false); 1424 1425 Toolbox.redraw_tool_box (); 1426 return false; 1427 }); 1428 1429 idle.attach (null); 1430 } 1431 1432 public static void set_default_point_type (string type) { 1433 if (type == "quadratic") { 1434 quadratic_points.set_selected (true); 1435 point_type = PointType.QUADRATIC; 1436 } else if (type == "cubic") { 1437 cubic_points.set_selected (true); 1438 point_type = PointType.CUBIC; 1439 } else if (type == "double_curve") { 1440 double_points.set_selected (true); 1441 point_type = PointType.DOUBLE_CURVE; 1442 } 1443 } 1444 1445 public override Gee.ArrayList<Expander> get_expanders () { 1446 return expanders; 1447 } 1448 1449 /** Insert new points of this type. */ 1450 public static PointType get_selected_point_type () { 1451 return point_type; 1452 } 1453 1454 public void remove_all_grid_buttons () { 1455 grid_expander.tool.clear (); 1456 1457 GridTool.sizes.clear (); 1458 1459 MainWindow.get_toolbox ().update_expanders (); 1460 MainWindow.get_toolbox ().redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1461 } 1462 1463 public void parse_grid (string spin_button_value) { 1464 SpinButton sb = add_new_grid (); 1465 sb.set_value (spin_button_value); 1466 MainWindow.get_toolbox ().select_tool (sb); 1467 } 1468 1469 public static SpinButton add_new_grid (double size = 2) { 1470 SpinButton grid_width = new SpinButton ("grid_width", t_("Set size for grid")); 1471 Toolbox tb = MainWindow.get_toolbox (); 1472 1473 grid_width.new_value_action.connect((self) => { 1474 grid_width.select_action (grid_width); 1475 }); 1476 1477 grid_width.select_action.connect((self) => { 1478 SpinButton sb = (SpinButton) self; 1479 GridTool.set_grid_width (sb.get_value ()); 1480 GlyphCanvas.redraw (); 1481 }); 1482 1483 grid_expander.add_tool (grid_width); 1484 1485 GridTool.sizes.add (grid_width); 1486 1487 grid_width.set_value_round (size); 1488 1489 tb.update_expanders (); 1490 1491 tb.redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1492 1493 tb.select_tool (grid_width); 1494 grid_width.set_active (false); 1495 1496 return grid_width; 1497 } 1498 1499 public void remove_current_grid () { 1500 Tool grid_width; 1501 Toolbox tb = MainWindow.get_toolbox (); 1502 1503 foreach (Tool t in grid_expander.tool) { 1504 if (t.is_selected () && t is SpinButton) { 1505 GridTool.sizes.remove ((SpinButton)t); 1506 grid_expander.tool.remove (t); 1507 break; 1508 } 1509 } 1510 1511 if (grid_expander.tool.size > 0) { 1512 grid_width = grid_expander.tool.get (grid_expander.tool.size - 1); 1513 tb.select_tool (grid_width); 1514 grid_width.set_active (false); 1515 } 1516 1517 MainWindow.get_toolbox ().update_expanders (); 1518 tb.redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1519 } 1520 1521 private void add_expander (Expander e) { 1522 expanders.add (e); 1523 } 1524 1525 public override Gee.ArrayList<string> get_displays () { 1526 Gee.ArrayList<string> d = new Gee.ArrayList<string> (); 1527 d.add ("Glyph"); 1528 return d; 1529 } 1530 } 1531 1532 } 1533