The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Toolbox.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/Toolbox.vala.
Merge ../birdfont-2.x
1 /* 2 Copyright (C) 2012 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 Toolbox : GLib.Object { 21 public static ToolCollection current_set; 22 23 public static HiddenTools hidden_tools; 24 public static DrawingTools drawing_tools; 25 public static KerningTools kerning_tools; 26 public static PreviewTools preview_tools; 27 public static OverviewTools overview_tools; 28 public static BackgroundTools background_tools; 29 public static SpacingTools spacing_tools; 30 public static SpacingClassTools spacing_class_tools; 31 public static FileTools file_tools; 32 public static ThemeTools theme_tools; 33 34 public Tool press_tool; 35 36 public signal void redraw (int x, int y, int w, int h); 37 38 public static int allocation_width = 0; 39 public static int allocation_height = 0; 40 41 /** Scrolling with scroll wheel */ 42 bool scrolling_toolbox = false; 43 44 /** Scroll with touch pad. */ 45 bool scrolling_touch = false; 46 double scroll_y = 0; 47 48 public Gee.ArrayList<ToolCollection> tool_sets; 49 50 string? tool_tip = null; 51 double tool_tip_x = 0; 52 double tool_tip_y = 0; 53 54 public signal void new_tool_set (Tab? tab); 55 bool suppress_event = false; 56 57 public Toolbox (GlyphCanvas glyph_canvas, TabBar tab_bar) { 58 tool_sets = new Gee.ArrayList<ToolCollection> (); 59 press_tool = new Tool (null); 60 61 hidden_tools = new HiddenTools (); 62 drawing_tools = new DrawingTools (glyph_canvas); 63 kerning_tools = new KerningTools (); 64 preview_tools = new PreviewTools (); 65 overview_tools = new OverviewTools (); 66 background_tools = new BackgroundTools (); 67 spacing_tools = new SpacingTools (); 68 spacing_class_tools = new SpacingClassTools (); 69 file_tools = new FileTools (); 70 theme_tools = new ThemeTools (); 71 72 tool_sets.add (theme_tools); 73 tool_sets.add (file_tools); 74 tool_sets.add (hidden_tools); 75 tool_sets.add (drawing_tools); 76 tool_sets.add (kerning_tools); 77 tool_sets.add (preview_tools); 78 tool_sets.add (overview_tools); 79 tool_sets.add (spacing_class_tools); 80 tool_sets.add (background_tools); 81 // the menu has all the file_tools commands, it will not be added here 82 tool_sets.add (hidden_tools); // tools without a button 83 84 current_set = file_tools; 85 current_set.selected (); 86 87 tab_bar.signal_tab_selected.connect ((tab) => { 88 string tab_name = tab.get_display ().get_name (); 89 set_toolbox_from_tab (tab_name, tab); 90 new_tool_set (tab); 91 }); 92 93 update_expanders (); 94 } 95 96 public void set_suppress_event (bool e) { 97 suppress_event = e; 98 } 99 100 public static DrawingTools get_drawing_tools () { 101 return drawing_tools; 102 } 103 104 public void update_all_expanders () { 105 foreach (ToolCollection tc in tool_sets) { 106 tc.redraw (); 107 } 108 } 109 110 public static void cache_all_tools () { 111 Toolbox t = MainWindow.get_toolbox (); 112 113 foreach (ToolCollection tc in t.tool_sets) { 114 tc.cache (); 115 } 116 } 117 118 public static void set_toolbox_from_tab (string tab_name, Tab? t = null) { 119 if (tab_name == "Spacing") { 120 current_set = (ToolCollection) spacing_tools; 121 } else if (tab_name == "Kerning") { 122 current_set = (ToolCollection) kerning_tools; 123 } else if (tab_name == "Preview") { 124 current_set = (ToolCollection) preview_tools; 125 } else if (tab_name == "Overview") { 126 current_set = (ToolCollection) overview_tools; 127 } else if (tab_name == "Backgrounds") { 128 current_set = (ToolCollection) background_tools; 129 } else if (tab_name == "SpacingClasses") { 130 current_set = (ToolCollection) spacing_class_tools; 131 } else if (tab_name == "Themes") { 132 current_set = (ToolCollection) theme_tools; 133 } else if (t != null && ((!) t).get_display () is GlyphTab) { 134 current_set = (ToolCollection) drawing_tools; 135 } else if (t != null && ((!) t).get_display () is Glyph) { 136 warning ("Expecting GlyphTab instead of Glyph."); 137 current_set = (ToolCollection) drawing_tools; 138 } else { 139 current_set = (ToolCollection) file_tools; 140 } 141 142 current_set.selected (); 143 MainWindow.get_toolbox ().update_expanders (); 144 redraw_tool_box (); 145 } 146 147 public static Tool get_move_tool () { 148 return DrawingTools.move_tool; 149 } 150 151 public static void set_object_stroke (double width) { 152 DrawingTools.object_stroke.set_value_round (width); 153 redraw_tool_box (); 154 } 155 156 public static void set_allocation (int width, int height) { 157 if (width != allocation_width || allocation_height != height) { 158 allocation_width = width; 159 allocation_height = height; 160 Toolbox.redraw_tool_box (); 161 } 162 } 163 164 public void press (uint button, double x, double y) { 165 if (MenuTab.has_suppress_event () || suppress_event) { 166 warn_if_test ("Event suppressed"); 167 return; 168 } 169 170 y -= current_set.scroll; 171 172 foreach (Expander exp in current_set.get_expanders ()) { 173 if (exp.visible) { 174 foreach (Tool t in exp.tool) { 175 if (t.tool_is_visible () && t.is_over (x, y)) { 176 t.panel_press_action (t, button, x, y); 177 press_tool = t; 178 } 179 } 180 } 181 } 182 183 scrolling_touch = true; 184 scroll_y = y; 185 } 186 187 public void release (uint button, double x, double y) { 188 bool active; 189 190 y -= current_set.scroll; 191 192 if (MenuTab.has_suppress_event () || suppress_event) { 193 warn_if_test ("Event suppressed"); 194 return; 195 } 196 197 foreach (Expander exp in current_set.get_expanders ()) { 198 if (exp.visible) { 199 foreach (Tool t in exp.tool) { 200 if (t.tool_is_visible ()) { 201 active = t.is_over (x, y); 202 203 if (active) { 204 if (press_tool == t) { 205 select_tool (t); 206 } 207 } 208 209 t.panel_release_action (t, button, x, y); 210 } 211 } 212 } 213 } 214 215 scrolling_touch = false; 216 } 217 218 public void double_click (uint button, double x, double y) { 219 if (MenuTab.has_suppress_event () || suppress_event) { 220 warn_if_test ("Event suppressed"); 221 return; 222 } 223 224 y -= current_set.scroll; 225 226 foreach (Expander e in current_set.get_expanders ()) { 227 if (e.visible) { 228 foreach (Tool t in e.tool) { 229 t.panel_double_click_action (t, button, x, y); 230 } 231 } 232 } 233 } 234 235 public void scroll_wheel (double x, double y, double dx, double dy) { 236 bool action = false; 237 238 y -= current_set.scroll; 239 240 if (MenuTab.has_suppress_event () || suppress_event) { 241 warn_if_test ("Event suppressed"); 242 return; 243 } 244 245 if (!scrolling_toolbox) { 246 foreach (Expander exp in current_set.get_expanders ()) { 247 if (exp.visible) { 248 foreach (Tool t in exp.tool) { 249 if (t.tool_is_visible () && t.is_over (x, y)) { 250 if (dy < 0) { 251 action = t.scroll_wheel_up_action (t); 252 } else { 253 action = t.scroll_wheel_down_action (t); 254 } 255 press_tool = t; 256 } 257 } 258 } 259 } 260 } 261 262 if (!action) { 263 scroll_current_set (dy); 264 } 265 266 redraw_tool_box (); 267 } 268 269 void scroll_current_set (double d) { 270 current_set.scroll += d; 271 272 if (current_set.scroll > 0) { 273 current_set.scroll = 0; 274 } 275 276 if (current_set.content_height < allocation_height) { 277 current_set.scroll = 0; 278 } else if (current_set.content_height + current_set.scroll < allocation_height) { 279 current_set.scroll = allocation_height - current_set.content_height; 280 } 281 282 update_expanders (); 283 suppress_scroll (); 284 } 285 286 public void scroll_up (double x, double y) { 287 scroll_wheel (x, y, 0, 20); 288 } 289 290 public void scroll_down (double x, double y) { 291 scroll_wheel (x, y, 0, -20); 292 } 293 294 void suppress_scroll () { 295 scrolling_toolbox = true; 296 297 Timeout.add (2000, () => { 298 scrolling_toolbox = false; 299 return false; 300 }); 301 } 302 303 public void move (double x, double y) { 304 bool update; 305 bool a; 306 bool consumed = false; 307 bool active; 308 309 y -= current_set.scroll; 310 311 MainWindow.set_cursor (NativeWindow.VISIBLE); 312 313 foreach (Expander exp in current_set.get_expanders ()) { 314 if (exp.visible) { 315 a = exp.is_over (x, y); 316 update = exp.set_active (a); 317 318 if (update) { 319 redraw ((int) exp.x - 10, (int) exp.y - 10, (int) (exp.x + exp.w + 20), (int) (exp.y + exp.h + 20)); 320 } 321 322 foreach (Tool t in exp.tool) { 323 if (t.tool_is_visible ()) { 324 active = t.is_over (x, y); 325 326 if (!active && t.is_active ()) { 327 t.move_out_action (t); 328 } 329 330 update = t.set_active (active); 331 332 if (update) { 333 redraw (0, 0, allocation_width, allocation_height); 334 } 335 336 if (t.panel_move_action (t, x, y)) { 337 consumed = true; 338 } 339 } 340 } 341 } 342 } 343 344 if (scrolling_touch && !consumed && BirdFont.android) { 345 scroll_current_set (y - scroll_y); 346 scroll_y = y; 347 redraw_tool_box (); 348 } 349 } 350 351 public static void redraw_tool_box () { 352 if (MenuTab.has_suppress_event ()) { 353 warn_if_test ("Don't redraw toolbox when background thread is running."); 354 return; 355 } 356 357 Toolbox t = MainWindow.get_toolbox (); 358 if (!is_null (t)) { 359 t.redraw (0, 0, allocation_width, allocation_height); 360 } 361 } 362 363 public void reset_active_tool () { 364 foreach (Expander exp in current_set.get_expanders ()) { 365 foreach (Tool t in exp.tool) { 366 t.set_active (false); 367 } 368 } 369 } 370 371 public Tool? get_active_tool () { 372 foreach (Expander exp in current_set.get_expanders ()) { 373 foreach (Tool t in exp.tool) { 374 if (t.is_active ()) { 375 return t; 376 } 377 } 378 } 379 380 return null; 381 } 382 383 public void set_current_tool (Tool tool) { 384 if (tool.editor_events) { 385 current_set.set_current_tool (tool); 386 } 387 } 388 389 public Tool get_current_tool () { 390 return current_set.get_current_tool (); 391 } 392 393 public void select_tool (Tool tool) { 394 bool update; 395 int offset_y; 396 foreach (Expander exp in current_set.get_expanders ()) { 397 if (exp.visible) { 398 foreach (Tool t in exp.tool) { 399 if (tool.get_id () == t.get_id ()) { 400 if (!t.tool_is_visible ()) { 401 warning ("Tool is hidden"); 402 } else { 403 update = false; 404 405 update = tool.set_selected (true); 406 if (tool.persistent) { 407 update = tool.set_active (true); 408 } 409 410 tool.select_action (tool); 411 412 if (update) { 413 offset_y = (int) (exp.y - scroll_y); 414 redraw ((int) exp.x - 10, (int) offset_y - 10, allocation_width, (int) (allocation_height - offset_y + 10)); 415 } 416 417 set_current_tool (tool); 418 } 419 } 420 } 421 } 422 } 423 } 424 425 public Tool get_tool (string name) { 426 foreach (ToolCollection tc in tool_sets) { 427 foreach (Expander e in tc.get_expanders ()) { 428 foreach (Tool t in e.tool) { 429 if (t.get_name () == name) { 430 return t; 431 } 432 } 433 } 434 } 435 436 warning ("No tool found for name \"%s\".\n", name); 437 438 return new Tool ("no_icon"); 439 } 440 441 public static void set_tool_visible (string name, bool visible) { 442 Toolbox tb = MainWindow.get_toolbox (); 443 Tool t = tb.get_tool (name); 444 t.set_tool_visibility (visible); 445 tb.update_expanders (); 446 Toolbox.redraw_tool_box (); 447 } 448 449 public static void select_tool_by_name (string name) { 450 Toolbox b = MainWindow.get_toolbox (); 451 452 if (is_null (b)) { 453 return; 454 } 455 456 b.select_tool (b.get_tool (name)); 457 } 458 459 public static double get_scale () { 460 return MainWindow.units; 461 } 462 463 public void set_default_tool_size () { 464 foreach (ToolCollection t in tool_sets) { 465 foreach (Expander e in t.get_expanders ()) { 466 e.update_tool_position (); 467 } 468 } 469 } 470 471 public void update_expanders () { 472 double pos; 473 474 foreach (Expander e in current_set.get_expanders ()) { 475 e.set_scroll (current_set.scroll); 476 } 477 478 pos = 4 * get_scale (); 479 foreach (Expander e in current_set.get_expanders ()) { 480 if (e.visible) { 481 e.set_offset (pos); 482 pos += e.get_content_height () + 4 * get_scale (); 483 current_set.content_height = pos; 484 485 if (BirdFont.android) { 486 current_set.content_height *= 1.15; 487 } 488 } 489 } 490 491 foreach (Expander e in current_set.get_expanders ()) { 492 e.set_active (false); 493 } 494 } 495 496 private void draw_expanders (int w, int h, Context cr) { 497 foreach (Expander e in current_set.get_expanders ()) { 498 if (e.visible) { 499 e.draw (cr); 500 } 501 } 502 } 503 504 public void draw (int w, int h, Context cr) { 505 cr.save (); 506 507 Theme.color (cr, "Default Background"); 508 509 cr.rectangle (0, 0, w, h); 510 cr.set_line_width (0); 511 cr.fill (); 512 513 draw_expanders (w, h, cr); 514 515 cr.restore (); 516 517 draw_tool_tip (cr); 518 } 519 520 private void draw_tool_tip (Context cr) { 521 TextArea t; 522 523 if (tool_tip != null && tool_tip != "") { 524 t = new TextArea (17 * get_scale ()); 525 t.allocation = new WidgetAllocation.for_area (0, 0, allocation_width, allocation_height); 526 t.set_editable (false); 527 t.set_text ((!) tool_tip); 528 t.width = allocation_width - 20 * get_scale (); 529 t.min_height = 17 * get_scale (); 530 t.height = 17 * get_scale (); 531 532 t.layout (); 533 534 t.widget_x = 10 * get_scale (); 535 t.widget_y = tool_tip_y - t.height - 5 * get_scale (); 536 537 if (t.widget_y < 5) { 538 t.widget_y = 5; 539 } 540 541 t.draw (cr); 542 } 543 } 544 545 public void hide_tooltip () { 546 if (tool_tip != null) { 547 tool_tip = null; 548 redraw_tool_box (); 549 } 550 } 551 552 public void show_tooltip (string tool_tip, double x, double y) { 553 if (tool_tip != "") { 554 this.tool_tip = tool_tip; 555 this.tool_tip_x = x; 556 this.tool_tip_y = y; 557 558 redraw_tool_box (); 559 } 560 } 561 562 public void set_current_tool_set (ToolCollection ts) { 563 current_set = ts; 564 } 565 566 public class EmptySet : ToolCollection { 567 Gee.ArrayList<Expander> expanders; 568 569 public EmptySet () { 570 expanders = new Gee.ArrayList<Expander> (); 571 } 572 573 public override Gee.ArrayList<Expander> get_expanders () { 574 return expanders; 575 } 576 } 577 } 578 579 } 580