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