The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Tool.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/Tool.vala.
Fix self intersecting stroke
1 /* 2 Copyright (C) 2012, 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 17 namespace BirdFont { 18 19 public class Tool : Widget { 20 21 public double x = 0; 22 public double y = 0; 23 public double w = 33 * Toolbox.get_scale (); 24 public double h = (33 / 1.11) * Toolbox.get_scale (); 25 26 double scale; 27 28 public bool active = false; 29 public bool selected = false; 30 31 public Text icon_font; 32 33 public signal void select_action (Tool selected); 34 public signal void deselect_action (Tool selected); 35 36 public signal void press_action (Tool selected, int button, int x, int y); 37 public signal void double_click_action (Tool selected, int button, int x, int y); 38 public signal void move_action (Tool selected, int x, int y); 39 public signal void move_out_action (Tool selected); 40 public signal void release_action (Tool selected, int button, int x, int y); 41 42 /** Returns true if tool is listening for scroll wheel actions. */ 43 public signal bool scroll_wheel_up_action (Tool selected); 44 public signal bool scroll_wheel_down_action (Tool selected); 45 46 public signal void key_press_action (Tool selected, uint32 keyval); 47 public signal void key_release_action (Tool selected, uint32 keyval); 48 49 public signal void panel_press_action (Tool selected, uint button, double x, double y); 50 public signal void panel_release_action (Tool selected, uint button, double x, double y); 51 52 /** @return true is event is consumed. */ 53 public signal bool panel_move_action (Tool selected, double x, double y); 54 55 public signal void draw_action (Tool selected, Context cr, Glyph glyph); 56 57 public string name = ""; 58 59 static int next_id = 1; 60 61 int id; 62 63 public bool new_selection = false; 64 65 bool show_bg = true; 66 67 public string tip = ""; 68 69 // keyboard bindings 70 public uint modifier_flag; 71 public unichar key; 72 73 public bool persistent = false; 74 public bool editor_events = false; 75 76 bool waiting_for_tooltip = false; 77 bool showing_this_tooltip = false; 78 static Tool active_tooltip = new Tool (); 79 80 bool visible = true; 81 public bool is_tool_modifier = false; 82 83 public string icon_color = ""; 84 85 /** Create tool with a certain name and load icon "name".png */ 86 public Tool (string? name = null, string tip = "") { 87 this.tip = tip; 88 89 icon_font = new Text (); 90 91 scale = w / 111.0; // scale to 320 dpi 92 93 if (name != null) { 94 set_icon ((!) name); 95 this.name = (!) name; 96 } 97 98 id = next_id; 99 next_id++; 100 101 panel_press_action.connect ((self, button, x, y) => { 102 }); 103 104 move_out_action.connect ((self) => { 105 MainWindow.get_toolbox ().hide_tooltip (); 106 active_tooltip.showing_this_tooltip = false; 107 }); 108 109 panel_move_action.connect ((self, x, y) => { 110 if (is_active ()) { 111 wait_for_tooltip (); 112 } 113 return false; 114 }); 115 } 116 117 public override double get_height () { 118 return 33 * scale; 119 } 120 121 public override double get_width () { 122 return 33 * scale; 123 } 124 125 public void set_tool_visibility (bool v) { 126 visible = v; 127 } 128 129 public bool tool_is_visible () { 130 return visible; 131 } 132 133 void wait_for_tooltip () { 134 TimeoutSource timer_show; 135 int timeout_interval = 1500; 136 137 if (active_tooltip != this) { 138 if (active_tooltip.showing_this_tooltip) { 139 timeout_interval = 1; 140 } 141 142 active_tooltip.showing_this_tooltip = false; 143 showing_this_tooltip = false; 144 active_tooltip = this; 145 146 if (!waiting_for_tooltip) { 147 waiting_for_tooltip = true; 148 timer_show = new TimeoutSource (timeout_interval); 149 timer_show.set_callback (() => { 150 if (tip != "" && active_tooltip.is_active () && !active_tooltip.showing_this_tooltip) { 151 show_tooltip (); 152 } 153 waiting_for_tooltip = false; 154 return waiting_for_tooltip; 155 }); 156 timer_show.attach (null); 157 } 158 } 159 } 160 161 public static void show_tooltip () { 162 TimeoutSource timer_hide; 163 Toolbox toolbox; 164 165 toolbox = MainWindow.get_toolbox (); 166 167 // hide tooltip label later 168 if (!active_tooltip.showing_this_tooltip) { 169 timer_hide = new TimeoutSource (1500); 170 timer_hide.set_callback (() => { 171 if (!active_tooltip.is_active ()) { 172 toolbox.hide_tooltip (); 173 active_tooltip.showing_this_tooltip = false; 174 active_tooltip = new Tool (); 175 } 176 return active_tooltip.showing_this_tooltip; 177 }); 178 timer_hide.attach (null); 179 } 180 181 active_tooltip.showing_this_tooltip = true; 182 183 toolbox.hide_tooltip (); 184 toolbox.show_tooltip (active_tooltip.tip, (int) active_tooltip.x, (int) active_tooltip.y); 185 } 186 187 public void set_icon (string name) { 188 bool found; 189 string icon_file; 190 191 icon_file = Theme.get_icon_file (); 192 icon_font = new Text ((!) name); 193 found = icon_font.load_font (icon_file); 194 icon_font.use_cache (true); 195 icon_font.set_font_size (35); 196 197 if (!found) { 198 warning (@"Icon font for toolbox was not found. ($(icon_file))"); 199 } 200 } 201 202 public bool is_active () { 203 return active; 204 } 205 206 public void set_show_background (bool bg) { 207 show_bg = bg; 208 } 209 210 public int get_id () { 211 return id; 212 } 213 214 public string get_name () { 215 return name; 216 } 217 218 public bool is_selected () { 219 return selected; 220 } 221 222 public string get_tip () { 223 return tip; 224 } 225 226 public new bool is_over (double xp, double yp) { 227 bool r = (x <= xp <= x + w && y <= yp <= y + h); 228 return r; 229 } 230 231 public bool set_selected (bool a) { 232 new_selection = true; 233 selected = a; 234 set_active (a); 235 236 if (!a) { 237 deselect_action (this); 238 } 239 240 return true; 241 } 242 243 /** @return true if this tool changes state, */ 244 public bool set_active (bool ac) { 245 bool ret = (active != ac); 246 active = ac; 247 return ret; 248 } 249 250 public override void draw (Context cr) { 251 double xt = x; 252 double yt = y; 253 254 double bgx, bgy; 255 double iconx, icony; 256 257 string border = "Button Border 3"; 258 string background = "Button Border 3"; 259 260 cr.save (); 261 262 bgx = xt; 263 bgy = yt; 264 265 // Button in four states 266 if (selected) { 267 border = "Button Border 1"; 268 background = "Button Background 1"; 269 } 270 271 if (selected && active) { 272 border = "Button Border 2"; 273 background = "Button Background 2"; 274 } 275 276 if (!selected) { 277 border = "Button Border 3"; 278 background = "Button Background 3"; 279 } 280 281 if (!selected && active) { 282 border = "Button Border 4"; 283 background = "Button Background 4"; 284 } 285 286 Theme.color (cr, background); 287 draw_rounded_rectangle (cr, bgx, bgy, 34, 28, 4); 288 cr.fill (); 289 290 cr.set_line_width (1); 291 Theme.color (cr, border); 292 draw_rounded_rectangle (cr, bgx, bgy, 34, 28, 4); 293 cr.stroke (); 294 295 iconx = bgx + 1 + (w - 1) / 2 - icon_font.get_sidebearing_extent () / 2; 296 icony = bgy + 1 + (h - 1)/ 2 - icon_font.get_height () / 2; 297 298 if (icon_color == "") { 299 if (!selected) { 300 Theme.text_color (icon_font, "Tool Foreground"); 301 } else { 302 Theme.text_color (icon_font, "Selected Tool Foreground"); 303 } 304 } else { 305 Theme.text_color (icon_font, icon_color); 306 } 307 308 icon_font.widget_x = iconx; 309 icon_font.widget_y = icony; 310 311 icon_font.draw (cr); 312 313 cr.restore (); 314 } 315 316 /** Run pending events in main loop before continuing. */ 317 public static void @yield () { 318 int t = 0; 319 TimeoutSource time = new TimeoutSource (500); 320 bool timeout; 321 unowned MainContext context; 322 bool acquired; 323 324 if (TestBirdFont.is_slow_test ()) { 325 timeout = false; 326 327 time.set_callback (() => { 328 timeout = true; 329 return false; 330 }); 331 332 time.attach (null); 333 } else { 334 timeout = true; 335 } 336 337 context = MainContext.default (); 338 acquired = context.acquire (); 339 340 if (unlikely (!acquired)) { 341 warning ("Failed to acquire main loop.\n"); 342 return; 343 } 344 345 while (context.pending () || TestBirdFont.is_slow_test ()) { 346 context.iteration (true); 347 t++; 348 349 if (!context.pending () && TestBirdFont.is_slow_test ()) { 350 if (timeout) break; 351 } 352 } 353 354 context.release (); 355 } 356 357 public void set_persistent (bool p) { 358 persistent = p; 359 } 360 361 public virtual void before_undo () { 362 } 363 364 public virtual void after_undo () { 365 } 366 367 } 368 369 } 370