The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Expander.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/Expander.vala.
Bottom margin in expander
1 /* 2 Copyright (C) 2012 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 Math; 17 18 namespace BirdFont { 19 20 public class Expander : GLib.Object { 21 22 private static const double HEADLINE_MARGIN = 4; 23 24 public double x = 7; 25 public double y = 5; 26 public double scroll = 0; 27 28 public double w = 6; 29 public double h = 5; 30 31 public double margin = 0; 32 33 protected double opacity = 0; 34 35 protected bool active = false; 36 37 public Gee.ArrayList<Tool> tool; 38 39 bool persist = false; 40 bool unique = false; 41 42 double content_height = 0; 43 44 string? headline; 45 Text title; 46 47 public bool visible = true; 48 Surface? cached = null; 49 50 public Expander (string? headline = null) { 51 this.headline = headline; 52 53 title = new Text (); 54 55 if (headline != null) { 56 title.set_text ((!) headline); 57 } 58 59 tool = new Gee.ArrayList<Tool> (); 60 } 61 62 public void set_headline (string? h) { 63 headline = h; 64 } 65 66 public double get_content_height () { 67 return content_height; 68 } 69 70 /** Returns true if tools can be used with the current canvas after 71 * they have been selectes and false if they are a commands to be executed. 72 */ 73 public bool is_persistent () { 74 return persist; 75 } 76 77 /** Returns true if all other tools in thid expander should be deselected 78 * when a tool is selected. 79 */ 80 public bool is_unique () { 81 return unique; 82 } 83 84 public void set_persistent (bool p) { 85 persist = p; 86 } 87 88 public void set_unique (bool u) { 89 unique = u; 90 } 91 92 public void update_tool_position () { 93 double scale = Toolbox.get_scale (); 94 double margin_small = 5 * scale; 95 double xt = x; 96 double yt = y + margin_small; // + scroll 97 bool new_row = false; 98 bool has_visible_tools = false; 99 Tool previous; 100 bool first_row; 101 102 foreach (Tool t in tool) { 103 if (t.tool_is_visible ()) { 104 has_visible_tools = true; 105 break; 106 } 107 } 108 109 if (!has_visible_tools) { 110 content_height = 0; 111 return; 112 } 113 114 foreach (Tool t in tool) { 115 if (t is ZoomBar) { 116 t.w = Toolbox.allocation_width * scale; 117 t.h = 10 * scale; // 7 118 } else if (t is LabelTool) { 119 t.w = Toolbox.allocation_width * scale; 120 t.h = 22 * scale; 121 } else if (t is FontName) { 122 t.w = Toolbox.allocation_width * scale; 123 t.h = 20 * scale; 124 } else if (t is KerningRange) { 125 t.w = Toolbox.allocation_width * scale; 126 t.h = 17 * scale; 127 } else { 128 t.w = 33 * scale; 129 t.h = (33 / 1.11) * scale; 130 } 131 } 132 133 if (tool.size > 0) { 134 content_height = tool.get (0).h + margin_small; 135 } else { 136 content_height = 0; 137 } 138 139 if (headline != null && tool.size > 0) { 140 yt += 17 * scale + HEADLINE_MARGIN; 141 content_height += 17 * scale + HEADLINE_MARGIN; 142 } 143 144 if (tool.size > 0) { 145 previous = tool.get (0); 146 first_row = true; 147 foreach (Tool t in tool) { 148 if (t.tool_is_visible ()) { 149 new_row = xt + t.w > Toolbox.allocation_width - 7 * scale; 150 151 if (t is ZoomBar) { 152 t.x = xt; 153 t.y = yt; 154 //content_height += t.h; 155 yt += t.h + 7 * scale; 156 previous = t; 157 continue; 158 } 159 160 if (previous is ZoomBar) { 161 content_height += t.h; 162 } 163 164 if (new_row && !first_row) { 165 content_height += previous.h + margin_small; 166 xt = x; 167 yt += previous.h; 168 169 if (t is LabelTool) { 170 // yt += 0 * scale; 171 } else { 172 yt += 7 * scale; 173 } 174 } 175 176 t.x = xt; 177 t.y = yt; 178 179 xt += t.w + 7 * scale; 180 181 if (previous is ZoomBar) { 182 content_height += 7 * scale; 183 } 184 185 previous = t; 186 first_row = false; 187 } 188 } 189 } 190 } 191 192 public void set_scroll (double scroll) { 193 this.scroll = scroll; 194 } 195 196 public void set_offset (double ty) { 197 y = ty; 198 update_tool_position (); 199 } 200 201 public void redraw () { 202 cached = null; 203 Toolbox.redraw_tool_box (); 204 } 205 206 public void add_tool (Tool t, int position = -1) { 207 if (position < 0) { 208 tool.add (t); 209 } else { 210 return_if_fail (position <= tool.size); 211 tool.insert (position, t); 212 } 213 214 t.redraw_tool.connect (() => { 215 cached = null; 216 }); 217 218 update_tool_position (); 219 220 t.select_action.connect ((selected) => { 221 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin)); 222 223 if (is_unique ()) { 224 foreach (var deselected in tool) { 225 if (selected.get_id () != deselected.get_id ()) { 226 deselected.set_selected (false); 227 } 228 } 229 } 230 231 if (!selected.new_selection && selected.persistent) { 232 if (is_persistent ()) { 233 selected.set_selected (true); 234 } else { 235 selected.set_selected (false); 236 } 237 } 238 239 if (!is_persistent () && !selected.persistent) { 240 var time = new TimeoutSource(200); 241 time.set_callback(() => { 242 selected.set_selected (false); 243 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin)); 244 return false; 245 }); 246 time.attach(null); 247 } 248 249 selected.new_selection = false; 250 }); 251 } 252 253 public bool is_over (double xp, double yp) { 254 double yt = y + scroll + 2; 255 return yt - 7 <= yp <= yt + 7 && xp < 17; 256 } 257 258 public bool set_active (bool a) { 259 bool r = (active != a); 260 opacity = (a) ? 1 : 0; 261 active = a; 262 return r; 263 } 264 265 public void draw (Context cr) { 266 Surface cache; 267 268 if (unlikely (cached == null)) { 269 Context cc; 270 271 double text_height = 17 * Toolbox.get_scale (); 272 double offset_y = 0; 273 274 cache = new Surface.similar (cr.get_target (), Cairo.Content.COLOR_ALPHA, Toolbox.allocation_width, (int) (h + content_height)); 275 cc = new Context (cache); 276 277 if (tool.size > 0 && headline != null) { 278 Theme.text_color (title, "Text Tool Box"); 279 title.set_font_size (text_height); 280 title.draw_at_top (cc, x, 0); 281 offset_y = text_height + HEADLINE_MARGIN; 282 } 283 284 draw_content (cc, offset_y); 285 cached = (!) cache; 286 } 287 288 if (cached != null) { 289 cache = (!) cached; 290 cr.save (); 291 cr.set_antialias (Cairo.Antialias.NONE); 292 cr.set_source_surface (cache, 0, (int) (y + scroll)); 293 cr.paint (); 294 cr.restore (); 295 } 296 } 297 298 public void draw_content (Context cr, double text_end) { 299 double offset_y = 0; 300 double offset_x = 0; 301 302 update_tool_position (); //FIXME 303 304 if (tool.size > 0) { 305 offset_x = tool.get (0).x; 306 offset_y = tool.get (0).y - text_end; 307 } 308 309 cr.save (); 310 foreach (Tool t in tool) { 311 if (t.tool_is_visible ()) { 312 t.draw_tool (cr, offset_x - x, offset_y); 313 } 314 } 315 cr.restore (); 316 } 317 318 } 319 320 } 321