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