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