The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

DropMenu.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/DropMenu.vala.
Suppress zoom when canvas is moving
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 enum MenuDirection { 20 DROP_DOWN, 21 POP_UP; 22 } 23 24 public class DropMenu : GLib.Object { 25 26 public delegate void Selected (MenuAction self); 27 public signal void selected (DropMenu self); 28 29 double x = -1; 30 double y = -1; 31 32 double menu_x = -1; 33 34 public bool menu_visible = false; 35 36 Gee.ArrayList <MenuAction> actions = new Gee.ArrayList <MenuAction> (); 37 38 const int item_height = 25; 39 40 MenuDirection direction = MenuDirection.DROP_DOWN; 41 42 public signal void signal_delete_item (int item_index); 43 44 public DropMenu () { 45 } 46 47 public MenuAction get_action_index (int index) { 48 if (!(0 <= index < actions.size)) { 49 warning (@"No action for index $index."); 50 return new MenuAction ("None"); 51 } 52 return actions.get (index); 53 } 54 55 public void recreate_index () { 56 int i = -1; 57 foreach (MenuAction a in actions) { 58 a.index = i; 59 i++; 60 } 61 } 62 63 public MenuAction get_action_no2 () { 64 if (actions.size < 2) { 65 warning ("No such action"); 66 return new MenuAction ("None"); 67 } 68 69 return actions.get (1); 70 } 71 72 public void deselect_all () { 73 foreach (MenuAction m in actions) { 74 m.set_selected (false); 75 } 76 } 77 78 public void set_direction (MenuDirection d) { 79 direction = d; 80 } 81 82 public void close () { 83 menu_visible = false; 84 } 85 86 public MenuAction add_item (string label) { 87 MenuAction m = new MenuAction (label); 88 add_menu_item (m); 89 return m; 90 } 91 92 public void add_menu_item (MenuAction m) { 93 m.parent = this; 94 actions.add (m); 95 } 96 97 public bool is_over_icon (double px, double py) { 98 if (x == -1 || y == -1) { 99 return false; 100 } 101 102 return x - 5 < px < x + 12 + 5 && y - 5 < py < y + 12 + 5; 103 } 104 105 public bool menu_item_action (double px, double py) { 106 MenuAction? action; 107 MenuAction a; 108 MenuAction ma; 109 int index; 110 111 if (menu_visible) { 112 action = get_menu_action_at (px, py); 113 114 if (action != null) { 115 a = (!) action; 116 117 // action for the delete button 118 if (a.has_delete_button && menu_x + 88 - 7 < px < menu_x + 88 + 13) { 119 index = 0; 120 ma = actions.get (0); 121 while (true) { 122 if (a == ma) { 123 actions.remove_at (index); 124 signal_delete_item (index); 125 break; 126 } 127 128 if (ma == actions.get (actions.size - 1)) { 129 break; 130 } else { 131 ma = actions.get (index + 1); 132 index++; 133 } 134 } 135 return false; 136 } else { 137 a.action (a); 138 selected (this); 139 menu_visible = false; 140 } 141 142 return true; 143 } 144 } 145 146 return false; 147 } 148 149 public bool menu_icon_action (double px, double py) { 150 menu_visible = is_over_icon (px, py); 151 return menu_visible; 152 } 153 154 MenuAction? get_menu_action_at (double px, double py) { 155 double n = 0; 156 double ix, iy; 157 158 foreach (MenuAction item in actions) { 159 ix = menu_x - 6; 160 161 if (direction == MenuDirection.DROP_DOWN) { 162 iy = y + 12 + n * item_height; 163 } else { 164 iy = y - 24 - n * item_height; 165 } 166 167 if (ix <= px <= ix + 100 && iy <= py <= iy + item_height) { 168 return item; 169 } 170 171 n++; 172 } 173 174 return null; 175 } 176 177 public void set_position (double px, double py) { 178 x = px; 179 y = py; 180 181 if (x - 100 + 19 < 0) { 182 menu_x = 10; 183 } else { 184 menu_x = x - 100 + 19; 185 } 186 } 187 188 public void draw_menu (Context cr) { 189 double ix, iy; 190 int n; 191 Pattern gradient; 192 193 if (likely (!menu_visible)) { 194 return; 195 } 196 197 cr.save (); 198 cr.set_source_rgba (177/255.0, 177/255.0, 177/255.0, 1); 199 cr.set_line_width (0); 200 201 gradient = new Pattern.linear (menu_x, y - 3 * item_height, menu_x, y); 202 gradient.add_color_stop_rgb (0, 177/255.0, 177/255.0, 177/255.0); 203 gradient.add_color_stop_rgb (1, 234/255.0, 234/255.0, 234/255.0); 204 205 cr.set_source (gradient); 206 cr.rectangle (menu_x, y - actions.size * item_height, 94, actions.size * item_height); 207 208 cr.fill_preserve (); 209 cr.stroke (); 210 cr.restore (); 211 212 cr.save (); 213 214 n = 0; 215 foreach (MenuAction item in actions) { 216 iy = y - 8 - n * item_height; 217 ix = menu_x + 2; 218 219 item.draw (ix, iy, cr); 220 n++; 221 } 222 223 cr.restore (); 224 } 225 } 226 227 } 228