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