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