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