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 15using Cairo; 16using Math; 17 18namespace BirdFont { 19 20internal abstract class SettingsDisplay : FontDisplay { 21 22 double scroll = 0; 23 double content_height = 1; 24 WidgetAllocation allocation; 25 public Gee.ArrayList<SettingsItem> tools; 26 27 public static SpinButton precision; 28 29 SettingsItem new_key_bindings = new SettingsItem.head_line (""); 30 public static bool update_key_bindings = false; 31 32 protected SettingsDisplay () { 33 allocation = new WidgetAllocation (); 34 tools = new Gee.ArrayList<SettingsItem> (); 35 content_height = 200; 36 precision = new SpinButton ("precision"); 37 } 38 39 public abstract void create_setting_items (); 40 41 public override void draw (WidgetAllocation allocation, Context cr) { 42 this.allocation = allocation; 43 44 layout (); 45 46 // background 47 cr.save (); 48 cr.rectangle (0, 0, allocation.width, allocation.height); 49 cr.set_line_width (0); 50 Theme.color (cr, "Default Background"); 51 cr.fill (); 52 cr.stroke (); 53 cr.restore (); 54 55 foreach (SettingsItem s in tools) { 56 if (-20 * MainWindow.units <= s.y <= allocation.height + 20 * MainWindow.units) { 57 s.draw (allocation, cr); 58 } 59 } 60 } 61 62 public void layout () { 63 double y = -scroll; 64 bool first = true; 65 foreach (SettingsItem s in tools) { 66 67 if (!first && s.headline) { 68 y += 30 * MainWindow.units; 69 } 70 71 s.y = y; 72 73 if (s.button != null) { 74 ((!) s.button).y = y; 75 ((!) s.button).x = 20 * MainWindow.units; 76 } 77 78 if (s.headline) { 79 y += 50 * MainWindow.units; 80 } else { 81 y += 40 * MainWindow.units; 82 } 83 84 first = false; 85 } 86 87 content_height = y + scroll; 88 } 89 90 void set_key_bindings (SettingsItem item) { 91 if (new_key_bindings.active) { 92 new_key_bindings.active = false; 93 update_key_bindings = false; 94 } else { 95 new_key_bindings.active = false; 96 new_key_bindings = item; 97 update_key_bindings = true; 98 new_key_bindings.active = true; 99 } 100 } 101 102 public override void key_release (uint keyval) { 103 SettingsItem old_key_binding; 104 105 if (!is_modifier_key (keyval) || keyval == Key.BACK_SPACE || keyval == Key.DEL) { 106 if (update_key_bindings) { 107 if (keyval == Key.BACK_SPACE || keyval == Key.DEL) { 108 update_key_bindings = false; 109 new_key_bindings.active = false; 110 new_key_bindings.menu_item.modifiers = NONE; 111 new_key_bindings.menu_item.key = '\0'; 112 } else if (KeyBindings.get_mod_from_key (keyval) == NONE) { 113 114 if (has_key_binding (KeyBindings.modifier, (unichar) keyval)) { 115 old_key_binding = (!) get_key_binding (KeyBindings.modifier, (unichar) keyval); 116 117 if (same_scope (old_key_binding, new_key_bindings)) { 118 old_key_binding.menu_item.modifiers = NONE; 119 old_key_binding.menu_item.key = '\0'; 120 } 121 } 122 123 new_key_bindings.menu_item.modifiers = KeyBindings.modifier; 124 new_key_bindings.menu_item.key = (unichar) keyval; 125 update_key_bindings = false; 126 new_key_bindings.active = false; 127 } 128 129 MainWindow.get_menu ().write_key_bindings (); 130 GlyphCanvas.redraw (); 131 } 132 } 133 } 134 135 /** Check if key binding is used in same tab. */ 136 bool same_scope (SettingsItem key_binding1, SettingsItem key_binding2) { 137 foreach (string scope in key_binding1.menu_item.displays) { 138 if (key_binding2.menu_item.in_display (scope)) { 139 return true; 140 } 141 } 142 143 return false; 144 } 145 146 bool has_key_binding (uint modifier, unichar key) { 147 return get_key_binding (modifier, key) != null; 148 } 149 150 SettingsItem? get_key_binding (uint modifier, unichar key) { 151 foreach (SettingsItem i in tools) { 152 if (i.menu_item.modifiers == modifier && i.menu_item.key == key) { 153 return i; 154 } 155 } 156 157 return null; 158 } 159 160 public override void button_press (uint button, double x, double y) { 161 foreach (SettingsItem s in tools) { 162 if (s.handle_events && s.button != null) { 163 if (((!) s.button).is_over (x, y)) { 164 165 ((!) s.button).set_selected (! ((!) s.button).selected); 166 167 if (((!) s.button).selected) { 168 ((!) s.button).select_action ((!) s.button); 169 } 170 171 ((!) s.button).panel_press_action ((!) s.button, button, x, y); 172 } 173 } 174 } 175 GlyphCanvas.redraw (); 176 } 177 178 public override void button_release (int button, double x, double y) { 179 foreach (SettingsItem s in tools) { 180 if (s.handle_events && s.button != null) { 181 ((!) s.button).panel_release_action (((!) s.button), button, x, y); 182 } 183 184 if (s.key_bindings && s.y <= y < s.y + 40 * MainWindow.units && button == 1) { 185 set_key_bindings (s); 186 } 187 } 188 GlyphCanvas.redraw (); 189 } 190 191 public override void motion_notify (double x, double y) { 192 bool consumed = false; 193 bool active; 194 bool update = false; 195 196 foreach (SettingsItem si in tools) { 197 198 if (si.handle_events && si.button != null) { 199 active = ((!) si.button).is_over (x, y); 200 201 if (!active && ((!) si.button).is_active ()) { 202 ((!) si.button).move_out_action ((!) si.button); 203 } 204 205 if (((!) si.button).set_active (active)) { 206 update = true; 207 } 208 } 209 } 210 211 foreach (SettingsItem s in tools) { 212 if (s.handle_events && s.button != null) { 213 if (((!) s.button).panel_move_action ((!) s.button, x, y)) { 214 consumed = true; 215 } 216 } 217 } 218 219 if (consumed || update) { 220 GlyphCanvas.redraw (); 221 } 222 } 223 224 public override string get_label () { 225 return t_("Settings"); 226 } 227 228 public override string get_name () { 229 return "Settings"; 230 } 231 232 public override bool has_scrollbar () { 233 return true; 234 } 235 236 public override void scroll_wheel (double x, double y, double pixeldelta, double dy) { 237 if (dy < 0) { 238 foreach (SettingsItem s in tools) { 239 if (s.handle_events && s.button != null) { 240 if (((!) s.button).is_over (x, y)) { 241 ((!) s.button).scroll_wheel_down_action ((!) s.button); 242 return; 243 } 244 } 245 } 246 } else { 247 foreach (SettingsItem s in tools) { 248 if (s.handle_events && s.button != null) { 249 if (((!) s.button).is_over (x, y)) { 250 ((!) s.button).scroll_wheel_up_action ((!) s.button); 251 return; 252 } 253 } 254 } 255 } 256 257 scroll -= dy * MainWindow.units; 258 259 if (scroll + allocation.height >= content_height) { 260 scroll = content_height - allocation.height; 261 } 262 263 if (scroll < 0) { 264 scroll = 0; 265 } 266 267 update_scrollbar (); 268 GlyphCanvas.redraw (); 269 } 270 271 public override void selected_canvas () { 272 MainWindow.get_toolbox ().set_default_tool_size (); 273 update_scrollbar (); 274 GlyphCanvas.redraw (); 275 } 276 277 public override void update_scrollbar () { 278 double h = content_height - allocation.height; 279 MainWindow.set_scrollbar_size (allocation.height / content_height); 280 MainWindow.set_scrollbar_position (scroll / h); 281 } 282 283 public override void scroll_to (double percent) { 284 double h = content_height - allocation.height; 285 scroll = percent * h; 286 GlyphCanvas.redraw (); 287 } 288} 289 290} 291