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