The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

AbstractMenu.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/AbstractMenu.vala.
Show key bindings in tool tip
1 /* 2 Copyright (C) 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 B; 17 18 namespace BirdFont { 19 20 /** Interface for events from native window to the current tab. */ 21 public class AbstractMenu : GLib.Object { 22 23 public bool show_menu { 24 get { 25 return menu_visibility; 26 } 27 28 set { 29 string tab_name; 30 31 menu_visibility = value; 32 current_menu = top_menu; 33 34 if (menu_visibility) { 35 tab_name = MainWindow.get_tab_bar ().get_selected_tab ().get_display ().get_name (); 36 if (tab_name == "Preview") { 37 MenuTab.select_overview (); 38 } 39 } 40 } 41 } 42 43 public bool menu_visibility = false; 44 public SubMenu top_menu; 45 46 SubMenu current_menu; 47 WidgetAllocation allocation = new WidgetAllocation (); 48 49 double width = 250 * MainWindow.units; 50 double height = 25 * MainWindow.units; 51 52 public Gee.HashMap<string, MenuItem> menu_items = new Gee.HashMap<string, MenuItem> (); 53 public Gee.ArrayList<MenuItem> sorted_menu_items = new Gee.ArrayList<MenuItem> (); 54 55 public AbstractMenu () { 56 } 57 58 public void process_key_binding_events (uint keyval) { 59 string display; 60 FontDisplay current_display = MainWindow.get_current_display (); 61 ToolItem tm; 62 63 foreach (MenuItem item in sorted_menu_items) { 64 if (item.key == (unichar) keyval && item.modifiers == KeyBindings.modifier) { 65 66 display = current_display.get_name (); 67 68 if (current_display is Glyph) { 69 display = "Glyph"; 70 } 71 72 if (!current_display.needs_modifier () || item.modifiers != NONE) { 73 if (!SettingsDisplay.update_key_bindings 74 && item.in_display (display) 75 && !(item is ToolItem)) { 76 item.action (); 77 return; 78 } 79 80 if (item is ToolItem) { 81 tm = (ToolItem) item; 82 83 if (tm.in_display (display)) { 84 if (tm.tool.editor_events) { 85 MainWindow.get_toolbox ().set_current_tool (tm.tool); 86 tm.tool.select_action (tm.tool); 87 return; 88 } else { 89 tm.tool.select_action (tm.tool); 90 return; 91 } 92 } 93 } 94 } 95 } 96 } 97 } 98 99 public void load_key_bindings () { 100 File default_key_bindings = SearchPaths.find_file (null, "key_bindings.xml"); 101 File user_key_bindings = get_child (BirdFont.get_settings_directory (), "key_bindings.xml"); 102 103 if (default_key_bindings.query_exists ()) { 104 parse_key_bindings (default_key_bindings); 105 } 106 107 if (user_key_bindings.query_exists ()) { 108 parse_key_bindings (user_key_bindings); 109 } 110 } 111 112 public void parse_key_bindings (File f) { 113 string xml_data; 114 XmlParser parser; 115 116 try { 117 FileUtils.get_contents((!) f.get_path (), out xml_data); 118 parser = new XmlParser (xml_data); 119 parse_bindings (parser.get_root_tag ()); 120 } catch (GLib.Error e) { 121 warning (e.message); 122 } 123 } 124 125 public void parse_bindings (Tag tag) { 126 foreach (Tag t in tag) { 127 if (t.get_name () == "action") { 128 parse_binding (t.get_attributes ()); 129 } 130 } 131 } 132 133 public void parse_binding (Attributes attr) { 134 uint modifier = NONE; 135 unichar key = '\0'; 136 string action = ""; 137 MenuItem menu_action; 138 MenuItem? ma; 139 140 foreach (Attribute a in attr) { 141 if (a.get_name () == "key") { 142 key = a.get_content ().get_char (0); 143 } 144 145 if (a.get_name () == "ctrl" && a.get_content () == "true") { 146 modifier |= CTRL; 147 } 148 149 if (a.get_name () == "alt" && a.get_content () == "true") { 150 modifier |= ALT; 151 } 152 153 if (a.get_name () == "command" && a.get_content () == "true") { 154 modifier |= LOGO; 155 } 156 157 if (a.get_name () == "shift" && a.get_content () == "true") { 158 modifier |= SHIFT; 159 } 160 161 if (a.get_name () == "action") { 162 action = a.get_content (); 163 } 164 } 165 166 ma = menu_items.get (action); 167 if (ma != null) { 168 menu_action = (!) ma; 169 menu_action.modifiers = modifier; 170 menu_action.key = key; 171 } 172 } 173 174 public MenuItem add_menu_item (string label, string description = "", string display = "") { 175 MenuItem i = new MenuItem (label, description); 176 177 if (description != "") { 178 menu_items.set (description, i); 179 sorted_menu_items.add (i); 180 } 181 182 if (display != "") { 183 i.add_display (display); 184 } 185 186 return i; 187 } 188 189 public void button_release (int button, double ex, double ey) { 190 double y = 0; 191 double x = allocation.width - width; 192 193 if (button == 1) { 194 foreach (MenuItem item in current_menu.items) { 195 if (x <= ex < allocation.width && y <= ey <= y + height) { 196 item.action (); 197 GlyphCanvas.redraw (); 198 return; 199 } 200 201 y += height; 202 } 203 204 menu_visibility = false; 205 current_menu = (!) top_menu; 206 GlyphCanvas.redraw (); 207 } 208 } 209 210 public void add_tool_key_bindings () { 211 ToolItem tool_item; 212 foreach (ToolCollection tool_set in MainWindow.get_toolbox ().tool_sets) { 213 foreach (Expander e in tool_set.get_expanders ()) { 214 foreach (Tool t in e.tool) { 215 tool_item = new ToolItem (t); 216 if (tool_item.identifier != "" && !has_menu_item (tool_item.identifier)) { 217 menu_items.set (tool_item.identifier, tool_item); 218 sorted_menu_items.add (tool_item); 219 } 220 221 foreach (string d in tool_set.get_displays ()) { 222 tool_item.add_display (d); 223 } 224 } 225 } 226 } 227 } 228 229 public bool has_menu_item (string identifier) { 230 foreach (MenuItem mi in sorted_menu_items) { 231 if (mi.identifier == identifier) { 232 return true; 233 } 234 } 235 236 return false; 237 } 238 239 public void set_menu (SubMenu m) { 240 current_menu = m; 241 GlyphCanvas.redraw (); 242 } 243 244 public double layout_width () { 245 Text key_binding = new Text (); 246 double font_size = 17 * MainWindow.units;; 247 double w; 248 249 width = 0; 250 foreach (MenuItem item in current_menu.items) { 251 key_binding.set_text (item.get_key_bindings ()); 252 253 item.label.set_font_size (font_size); 254 key_binding.set_font_size (font_size); 255 256 w = item.label.get_extent (); 257 w += key_binding.get_extent (); 258 w += 3 * height * MainWindow.units; 259 260 if (w > width) { 261 width = w; 262 } 263 } 264 265 return width; 266 } 267 268 public void draw (WidgetAllocation allocation, Context cr) { 269 double y; 270 double x; 271 double label_x; 272 double label_y; 273 double font_size; 274 Text key_binding; 275 double binding_extent; 276 277 width = layout_width (); 278 279 key_binding = new Text (); 280 281 x = allocation.width - width; 282 y = 0; 283 font_size = 17 * MainWindow.units; 284 this.allocation = allocation; 285 286 foreach (MenuItem item in current_menu.items) { 287 cr.save (); 288 Theme.color (cr, "Menu Background"); 289 cr.rectangle (x, y, width, height); 290 cr.fill (); 291 cr.restore (); 292 293 cr.save (); 294 label_x = allocation.width - width + 0.7 * height * MainWindow.units; 295 label_y = y + font_size - 1 * MainWindow.units; 296 Theme.text_color (item.label, "Menu Foreground"); 297 item.label.draw_at_baseline (cr, label_x, label_y); 298 299 key_binding.set_text (item.get_key_bindings ()); 300 key_binding.set_font_size (font_size); 301 binding_extent = key_binding.get_extent (); 302 label_x = x + width - binding_extent - 0.6 * height * MainWindow.units; 303 key_binding.set_font_size (font_size); 304 Theme.text_color (key_binding, "Menu Foreground"); 305 key_binding.draw_at_baseline (cr, label_x, label_y); 306 307 y += height; 308 } 309 } 310 311 public void write_key_bindings () { 312 DataOutputStream os; 313 File file; 314 bool has_ctrl, has_alt, has_command, has_shift; 315 316 file = get_child (BirdFont.get_settings_directory (), "key_bindings.xml"); 317 318 try { 319 if (file.query_exists ()) { 320 file.delete (); 321 } 322 } catch (GLib.Error e) { 323 warning (e.message); 324 } 325 326 try { 327 os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); 328 os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>"""); 329 os.put_string ("\n"); 330 331 os.put_string ("<bindings>\n"); 332 333 foreach (MenuItem item in sorted_menu_items) { 334 os.put_string ("\t<action "); 335 336 os.put_string (@"key=\"$((!)item.key.to_string ())\" "); 337 338 has_ctrl = (item.modifiers & CTRL) > 0; 339 os.put_string (@"ctrl=\"$(has_ctrl.to_string ())\" "); 340 341 has_alt = (item.modifiers & ALT) > 0; 342 os.put_string (@"alt=\"$(has_alt.to_string ())\" "); 343 344 has_command = (item.modifiers & LOGO) > 0; 345 os.put_string (@"command=\"$(has_command.to_string ())\" "); 346 347 has_shift = (item.modifiers & SHIFT) > 0; 348 os.put_string (@"shift=\"$(has_shift.to_string ())\" "); 349 350 os.put_string (@"action=\"$(item.identifier)\" "); 351 352 os.put_string ("/>\n"); 353 } 354 os.put_string ("</bindings>\n"); 355 356 os.close (); 357 } catch (GLib.Error e) { 358 warning (e.message); 359 } 360 } 361 362 public void set_current_menu (SubMenu menu) { 363 current_menu = menu; 364 } 365 } 366 367 } 368