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.
Update font name in toolbox
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 if (t is LayerLabel) { 128 t.w = Toolbox.allocation_width * scale; 129 t.h = 21 * scale; 130 } else if (t is ColorPicker) { 131 t.w = Toolbox.allocation_width * scale; 132 t.h = 5 * ((ColorPicker) t).bar_height; 133 } else { 134 t.w = 33 * scale; 135 t.h = (33 / 1.11) * scale; 136 } 137 } 138 139 if (tool.size > 0) { 140 content_height = tool.get (0).h + margin_small; 141 } else { 142 content_height = 0; 143 } 144 145 if (headline != null && tool.size > 0) { 146 yt += 17 * scale + HEADLINE_MARGIN; 147 content_height += 17 * scale + HEADLINE_MARGIN; 148 } 149 150 if (tool.size > 0) { 151 previous = tool.get (0); 152 first_row = true; 153 foreach (Tool t in tool) { 154 if (t.tool_is_visible ()) { 155 new_row = xt + t.w > Toolbox.allocation_width - 7 * scale; 156 157 if (t is ZoomBar) { 158 t.x = xt; 159 t.y = yt; 160 yt += t.h + 7 * scale; 161 previous = t; 162 continue; 163 } 164 165 if (previous is ZoomBar) { 166 content_height += t.h; 167 } 168 169 if (new_row && !first_row) { 170 content_height += previous.h; 171 xt = x; 172 yt += previous.h; 173 174 if (!(t is LabelTool) && !(previous is LayerLabel)) { 175 yt += 7 * scale; 176 } 177 178 if (!(previous is LayerLabel)) { 179 content_height += margin_small; 180 } 181 } 182 183 t.x = xt; 184 t.y = yt; 185 186 xt += t.w + 7 * scale; 187 188 if (previous is ZoomBar) { 189 content_height += 7 * scale; 190 } 191 192 previous = t; 193 first_row = false; 194 } 195 } 196 197 content_height += 5 * scale; 198 } 199 200 if (unlikely (content_height < 0)) { 201 warning (@"content_height < 0"); 202 } 203 } 204 205 public void set_scroll (double scroll) { 206 this.scroll = scroll; 207 } 208 209 public void set_offset (double ty) { 210 y = ty; 211 update_tool_position (); 212 } 213 214 public void redraw () { 215 cached = null; 216 Toolbox.redraw_tool_box (); 217 } 218 219 public void add_tool (Tool t, int position = -1) { 220 if (position < 0) { 221 tool.add (t); 222 } else { 223 return_if_fail (position <= tool.size); 224 tool.insert (position, t); 225 } 226 227 t.redraw_tool.connect (() => { 228 cached = null; 229 }); 230 231 update_tool_position (); 232 233 t.select_action.connect ((selected) => { 234 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin)); 235 236 if (is_unique ()) { 237 foreach (var deselected in tool) { 238 if (selected.get_id () != deselected.get_id ()) { 239 deselected.set_selected (false); 240 } 241 } 242 } 243 244 if (!selected.new_selection && selected.persistent) { 245 if (is_persistent ()) { 246 selected.set_selected (true); 247 } else { 248 selected.set_selected (false); 249 } 250 } 251 252 // FIXME: delete 253 /* 254 if (!is_persistent () && !selected.persistent) { 255 var time = new TimeoutSource(200); 256 time.set_callback(() => { 257 selected.set_selected (false); 258 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin)); 259 return false; 260 }); 261 time.attach(null); 262 }*/ 263 264 selected.new_selection = false; 265 }); 266 } 267 268 public bool is_over (double xp, double yp) { 269 double yt = y + scroll + 2; 270 return yt - 7 <= yp <= yt + 7 && xp < 17; 271 } 272 273 public bool set_active (bool a) { 274 bool r = (active != a); 275 opacity = (a) ? 1 : 0; 276 active = a; 277 return r; 278 } 279 280 public void draw (Context cr) { 281 Surface cache; 282 283 if (unlikely (cached == null)) { 284 Context cc; 285 double text_height = 17 * Toolbox.get_scale (); 286 double offset_y = 0; 287 288 cache = new Surface.similar (cr.get_target (), Cairo.Content.COLOR_ALPHA, Toolbox.allocation_width, (int) (h + content_height)); 289 cc = new Context (cache); 290 291 if (tool.size > 0 && headline != null) { 292 Theme.text_color (title, "Text Tool Box"); 293 title.set_font_size (text_height); 294 title.draw_at_top (cc, x, 0); 295 offset_y = text_height + HEADLINE_MARGIN; 296 } 297 298 draw_content (cc, offset_y); 299 cached = (!) cache; 300 } 301 302 if (cached != null) { 303 cache = (!) cached; 304 cr.save (); 305 cr.set_antialias (Cairo.Antialias.NONE); 306 307 cr.set_source_surface (cache, 0, (int) (y + scroll)); 308 cr.paint (); 309 cr.restore (); 310 } 311 } 312 313 public void draw_content (Context cr, double text_end) { 314 double offset_y = 0; 315 double offset_x = 0; 316 317 update_tool_position (); 318 319 if (tool.size > 0) { 320 offset_x = tool.get (0).x; 321 offset_y = tool.get (0).y - text_end; 322 } 323 324 cr.save (); 325 foreach (Tool t in tool) { 326 if (t.tool_is_visible ()) { 327 t.draw_tool (cr, offset_x - x, offset_y); 328 } 329 } 330 cr.restore (); 331 } 332 333 } 334 335 } 336