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