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