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.
Fix background tools selection
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 public static SpinButton background_threshold; 68 public static SpinButton background_scale; 69 Tool high_contrast_background; 70 public static SpinButton auto_trace_resolution; 71 Tool auto_trace; 72 public static 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 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 Tool full_height_tool; 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 // width 401 width = new SpinButton ("width", t_("Width")); 402 width.set_big_number (true); 403 width.set_int_value ("0.0000"); 404 width.set_int_step (0.01); 405 width.show_icon (true); 406 width.set_persistent (false); 407 width.new_value_action.connect ((self) => { 408 double x, y, w, h; 409 Glyph glyph; 410 double new_size; 411 412 glyph = MainWindow.get_current_glyph (); 413 glyph.selection_boundaries (out x, out y, out w, out h); 414 415 new_size = self.get_value () / w; 416 417 if (self.get_value () > 0 && new_size != 1) { 418 resize_tool.resize_selected_paths (new_size); 419 } 420 421 GlyphCanvas.redraw (); 422 }); 423 draw_tool_modifiers.add_tool (width); 424 425 // height 426 height = new SpinButton ("height", t_("Height")); 427 height.set_big_number (true); 428 height.set_int_value ("0.0000"); 429 height.set_int_step (0.01); 430 height.show_icon (true); 431 height.set_persistent (false); 432 height.new_value_action.connect ((self) => { 433 double x, y, w, h; 434 Glyph glyph; 435 double new_size; 436 437 glyph = MainWindow.get_current_glyph (); 438 glyph.selection_boundaries (out x, out y, out w, out h); 439 440 new_size = self.get_value () / h; 441 442 if (self.get_value () > 0 && new_size != 1) { 443 resize_tool.resize_selected_paths (new_size); 444 } 445 446 GlyphCanvas.redraw (); 447 }); 448 draw_tool_modifiers.add_tool (height); 449 450 resize_tool.objects_resized.connect ((w, h) => { 451 height.set_value_round (h, true, false); 452 width.set_value_round (w, true, false); 453 }); 454 455 move_tool.objects_deselected.connect (() => { 456 width.set_value_round (0, true, false); 457 width.hide_value (); 458 459 height.set_value_round (0, true, false); 460 height.hide_value (); 461 }); 462 463 move_tool.objects_moved.connect (() => { 464 width.set_value_round (MoveTool.selection_box_width, true, false); 465 height.set_value_round (MoveTool.selection_box_height, true, false); 466 }); 467 468 // tie edit point handles 469 tie_handles = new Tool ("tie_point", t_("Tie curve handles for the selected edit point")); 470 tie_handles.select_action.connect ((self) => { 471 bool tie, end_point; 472 EditPoint p; 473 474 if (PenTool.move_selected_handle) { 475 p = PenTool.active_handle.parent; 476 tie = !p.tie_handles; 477 478 // don't tie end points 479 foreach (Path path in MainWindow.get_current_glyph ().active_paths) { 480 if (path.is_open ()) { 481 if (p == path.get_first_point () || p == path.get_last_point ()) { 482 tie = false; 483 } 484 } 485 } 486 487 if (tie) { 488 p.process_tied_handle (); 489 p.set_reflective_handles (false); 490 } 491 492 p.set_tie_handle (tie); 493 494 PenTool.handle_selection.path.update_region_boundaries (); 495 } else { 496 foreach (PointSelection ep in PenTool.selected_points) { 497 tie = !ep.point.tie_handles; 498 499 end_point = ep.point == ep.path.get_first_point () 500 || ep.point == ep.path.get_last_point (); 501 502 if (!ep.path.is_open () || !end_point) { 503 if (tie) { 504 ep.point.process_tied_handle (); 505 ep.point.set_reflective_handles (false); 506 } 507 508 ep.point.set_tie_handle (tie); 509 ep.path.update_region_boundaries (); 510 } 511 } 512 } 513 514 MainWindow.get_current_glyph ().update_view (); 515 PenTool.reset_stroke (); 516 }); 517 draw_tool_modifiers.add_tool (tie_handles); 518 519 // symmetrical handles 520 reflect_handle = new Tool ("symmetric", t_("Symmetrical handles")); 521 reflect_handle.select_action.connect ((self) => { 522 bool symmetrical, end_point; 523 PointSelection ep; 524 if (PenTool.selected_points.size > 0) { 525 ep = PenTool.selected_points.get (0); 526 symmetrical = ep.point.reflective_point; 527 528 foreach (PointSelection p in PenTool.selected_points) { 529 end_point = p.point == p.path.get_first_point () 530 || p.point == p.path.get_last_point (); 531 532 if (!p.path.is_open () || !end_point) { 533 p.point.set_reflective_handles (!symmetrical); 534 p.point.process_symmetrical_handles (); 535 536 if (symmetrical) { 537 ep.point.set_tie_handle (false); 538 } 539 540 p.path.update_region_boundaries (); 541 } 542 } 543 MainWindow.get_current_glyph ().update_view (); 544 } 545 546 PenTool.reset_stroke (); 547 }); 548 draw_tool_modifiers.add_tool (reflect_handle); 549 550 create_line = new Tool ("create_line", t_("Convert segment to line.")); 551 create_line.select_action.connect ((self) => { 552 PenTool.convert_segment_to_line (); 553 MainWindow.get_current_glyph ().update_view (); 554 PenTool.reset_stroke (); 555 }); 556 draw_tool_modifiers.add_tool (create_line); 557 558 reverse_path_tool = new OrientationTool ("reverse_path", t_("Create counter from outline")); 559 draw_tool_modifiers.add_tool (reverse_path_tool); 560 561 full_height_tool = new Tool ("full_height", t_("Scale object to font top/baseline")); 562 full_height_tool.select_action.connect ((self) => { 563 resize_tool.full_height (); 564 GlyphCanvas.redraw (); 565 }); 566 567 draw_tool_modifiers.add_tool (full_height_tool); 568 569 // close path 570 close_path_tool = new Tool ("close_path", t_("Close path")); 571 close_path_tool.select_action.connect ((self) => { 572 Tool current; 573 Glyph g; 574 575 current = MainWindow.get_toolbox ().get_current_tool (); 576 577 if (current is BezierTool) { 578 ((BezierTool) current).stop_drawing (); 579 } 580 581 PenTool.reset_stroke (); 582 583 g = MainWindow.get_current_glyph (); 584 g.close_path (); 585 g.clear_active_paths (); 586 587 self.set_selected (false); 588 GlyphCanvas.redraw (); 589 }); 590 draw_tool_modifiers.add_tool (close_path_tool); 591 592 move_layer = new Tool ("move_layer", t_("Move to path to the bottom of the layer")); 593 move_layer.select_action.connect ((self) => { 594 Glyph g = MainWindow.get_current_glyph (); 595 Layer layer = g.get_current_layer (); 596 597 foreach (Path p in g.active_paths) { 598 layer.paths.remove (p); 599 layer.paths.paths.insert (0, p); 600 } 601 602 GlyphCanvas.redraw (); 603 }); 604 draw_tool_modifiers.add_tool (move_layer); 605 606 flip_vertical = new Tool ("flip_vertical", t_("Flip path vertically")); 607 flip_vertical.select_action.connect ((self) => { 608 MoveTool.flip_vertical (); 609 MainWindow.get_current_glyph ().update_view (); 610 PenTool.reset_stroke (); 611 }); 612 draw_tool_modifiers.add_tool (flip_vertical); 613 614 flip_horizontal = new Tool ("flip_horizontal", t_("Flip path horizontally")); 615 flip_horizontal.select_action.connect ((self) => { 616 MoveTool.flip_horizontal (); 617 MainWindow.get_current_glyph ().update_view (); 618 PenTool.reset_stroke (); 619 }); 620 draw_tool_modifiers.add_tool (flip_horizontal); 621 622 // background tools 623 background_scale = new SpinButton ("scale_background", t_("Set size for background image")); 624 background_scale.show_icon (true); 625 background_scale.set_int_value ("1.000"); 626 627 background_scale.new_value_action.connect((self) => { 628 background_scale.select_action (self); 629 }); 630 631 background_scale.select_action.connect((self) => { 632 SpinButton sb = (SpinButton) self; 633 Glyph g = MainWindow.get_current_glyph (); 634 BackgroundImage? img = g.get_background_image (); 635 double s = sb.get_value (); 636 BackgroundImage i; 637 double xc, yc; 638 639 if (img != null) { 640 i = (!) img; 641 xc = i.img_middle_x; 642 yc = i.img_middle_y; 643 644 i.set_img_scale (s, s); 645 646 i.img_middle_x = xc; 647 i.img_middle_y = yc; 648 } 649 650 GlyphCanvas.redraw (); 651 }); 652 653 draw_tool_modifiers.add_tool (background_scale); 654 655 cut_background = new CutBackgroundTool ("cut_background"); 656 cut_background.select_action.connect ((self) => { 657 update_drawing_and_background_tools (self); 658 }); 659 draw_tool_modifiers.add_tool (cut_background); 660 661 show_bg = new Tool ("show_background", t_("Show/hide background image")); 662 show_bg.select_action.connect ((self) => { 663 update_drawing_and_background_tools (self); 664 }); 665 show_bg.select_action.connect ((self) => { 666 Glyph g = MainWindow.get_current_glyph (); 667 g.set_background_visible (!g.get_background_visible ()); 668 GlyphCanvas.redraw (); 669 }); 670 draw_tool_modifiers.add_tool (show_bg); 671 672 bg_selection = new Tool ("insert_background", t_("Insert a new background image")); 673 bg_selection.select_action.connect ((self) => { 674 update_drawing_and_background_tools (self); 675 }); 676 677 bg_selection.select_action.connect((self) => { 678 if (MainWindow.get_current_display () is Glyph) { 679 BackgroundTool.import_background_image (); 680 } 681 }); 682 683 bg_selection.set_show_background (true); 684 draw_tool_modifiers.add_tool (bg_selection); 685 686 high_contrast_background = new Tool ("high_contrast_background", t_("High contrast")); 687 high_contrast_background.select_action.connect ((self) => { 688 Glyph g = MainWindow.get_current_glyph (); 689 BackgroundImage? bg = g.get_background_image (); 690 BackgroundImage b; 691 692 if (bg != null) { 693 b = (!) bg; 694 b.set_high_contrast (!b.high_contrast); 695 b.update_background (); 696 } 697 }); 698 draw_tool_modifiers.add_tool (high_contrast_background); 699 700 background_threshold = new SpinButton ("contrast_threshold", t_("Set background threshold")); 701 background_threshold.show_icon (true); 702 background_threshold.set_value_round (1); 703 704 background_threshold.new_value_action.connect ((self) => { 705 Glyph g = MainWindow.get_current_glyph (); 706 BackgroundImage? bg = g.get_background_image (); 707 BackgroundImage b; 708 709 if (bg != null) { 710 b = (!) bg; 711 b.update_background (); 712 } 713 714 BirdFont.get_current_font ().settings.set_setting ("autotrace_threshold", background_threshold.get_display_value ()); 715 }); 716 717 draw_tool_modifiers.add_tool (background_threshold); 718 719 auto_trace_resolution = new SpinButton ("auto_trace_resolution", t_("Amount of autotrace details")); 720 auto_trace_resolution.set_value_round (1); 721 auto_trace_resolution.show_icon (true); 722 723 auto_trace_resolution.new_value_action.connect ((self) => { 724 Glyph g = MainWindow.get_current_glyph (); 725 BackgroundImage? bg = g.get_background_image (); 726 BackgroundImage b; 727 728 if (bg != null) { 729 b = (!) bg; 730 b.update_background (); 731 } 732 733 BirdFont.get_current_font ().settings.set_setting ("autotrace_resolution", auto_trace_resolution.get_display_value ()); 734 }); 735 736 draw_tool_modifiers.add_tool (auto_trace_resolution); 737 738 auto_trace_simplify = new SpinButton ("auto_trace_simplify", t_("Autotrace simplification")); 739 auto_trace_simplify.set_value_round (0.5); 740 auto_trace_simplify.show_icon (true); 741 742 auto_trace_simplify.new_value_action.connect ((self) => { 743 BirdFont.get_current_font ().settings.set_setting ("autotrace_simplification", background_threshold.get_display_value ()); 744 }); 745 746 draw_tool_modifiers.add_tool (auto_trace_simplify); 747 748 auto_trace = new Tool ("autotrace", t_("Autotrace background image")); 749 auto_trace.select_action.connect ((self) => { 750 Task t = new Task (auto_trace_background); 751 MainWindow.run_blocking_task (t); 752 }); 753 754 draw_tool_modifiers.add_tool (auto_trace); 755 756 delete_background = new Tool ("delete_background", t_("Delete background image")); 757 delete_background.select_action.connect ((self) => { 758 MainWindow.get_current_glyph ().delete_background (); 759 }); 760 761 draw_tool_modifiers.add_tool (delete_background); 762 763 add_layer = new Tool ("add_layer", t_("Add layer")); 764 add_layer.select_action.connect ((self) => { 765 layer_tools.visible = true; 766 MainWindow.get_current_glyph ().add_new_layer (); 767 update_layers (); 768 show_layers.selected = true; 769 add_layer.selected = false; 770 }); 771 layer_settings.add_tool (add_layer); 772 773 show_layers = new Tool ("show_layers", t_("Show layers")); 774 show_layers.select_action.connect ((self) => { 775 layer_tools.visible = !layer_tools.visible; 776 MainWindow.get_toolbox ().update_expanders (); 777 Toolbox.redraw_tool_box (); 778 show_layers.selected = layer_tools.visible; 779 }); 780 layer_settings.add_tool (show_layers); 781 782 // add stroke to path 783 add_stroke = new Tool ("apply_stroke", t_("Apply stroke")); 784 785 add_stroke.select_action.connect ((self) => { 786 Font f; 787 Glyph g = MainWindow.get_current_glyph (); 788 StrokeTool.add_stroke = !StrokeTool.add_stroke; 789 StrokeTool.stroke_width = object_stroke.get_value (); 790 791 add_stroke.selected = StrokeTool.add_stroke; 792 set_stroke_tool_visibility (); 793 GlyphCanvas.redraw (); 794 g.store_undo_state (); 795 796 if (StrokeTool.add_stroke) { 797 foreach (Path p in g.active_paths) { 798 p.stroke = StrokeTool.stroke_width; 799 p.line_cap = StrokeTool.line_cap; 800 } 801 } else { 802 foreach (Path p in g.active_paths) { 803 p.stroke = 0; 804 } 805 } 806 807 f = BirdFont.get_current_font (); 808 f.settings.set_setting ("apply_stroke", @"$(StrokeTool.add_stroke)"); 809 810 stroke_expander.redraw (); 811 MainWindow.get_toolbox ().update_expanders (); 812 }); 813 stroke_expander.add_tool (add_stroke); 814 add_stroke.selected = StrokeTool.add_stroke; 815 816 // edit stroke width 817 object_stroke = new SpinButton ("object_stroke", t_("Stroke width")); 818 object_stroke.set_big_number (true); 819 object_stroke.set_value_round (2); 820 object_stroke.set_max (0.01); 821 object_stroke.set_max (50); 822 823 object_stroke.new_value_action.connect((self) => { 824 Font f; 825 Glyph g = MainWindow.get_current_glyph (); 826 827 bool tool = resize_tool.is_selected () 828 || move_tool.is_selected () 829 || pen_tool.is_selected () 830 || track_tool.is_selected () 831 || point_tool.is_selected () 832 || bezier_tool.is_selected (); 833 834 StrokeTool.stroke_width = object_stroke.get_value (); 835 836 if (tool && StrokeTool.add_stroke) { 837 foreach (Path p in g.active_paths) { 838 p.stroke = StrokeTool.stroke_width; 839 p.reset_stroke (); 840 } 841 } 842 843 f = BirdFont.get_current_font (); 844 f.settings.set_setting ("stroke_width", object_stroke.get_display_value ()); 845 846 GlyphCanvas.redraw (); 847 }); 848 stroke_expander.add_tool (object_stroke); 849 850 move_tool.selection_changed.connect (() => { 851 update_stroke_settings (); 852 }); 853 854 move_tool.objects_moved.connect (() => { 855 update_stroke_settings (); 856 }); 857 858 // create outline from path 859 outline = new Tool ("stroke_to_outline", t_("Create outline form stroke")); 860 outline.select_action.connect ((self) => { 861 StrokeTool s = new StrokeTool (); 862 s.stroke_selected_paths (); 863 outline.set_selected (false); 864 }); 865 stroke_expander.add_tool (outline); 866 867 // set line cap 868 line_cap_butt = new Tool ("line_cap_butt", t_("Butt line cap")); 869 line_cap_butt.select_action.connect ((self) => { 870 Glyph g; 871 872 g = MainWindow.get_current_glyph (); 873 g.store_undo_state (); 874 875 foreach (Path p in g.active_paths) { 876 p.line_cap = LineCap.BUTT; 877 p.reset_stroke (); 878 } 879 880 StrokeTool.line_cap = LineCap.BUTT; 881 Font f = BirdFont.get_current_font (); 882 f.settings.set_setting ("line_cap", @"butt"); 883 884 line_cap_butt.selected = true; 885 line_cap_round.selected = false; 886 line_cap_square.selected = false; 887 888 GlyphCanvas.redraw (); 889 }); 890 stroke_expander.add_tool (line_cap_butt); 891 892 line_cap_round = new Tool ("line_cap_round", t_("Round line cap")); 893 line_cap_round.select_action.connect ((self) => { 894 Glyph g; 895 896 g = MainWindow.get_current_glyph (); 897 g.store_undo_state (); 898 899 foreach (Path p in g.active_paths) { 900 p.line_cap = LineCap.ROUND; 901 p.reset_stroke (); 902 } 903 904 StrokeTool.line_cap = LineCap.ROUND; 905 906 Font f = BirdFont.get_current_font (); 907 f.settings.set_setting ("line_cap", @"round"); 908 909 line_cap_butt.selected = false; 910 line_cap_round.selected = true; 911 line_cap_square.selected = false; 912 913 GlyphCanvas.redraw (); 914 }); 915 stroke_expander.add_tool (line_cap_round); 916 917 line_cap_square = new Tool ("line_cap_square", t_("Square line cap")); 918 line_cap_square.select_action.connect ((self) => { 919 Glyph g; 920 921 g = MainWindow.get_current_glyph (); 922 g.store_undo_state (); 923 924 foreach (Path p in g.active_paths) { 925 p.line_cap = LineCap.SQUARE; 926 p.reset_stroke (); 927 } 928 929 StrokeTool.line_cap = LineCap.SQUARE; 930 931 Font f = BirdFont.get_current_font (); 932 f.settings.set_setting ("line_cap", @"square"); 933 934 line_cap_butt.selected = false; 935 line_cap_round.selected = false; 936 line_cap_square.selected = true; 937 938 GlyphCanvas.redraw (); 939 }); 940 stroke_expander.add_tool (line_cap_square); 941 942 // tests 943 if (BirdFont.has_argument ("--test")) { 944 Tool test_case = new Tool ("test_case"); 945 test_case.select_action.connect((self) => { 946 if (self.is_selected ()) { 947 if (TestBirdFont.is_running ()) { 948 TestBirdFont.pause (); 949 } else { 950 TestBirdFont.continue (); 951 } 952 } 953 }); 954 test_tools.add_tool (test_case); 955 956 Tool slow_test = new Tool ("slow_test"); 957 slow_test.select_action.connect((self) => { 958 bool s = TestBirdFont.is_slow_test (); 959 TestBirdFont.set_slow_test (!s); 960 s = TestBirdFont.is_slow_test (); 961 self.set_selected (s); 962 }); 963 964 test_tools.add_tool (slow_test); 965 966 // Run from commad line 967 string? st = BirdFont.get_argument ("--test"); 968 if (st != null && ((!)st).char_count () > 0) { 969 IdleSource idle = new IdleSource (); 970 971 idle.set_callback (() => { 972 MainWindow.get_toolbox ().select_tool (test_case); 973 return false; 974 }); 975 976 idle.attach (null); 977 } 978 979 if (BirdFont.has_argument ("--slow")) { 980 MainWindow.get_toolbox ().select_tool (slow_test); 981 } 982 983 } 984 985 // guide lines, grid and other guidlines 986 help_lines = new Tool ("help_lines", t_("Show guidelines")); 987 help_lines.select_action.connect ((self) => { 988 bool h; 989 h = GlyphCanvas.get_current_glyph ().get_show_help_lines (); 990 GlyphCanvas.get_current_glyph ().set_show_help_lines (!h); 991 self.set_selected (!h); 992 GlyphCanvas.get_current_glyph ().redraw_help_lines (); 993 }); 994 selected_line = GlyphCanvas.get_current_glyph ().get_show_help_lines (); 995 help_lines.set_selected (selected_line); 996 guideline_tools.add_tool (help_lines); 997 998 xheight_help_lines = new Tool ("show_xheight_helplines", t_("Show more guidelines")); 999 xheight_help_lines.select_action.connect ((self) => { 1000 Glyph g = MainWindow.get_current_glyph (); 1001 bool v = !g.get_xheight_lines_visible (); 1002 g.set_xheight_lines_visible (v); 1003 self.set_selected (v); 1004 GlyphCanvas.redraw (); 1005 1006 if (v && !help_lines.is_selected ()) { 1007 MainWindow.get_toolbox ().select_tool (help_lines); 1008 } 1009 }); 1010 selected_line = GlyphCanvas.get_current_glyph ().get_xheight_lines_visible (); 1011 xheight_help_lines.set_selected (selected_line); 1012 guideline_tools.add_tool (xheight_help_lines); 1013 1014 background_help_lines = new Tool ("background_help_lines", t_("Show guidelines at top and bottom margin")); 1015 background_help_lines.select_action.connect ((self) => { 1016 Glyph g = MainWindow.get_current_glyph (); 1017 bool v = !g.get_margin_lines_visible (); 1018 g.set_margin_lines_visible (v); 1019 self.set_selected (v); 1020 GlyphCanvas.redraw (); 1021 1022 if (v && !help_lines.is_selected ()) { 1023 MainWindow.get_toolbox ().select_tool (help_lines); 1024 } 1025 }); 1026 selected_line = GlyphCanvas.get_current_glyph ().get_margin_lines_visible (); 1027 background_help_lines.set_selected (selected_line); 1028 guideline_tools.add_tool (background_help_lines); 1029 1030 show_grid = new GridTool ("show_grid"); 1031 show_grid.select_action.connect (() => { 1032 grid_expander.visible = show_grid.selected; 1033 MainWindow.get_toolbox ().update_expanders (); 1034 }); 1035 guideline_tools.add_tool (show_grid); 1036 grid_expander.visible = false; 1037 1038 lock_grid = new Tool ("lock_grid", t_("Lock guides and grid")); 1039 lock_grid.select_action.connect ((self) => { 1040 SpinButton sb; 1041 FontSettings fs; 1042 1043 GridTool.lock_grid = !GridTool.lock_grid; 1044 1045 foreach (Tool t in grid.tool) { 1046 if (t is SpinButton) { 1047 sb = (SpinButton) t; 1048 sb.locked = GridTool.lock_grid; 1049 } 1050 } 1051 1052 lock_grid.selected = GridTool.lock_grid; 1053 fs = BirdFont.get_current_font ().settings; 1054 fs.set_setting ("lock_grid", @"$(GridTool.lock_grid)"); 1055 }); 1056 guideline_tools.add_tool (lock_grid); 1057 1058 // Zoom tools 1059 zoom_bar = new ZoomBar (); 1060 zoom_bar.new_zoom.connect ((z) => { 1061 Glyph g = MainWindow.get_current_glyph (); 1062 double zoom = 20 * z + 1; 1063 double xc, yc, nxc, nyc; 1064 1065 xc = Glyph.path_coordinate_x (Glyph.xc ()); 1066 yc = Glyph.path_coordinate_y (Glyph.yc ()); 1067 1068 g.set_zoom (zoom); 1069 1070 nxc = Glyph.path_coordinate_x (Glyph.xc ()); 1071 nyc = Glyph.path_coordinate_y (Glyph.yc ()); 1072 1073 g.view_offset_x -= nxc - xc; 1074 g.view_offset_y += nyc - yc; 1075 1076 GlyphCanvas.redraw (); 1077 }); 1078 zoombar_tool.add_tool (zoom_bar); 1079 1080 Tool reset_zoom = new Tool ("zoom_1_1", t_("Zoom Out More")); 1081 reset_zoom.select_action.connect ((self) => { 1082 zoom_tool.store_current_view (); 1083 glyph_canvas.get_current_display ().reset_zoom (); 1084 glyph_canvas.redraw_area(0, 0, GlyphCanvas.allocation.width, GlyphCanvas.allocation.height); 1085 }); 1086 zoombar_tool.add_tool (reset_zoom); 1087 reset_zoom.set_tool_visibility (false); 1088 1089 Tool full_glyph = new Tool ("full_glyph", t_("Show full glyph")); 1090 full_glyph.select_action.connect((self) => { 1091 zoom_tool.store_current_view (); 1092 zoom_tool.zoom_full_glyph (); 1093 }); 1094 zoombar_tool.add_tool (full_glyph); 1095 1096 Tool zoom_boundaries = new Tool ("zoom_boundaries", t_("Fit in view")); 1097 zoom_boundaries.select_action.connect((self) => { 1098 zoom_tool.store_current_view (); 1099 glyph_canvas.get_current_display ().zoom_max (); 1100 }); 1101 zoombar_tool.add_tool (zoom_boundaries); 1102 1103 Tool zoom_bg = new Tool ("zoom_background_image", t_("Zoom in on background image")); 1104 zoom_bg.select_action.connect((self) => { 1105 if (MainWindow.get_current_glyph ().get_background_image () != null) { 1106 zoom_tool.store_current_view (); 1107 ZoomTool.zoom_full_background_image (); 1108 glyph_canvas.redraw_area(0, 0, GlyphCanvas.allocation.width, GlyphCanvas.allocation.height); 1109 } 1110 }); 1111 zoombar_tool.add_tool (zoom_bg); 1112 1113 Tool zoom_prev = new Tool ("prev", t_("Previous view")); 1114 zoom_prev.select_action.connect((self) => { 1115 zoom_tool.previous_view (); 1116 }); 1117 zoombar_tool.add_tool (zoom_prev); 1118 1119 Tool zoom_next = new Tool ("next", t_("Next view")); 1120 zoom_next.select_action.connect((self) => { 1121 zoom_tool.next_view (); 1122 }); 1123 zoombar_tool.add_tool (zoom_next); // view_tools 1124 zoom_next.set_tool_visibility (false); 1125 1126 // shape tools 1127 circle = new CircleTool ("circle"); 1128 circle.select_action.connect ((self) => { 1129 update_drawing_and_background_tools (self); 1130 }); 1131 shape_tools.add_tool (circle); 1132 1133 rectangle = new RectangleTool ("rectangle"); 1134 rectangle.select_action.connect ((self) => { 1135 update_drawing_and_background_tools (self); 1136 }); 1137 shape_tools.add_tool (rectangle); 1138 1139 add_expander (font_name); 1140 add_expander (draw_tools); 1141 1142 if (BirdFont.android) { 1143 add_expander (key_tools); 1144 } 1145 1146 add_expander (draw_tool_modifiers); 1147 add_expander (layer_settings); 1148 add_expander (layer_tools); 1149 add_expander (stroke_expander); 1150 add_expander (guideline_tools); 1151 add_expander (grid); 1152 add_expander (zoombar_tool); 1153 add_expander (shape_tools); 1154 1155 // Fixa: add_expander (trace); 1156 if (BirdFont.has_argument ("--test")) { 1157 add_expander (test_tools); 1158 } 1159 1160 layer_settings.set_persistent (true); 1161 layer_settings.set_unique (false); 1162 1163 draw_tools.set_persistent (true); 1164 draw_tools.set_unique (false); 1165 1166 stroke_expander.set_persistent (true); 1167 stroke_expander.set_unique (false); 1168 1169 key_tools.set_persistent (false); 1170 key_tools.set_unique (false); 1171 1172 draw_tool_modifiers.set_persistent (true); 1173 draw_tool_modifiers.set_unique (false); 1174 1175 test_tools.set_persistent (true); 1176 1177 guideline_tools.set_persistent (true); 1178 guideline_tools.set_unique (false); 1179 1180 grid.set_persistent (true); 1181 grid.set_unique (true); 1182 1183 shape_tools.set_persistent (true); 1184 shape_tools.set_unique (true); 1185 1186 // let these tools progagate events even when other tools are selected 1187 foreach (Tool t in draw_tools.tool) { 1188 t.editor_events = true; 1189 } 1190 1191 foreach (Tool t in shape_tools.tool) { 1192 t.editor_events = true; 1193 t.persistent = true; 1194 } 1195 1196 move_background.editor_events = true; 1197 cut_background.editor_events = true; 1198 move_canvas.editor_events = true; 1199 1200 move_background.persistent = true; 1201 cut_background.persistent = true; 1202 move_canvas.persistent = true; 1203 1204 // Default selection 1205 IdleSource idle = new IdleSource (); 1206 idle.set_callback (() => { 1207 Toolbox tb = MainWindow.get_toolbox (); 1208 1209 tb.reset_active_tool (); 1210 update_drawing_and_background_tools (point_tool); 1211 tb.select_tool (point_tool); 1212 tb.set_current_tool (point_tool); 1213 1214 set_point_type_from_preferences (); 1215 1216 if (GlyphCanvas.get_current_glyph ().get_show_help_lines ()) { 1217 help_lines.set_selected (true); 1218 help_lines.set_active (false); 1219 } 1220 1221 add_new_grid (1); 1222 add_new_grid (2); 1223 add_new_grid (4); 1224 1225 MainWindow.get_toolbox ().move (0, 0); 1226 set_stroke_tool_visibility (); 1227 1228 return false; 1229 }); 1230 idle.attach (null); 1231 1232 // update selelction when the user switches tab 1233 MainWindow.get_tab_bar ().signal_tab_selected.connect((tab) => { 1234 Glyph glyph; 1235 1236 if (tab.get_display () is Glyph) { 1237 glyph = (Glyph) tab.get_display (); 1238 show_bg.set_selected (glyph.get_background_visible ()); 1239 update_line_selection (glyph); 1240 } 1241 }); 1242 } 1243 1244 public static void update_stroke_settings () { 1245 bool stroke = false; 1246 Glyph g = MainWindow.get_current_glyph (); 1247 1248 foreach (Path p in g.active_paths) { 1249 if (p.stroke > 0) { 1250 stroke = true; 1251 } 1252 } 1253 1254 add_stroke.selected = stroke; 1255 StrokeTool.add_stroke = stroke; 1256 set_stroke_tool_visibility (); 1257 } 1258 1259 void auto_trace_background () { 1260 Glyph g = MainWindow.get_current_glyph (); 1261 BackgroundImage? bg = g.get_background_image (); 1262 BackgroundImage b; 1263 PathList pl; 1264 1265 if (bg != null) { 1266 b = (!) bg; 1267 pl = b.autotrace (); 1268 foreach (Path p in pl.paths) { 1269 g.add_path (p); 1270 } 1271 } 1272 } 1273 1274 void update_line_selection (Glyph glyph) { 1275 help_lines.set_selected (glyph.get_show_help_lines ()); 1276 xheight_help_lines.set_selected (glyph.get_xheight_lines_visible ()); 1277 background_help_lines.set_selected (glyph.get_margin_lines_visible ()); 1278 } 1279 1280 public static void set_point_type_from_preferences () { 1281 string type = Preferences.get ("point_type"); 1282 if (type == "double_points") { 1283 Toolbox.select_tool_by_name ("double_points"); 1284 } else if (type == "quadratic_points") { 1285 Toolbox.select_tool_by_name ("quadratic_points"); 1286 } if (type == "cubic_points") { 1287 Toolbox.select_tool_by_name ("cubic_points"); 1288 } 1289 } 1290 1291 void hide_all_modifiers () { 1292 x_coordinate.set_tool_visibility (false); 1293 y_coordinate.set_tool_visibility (false); 1294 rotation.set_tool_visibility (false); 1295 width.set_tool_visibility (false); 1296 height.set_tool_visibility (false); 1297 1298 reverse_path_tool.set_tool_visibility (false); 1299 full_height_tool.set_tool_visibility (false); 1300 move_layer.set_tool_visibility (false); 1301 flip_vertical.set_tool_visibility (false); 1302 flip_horizontal.set_tool_visibility (false); 1303 1304 tie_handles.set_tool_visibility (false); 1305 reflect_handle.set_tool_visibility (false); 1306 create_line.set_tool_visibility (false); 1307 close_path_tool.set_tool_visibility (false); 1308 1309 quadratic_points.set_tool_visibility (false); 1310 cubic_points.set_tool_visibility (false); 1311 double_points.set_tool_visibility (false); 1312 convert_points.set_tool_visibility (false); 1313 1314 cut_background.set_tool_visibility (false); 1315 show_bg.set_tool_visibility (false); 1316 bg_selection.set_tool_visibility (false); 1317 background_threshold.set_tool_visibility (false); 1318 background_scale.set_tool_visibility (false); 1319 high_contrast_background.set_tool_visibility (false); 1320 auto_trace_resolution.set_tool_visibility (false); 1321 auto_trace.set_tool_visibility (false); 1322 auto_trace_simplify.set_tool_visibility (false); 1323 delete_background.set_tool_visibility (false); 1324 } 1325 1326 void show_background_tool_modifiers () { 1327 draw_tool_modifiers.set_headline (t_("Background Tools")); 1328 1329 cut_background.set_tool_visibility (true); 1330 show_bg.set_tool_visibility (true); 1331 bg_selection.set_tool_visibility (true); 1332 background_threshold.set_tool_visibility (true); 1333 background_scale.set_tool_visibility (true); 1334 high_contrast_background.set_tool_visibility (true); 1335 auto_trace_resolution.set_tool_visibility (true); 1336 auto_trace.set_tool_visibility (true); 1337 auto_trace_simplify.set_tool_visibility (true); 1338 delete_background.set_tool_visibility (true); 1339 } 1340 1341 void show_point_tool_modifiers () { 1342 draw_tool_modifiers.set_headline (t_("Control Points")); 1343 1344 tie_handles.set_tool_visibility (true); 1345 reflect_handle.set_tool_visibility (true); 1346 create_line.set_tool_visibility (true); 1347 close_path_tool.set_tool_visibility (true); 1348 1349 quadratic_points.set_tool_visibility (true); 1350 cubic_points.set_tool_visibility (true); 1351 double_points.set_tool_visibility (true); 1352 convert_points.set_tool_visibility (true); 1353 1354 reverse_path_tool.set_tool_visibility (true); 1355 } 1356 1357 void show_object_tool_modifiers () { 1358 draw_tool_modifiers.set_headline (t_("Object Tools")); 1359 1360 x_coordinate.set_tool_visibility (true); 1361 y_coordinate.set_tool_visibility (true); 1362 rotation.set_tool_visibility (true); 1363 width.set_tool_visibility (true); 1364 height.set_tool_visibility (true); 1365 1366 reverse_path_tool.set_tool_visibility (true); 1367 move_layer.set_tool_visibility (true); 1368 flip_vertical.set_tool_visibility (true); 1369 flip_horizontal.set_tool_visibility (true); 1370 1371 full_height_tool.set_tool_visibility (true); 1372 } 1373 1374 public void update_drawing_and_background_tools (Tool current_tool) { 1375 IdleSource idle = new IdleSource (); 1376 1377 idle.set_callback (() => { 1378 Glyph g = MainWindow.get_current_glyph (); 1379 1380 hide_all_modifiers (); 1381 1382 foreach (Tool t in draw_tools.tool) { 1383 if (t != current_tool) { 1384 t.set_selected (false); 1385 } 1386 } 1387 1388 cut_background.set_selected (false); 1389 1390 bezier_tool.set_selected (false); 1391 pen_tool.set_selected (false); 1392 point_tool.set_selected (false); 1393 zoom_tool.set_selected (false); 1394 move_tool.set_selected (false); 1395 resize_tool.set_selected (false); 1396 track_tool.set_selected (false); 1397 move_canvas.set_selected (false); 1398 delete_background.set_selected (false); 1399 1400 show_bg.set_selected (g.get_background_visible ()); 1401 show_bg.set_active (false); 1402 bg_selection.set_selected (false); 1403 background_scale.set_active (false); 1404 1405 rectangle.set_selected (false); 1406 circle.set_selected (false); 1407 1408 reverse_path_tool.set_selected (false); 1409 move_layer.set_selected (false); 1410 flip_vertical.set_selected (false); 1411 flip_horizontal.set_selected (false); 1412 1413 current_tool.set_selected (true); 1414 1415 if (resize_tool.is_selected () || move_tool.is_selected ()) { 1416 show_object_tool_modifiers (); 1417 } else if (bezier_tool.is_selected () 1418 || pen_tool.is_selected () 1419 || point_tool.is_selected () 1420 || track_tool.is_selected ()) { 1421 show_point_tool_modifiers (); 1422 } else if (move_background.is_selected () 1423 || cut_background.is_selected () 1424 || show_bg.is_selected () 1425 || high_contrast_background.is_selected () 1426 || auto_trace.is_selected ()) { 1427 show_background_tool_modifiers (); 1428 } else { 1429 show_point_tool_modifiers (); 1430 } 1431 1432 MainWindow.get_toolbox ().update_expanders (); 1433 draw_tool_modifiers.redraw (); 1434 1435 return false; 1436 }); 1437 1438 idle.attach (null); 1439 } 1440 1441 void update_type_selection () { 1442 IdleSource idle = new IdleSource (); 1443 1444 // Do this in idle, after the animation 1445 idle.set_callback (() => { 1446 Font f = BirdFont.get_current_font (); 1447 1448 quadratic_points.set_selected (false); 1449 cubic_points.set_selected (false); 1450 double_points.set_selected (false); 1451 1452 switch (point_type) { 1453 case PointType.QUADRATIC: 1454 quadratic_points.set_selected (true); 1455 f.settings.set_setting ("point_type", "quadratic"); 1456 break; 1457 case PointType.CUBIC: 1458 cubic_points.set_selected (true); 1459 f.settings.set_setting ("point_type", "cubic"); 1460 break; 1461 case PointType.DOUBLE_CURVE: 1462 double_points.set_selected (true); 1463 f.settings.set_setting ("point_type", "double_curve"); 1464 break; 1465 } 1466 1467 convert_points.set_selected (false); 1468 1469 Toolbox.redraw_tool_box (); 1470 return false; 1471 }); 1472 1473 idle.attach (null); 1474 } 1475 1476 public static void set_default_point_type (string type) { 1477 if (type == "quadratic") { 1478 quadratic_points.set_selected (true); 1479 point_type = PointType.QUADRATIC; 1480 } else if (type == "cubic") { 1481 cubic_points.set_selected (true); 1482 point_type = PointType.CUBIC; 1483 } else if (type == "double_curve") { 1484 double_points.set_selected (true); 1485 point_type = PointType.DOUBLE_CURVE; 1486 } 1487 } 1488 1489 public override Gee.ArrayList<Expander> get_expanders () { 1490 return expanders; 1491 } 1492 1493 /** Insert new points of this type. */ 1494 public static PointType get_selected_point_type () { 1495 return point_type; 1496 } 1497 1498 public void remove_all_grid_buttons () { 1499 grid_expander.tool.clear (); 1500 1501 GridTool.sizes.clear (); 1502 1503 MainWindow.get_toolbox ().update_expanders (); 1504 MainWindow.get_toolbox ().redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1505 } 1506 1507 public void parse_grid (string spin_button_value) { 1508 SpinButton sb = add_new_grid (double.parse (spin_button_value), false); 1509 MainWindow.get_toolbox ().select_tool (sb); 1510 } 1511 1512 public static SpinButton add_new_grid (double size = 2, bool update_settings_in_font = true) { 1513 SpinButton grid_width = new SpinButton ("grid_width", t_("Set size for grid")); 1514 Toolbox tb = MainWindow.get_toolbox (); 1515 1516 grid_width.set_value_round (size); 1517 1518 grid_width.new_value_action.connect((self) => { 1519 Font font = BirdFont.get_current_font (); 1520 SpinButton w; 1521 1522 grid_width.select_action (grid_width); 1523 font.grid_width.clear (); 1524 1525 foreach (Tool t in grid_expander.tool) { 1526 return_if_fail (t is SpinButton); 1527 w = (SpinButton) t; 1528 font.grid_width.add (w.get_display_value ()); 1529 } 1530 }); 1531 1532 grid_width.select_action.connect((self) => { 1533 return_if_fail (self is SpinButton); 1534 SpinButton sb = (SpinButton) self; 1535 GridTool.set_grid_width (sb.get_value ()); 1536 GlyphCanvas.redraw (); 1537 }); 1538 1539 grid_expander.add_tool (grid_width); 1540 1541 tb.update_expanders (); 1542 1543 tb.redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1544 1545 tb.select_tool (grid_width); 1546 grid_width.set_active (false); 1547 1548 if (update_settings_in_font) { 1549 GridTool.sizes.add (grid_width); 1550 1551 foreach (Tool t in grid_expander.tool) { 1552 SpinButton sb = (SpinButton) t; 1553 BirdFont.get_current_font ().grid_width.add (sb.get_display_value ()); 1554 } 1555 } 1556 1557 return grid_width; 1558 } 1559 1560 public void remove_current_grid () { 1561 Tool grid_width; 1562 Toolbox tb = MainWindow.get_toolbox (); 1563 1564 foreach (Tool t in grid_expander.tool) { 1565 if (t.is_selected () && t is SpinButton) { 1566 GridTool.sizes.remove ((SpinButton)t); 1567 grid_expander.tool.remove (t); 1568 break; 1569 } 1570 } 1571 1572 if (grid_expander.tool.size > 0) { 1573 grid_width = grid_expander.tool.get (grid_expander.tool.size - 1); 1574 tb.select_tool (grid_width); 1575 grid_width.set_active (false); 1576 } 1577 1578 MainWindow.get_toolbox ().update_expanders (); 1579 tb.redraw (0, 0, Toolbox.allocation_width, Toolbox.allocation_height); 1580 } 1581 1582 private void add_expander (Expander e) { 1583 expanders.add (e); 1584 } 1585 1586 public override Gee.ArrayList<string> get_displays () { 1587 Gee.ArrayList<string> d = new Gee.ArrayList<string> (); 1588 d.add ("Glyph"); 1589 return d; 1590 } 1591 1592 public static void update_layers () 1593 requires (!is_null (layer_tools)) { 1594 Glyph g = MainWindow.get_current_glyph (); 1595 int i = 0; 1596 1597 layer_tools.tool.clear (); 1598 foreach (Layer layer in g.layers.subgroups) { 1599 LayerLabel label = new LayerLabel (layer); 1600 layer_tools.add_tool (label, 0); 1601 1602 if (i == g.current_layer) { 1603 label.select_layer (); 1604 } 1605 1606 i++; 1607 } 1608 1609 MainWindow.get_toolbox ().update_expanders (); 1610 layer_tools.redraw (); 1611 Toolbox.redraw_tool_box (); 1612 } 1613 1614 public static void deselect_layers () 1615 requires (!is_null (layer_tools)) { 1616 LayerLabel l; 1617 1618 foreach (Tool t in layer_tools.tool) { 1619 if (t is LayerLabel) { 1620 l = (LayerLabel) t; 1621 l.selected_layer = false; 1622 } 1623 } 1624 } 1625 1626 public static void set_stroke_tool_visibility () { 1627 object_stroke.visible = StrokeTool.add_stroke; 1628 line_cap_butt.visible = StrokeTool.add_stroke; 1629 line_cap_round.visible = StrokeTool.add_stroke; 1630 line_cap_square.visible = StrokeTool.add_stroke; 1631 MainWindow.get_toolbox ().update_expanders (); 1632 stroke_expander.redraw (); 1633 } 1634 } 1635 1636 } 1637