The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

OverViewItem.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/OverViewItem.vala.
Remove unused variables
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 [CCode (cname = "draw_overview_glyph")] 19 public extern bool draw_overview_glyph (Context context, string font_file, double width, double height, unichar character); 20 21 namespace BirdFont { 22 23 public class OverViewItem : GLib.Object { 24 public unichar character = '\0'; 25 public GlyphCollection? glyphs; 26 public double x; 27 public double y; 28 public bool selected = false; 29 public CharacterInfo info; 30 31 public static double DEFAULT_WIDTH = 100; 32 public static double DEFAULT_HEIGHT = 130; 33 public static double DEFAULT_MARGIN = 20; 34 35 public static double width = 100; 36 public static double height = 130; 37 public static double margin = 20; 38 39 public static double glyph_scale = 1.0; 40 41 public VersionList version_menu; 42 Text label; 43 44 private Surface? cache = null; 45 46 public static Surface? label_background = null; 47 public static Surface? selected_label_background = null; 48 public static Surface? label_background_no_menu = null; 49 public static Surface? selected_label_background_no_menu = null; 50 51 public OverViewItem () { 52 } 53 54 public void set_character (unichar character) { 55 this.character = character; 56 } 57 58 public void set_glyphs (GlyphCollection? gc) { 59 glyphs = gc; 60 } 61 62 public void generate_graphics () { 63 if (glyphs != null) { 64 version_menu = new VersionList ((!) glyphs); 65 version_menu.add_glyph_item.connect ((glyph) => { 66 ((!) glyphs).insert_glyph (glyph, true); 67 }); 68 69 version_menu.signal_delete_item.connect ((glyph_index) => { 70 OverView v = MainWindow.get_overview (); 71 version_menu = new VersionList ((!) glyphs); 72 v.update_item_list (); 73 GlyphCanvas.redraw (); 74 }); 75 } 76 77 info = new CharacterInfo (character, glyphs); 78 79 if (glyphs == null) { 80 label = new Text (); 81 } else { 82 label = new Text ((!) character.to_string (), 17); 83 truncate_label (); 84 } 85 86 draw_background (); 87 } 88 89 public void draw_glyph_from_font () { 90 if (glyphs == null) { 91 return; 92 } 93 94 Glyph g; 95 Font font; 96 double gx, gy; 97 double x1, x2, y1, y2; 98 double scale_box; 99 double w, h; 100 double glyph_width, glyph_height; 101 Surface s; 102 Context c; 103 Color color = Color.black (); 104 105 g = ((!) glyphs).get_current (); 106 107 if (g.overview_thumbnail != null) { 108 cache = g.overview_thumbnail; 109 return; 110 } 111 112 w = width; 113 h = height; 114 115 scale_box = width / DEFAULT_WIDTH; 116 117 s = Screen.create_background_surface ((int) width, (int) height - 20); 118 c = new Context (s); 119 120 c.save (); 121 g.boundaries (out x1, out y1, out x2, out y2); 122 123 if (g.color_svg_data != null) { 124 font = BirdFont.get_current_font (); 125 glyph_width = g.right_limit - g.left_limit; 126 glyph_height = font.top_position - font.bottom_position; 127 } else { 128 glyph_width = x2 - x1; 129 glyph_height = y2 - y1; 130 } 131 132 c.save (); 133 c.scale (glyph_scale * Screen.get_scale (), glyph_scale * Screen.get_scale ()); 134 135 g.add_help_lines (); 136 137 if (g.color_svg_data != null) { 138 gx = 10; 139 gy = (h / glyph_scale) - 25 / glyph_scale; 140 c.translate (gx - Glyph.xc () - g.get_lsb (), g.get_baseline () + gy - Glyph.yc ()); 141 g.draw_svg (c); 142 } else { 143 gx = ((w / glyph_scale) - glyph_width) / 2 - g.get_left_side_bearing (); 144 gy = (h / glyph_scale) - 25 / glyph_scale; 145 c.translate (gx - Glyph.xc () - g.get_lsb (), g.get_baseline () + gy - Glyph.yc ()); 146 g.draw_paths (c, color); 147 } 148 149 c.restore (); 150 151 cache = s; 152 GlyphCanvas.redraw (); 153 } 154 155 public void draw_background () { 156 Glyph g; 157 Font font; 158 double gx, gy; 159 double x1, x2, y1, y2; 160 double scale_box; 161 double w, h; 162 double glyph_width, glyph_height; 163 Surface s; 164 Context c; 165 Color color = Color.black (); 166 167 w = width; 168 h = height; 169 170 scale_box = width / DEFAULT_WIDTH; 171 172 s = Screen.create_background_surface ((int) width, (int) height - 20); 173 c = new Context (s); 174 175 if (glyphs != null) { // FIXME: lock 176 draw_glyph_from_font (); 177 } else { 178 c.scale (Screen.get_scale (), Screen.get_scale ()); 179 180 c.save (); 181 182 bool glyph_found; 183 string? font_file; 184 185 Theme.color (c, "Overview Glyph"); 186 187 font_file = FontCache.fallback_font.get_default_font_file (); 188 glyph_found = draw_overview_glyph (c, (!) font_file, width, height, character); 189 190 if (!glyph_found) { 191 font_file = find_font (FallbackFont.font_config, (!) character.to_string ()); 192 193 if (font_file != null) { 194 string path = (!) font_file; 195 196 if (!path.has_suffix("LastResort.ttf")) { 197 draw_overview_glyph (c, path, width, height, character); 198 } 199 } 200 } 201 202 c.restore (); 203 204 cache = s; 205 GlyphCanvas.redraw (); 206 } 207 } 208 209 public static void reset_label () { 210 label_background = null; 211 selected_label_background = null; 212 } 213 214 void truncate_label () { 215 double w = has_icons () ? width - 43 : width; 216 label.truncate (w); 217 } 218 219 public string get_name () { 220 StringBuilder s; 221 222 if (glyphs != null) { 223 return ((!) glyphs).get_name (); 224 } 225 226 s = new StringBuilder (); 227 s.append_unichar (character); 228 229 return s.str; 230 } 231 232 public void set_selected (bool s) { 233 selected = s; 234 } 235 236 public static double full_width () { 237 return width + margin; 238 } 239 240 public static double full_height () { 241 return height + margin; 242 } 243 244 public bool click (uint button, double px, double py) { 245 bool a; 246 GlyphCollection g; 247 bool s = (x <= px <= x + width) && (y <= py <= y + height); 248 249 if (has_icons () && glyphs != null) { 250 g = (!) glyphs; 251 version_menu.set_position (x + width - 21, y + height - 18); 252 a = version_menu.menu_item_action (px, py); // select one item on the menu 253 254 if (a) { 255 return s; 256 } 257 258 version_menu.menu_icon_action (px, py); // click in the open menu 259 } 260 261 info.set_position (x + width - 17, y + height - 22.5); 262 if (has_icons () && info.is_over_icon (px, py)) { 263 MainWindow.get_overview ().set_character_info (info); 264 } 265 266 return s; 267 } 268 269 public bool double_click (uint button, double px, double py) { 270 selected = (x <= px <= x + width) && (y <= py <= y + height); 271 return selected; 272 } 273 274 public bool is_on_screen (WidgetAllocation allocation) { 275 return y + height > 0 && y < allocation.height; 276 } 277 278 public void draw (WidgetAllocation allocation, Context cr) { 279 if (!is_on_screen (allocation)) { 280 return; 281 } 282 283 cr.save (); 284 Theme.color (cr, "Background 1"); 285 cr.rectangle (x, y, width, height); 286 cr.fill (); 287 cr.restore (); 288 289 cr.save (); 290 Theme.color (cr, "Overview Item Border"); 291 cr.rectangle (x, y, width, height); 292 cr.set_line_width (1); 293 cr.stroke (); 294 cr.restore (); 295 296 draw_thumbnail (cr, x, y + height); 297 draw_caption (cr); 298 draw_menu (cr); 299 } 300 301 public void adjust_scale () { 302 double x1, x2, y1, y2, glyph_width, glyph_height, scale, gx; 303 Glyph g; 304 Font font; 305 306 if (glyphs != null) { 307 font = BirdFont.get_current_font (); 308 g = ((!) glyphs).get_current (); 309 310 if (g.boundaries (out x1, out y1, out x2, out y2)) { 311 glyph_width = x2 - x1; 312 glyph_height = y2 - y1; 313 314 if (glyph_scale == 1) { 315 // caption height is 20 316 glyph_scale = (height - 20) / (font.top_limit - font.bottom_limit); 317 } 318 319 scale = glyph_scale; 320 gx = ((width / scale) - glyph_width) / 2; 321 322 if (gx < 0) { 323 glyph_scale = 1 + 2 * gx / width; 324 } 325 } 326 } 327 } 328 329 private void draw_thumbnail (Context cr, double x, double y) { 330 if (cache != null) { 331 cr.save (); 332 cr.set_antialias (Cairo.Antialias.NONE); 333 cr.scale (1 / Screen.get_scale (), 1 / Screen.get_scale ()); 334 cr.set_source_surface ((!) cache, (int) (x * Screen.get_scale ()), (int) ((y - height)) * Screen.get_scale ()); 335 cr.paint (); 336 cr.restore (); 337 } 338 } 339 340 public bool has_icons () { 341 return width > 50; 342 } 343 344 public void draw_caption (Context cr) { 345 draw_label_background (cr); 346 347 cr.save (); 348 349 if (glyphs != null) { 350 if (selected) { 351 Theme.text_color (label, "Overview Selected Foreground"); 352 } else { 353 Theme.text_color (label, "Overview Foreground"); 354 } 355 356 label.draw_at_baseline (cr, x + 0.08 * width, y + height - 6); 357 } 358 359 cr.restore (); 360 } 361 362 public void create_label_background_cache (Context cr) { 363 Context cc; 364 Cairo.Pattern p; 365 Surface cache; 366 367 // unselected item 368 cache = Screen.create_background_surface ((int) width + 1, 20); 369 cc = new Context (cache); 370 cc.scale(Screen.get_scale(), Screen.get_scale()); 371 372 cc.rectangle (0, 0, width, 20 - 1); 373 p = new Cairo.Pattern.linear (0.0, 0, 0.0, 20); 374 Theme.gradient (p, "Overview Item 1", "Overview Item 2"); 375 cc.set_source (p); 376 377 cc.fill (); 378 379 if (has_icons ()) { 380 draw_menu_icon (cc, false); 381 draw_character_info_icon (cc); 382 } 383 384 label_background = (!) cache; 385 386 // selected item 387 cache = Screen.create_background_surface ((int) width + 1, 20); 388 cc = new Context (cache); 389 cc.scale(Screen.get_scale(), Screen.get_scale()); 390 391 cc.rectangle (0, 0, width, 20 - 1); 392 393 Theme.color (cc, "Selected Overview Item"); 394 395 cc.fill (); 396 397 if (has_icons ()) { 398 draw_menu_icon (cc, true); 399 draw_character_info_icon (cc); 400 } 401 402 selected_label_background = (!) cache; 403 404 // deselected item without menu icon 405 cache = Screen.create_background_surface ((int) width, 20); 406 cc = new Context (cache); 407 cc.scale(Screen.get_scale(), Screen.get_scale()); 408 cc.rectangle (0, 0, width - 1, 20 - 1); 409 p = new Cairo.Pattern.linear (0.0, 0, 0.0, 20); 410 Theme.gradient (p, "Overview Item 1", "Overview Item 2"); 411 cc.set_source (p); 412 cc.fill (); 413 414 if (has_icons ()) { 415 draw_character_info_icon (cc); 416 } 417 418 label_background_no_menu = (!) cache; 419 420 // selected item 421 cache = Screen.create_background_surface ((int) width + 1, 20); 422 cc = new Context (cache); 423 cc.scale(Screen.get_scale(), Screen.get_scale()); 424 cc.rectangle (0, 0, width, 20 - 1); 425 Theme.color (cc, "Selected Overview Item"); 426 cc.fill (); 427 428 if (has_icons ()) { 429 draw_character_info_icon (cc); 430 } 431 432 selected_label_background_no_menu = (!) cache; 433 } 434 435 bool has_menu () { 436 return glyphs != null; 437 } 438 439 public void draw_label_background (Context cr) { 440 Surface cache; 441 bool icon; 442 443 if (unlikely (label_background == null)) { 444 create_label_background_cache (cr); 445 } 446 447 if (label_background != null 448 && selected_label_background != null 449 && label_background_no_menu != null 450 && selected_label_background_no_menu != null) { 451 452 icon = has_menu (); 453 if (selected && icon) { 454 cache = (!) selected_label_background; 455 } else if (!selected && icon) { 456 cache = (!) label_background; 457 } else if (selected && !icon) { 458 cache = (!) selected_label_background_no_menu; 459 } else { 460 cache = (!) label_background_no_menu; 461 } 462 463 Screen.paint_background_surface (cr, cache, (int) x, (int) (y + height - 19)); 464 } 465 } 466 467 private void draw_character_info_icon (Context cr) { 468 info.draw_icon (cr, selected, width - 17, -1.5); 469 } 470 471 public void hide_menu () { 472 if (!is_null (version_menu)) { 473 version_menu.menu_visible = false; 474 } 475 } 476 477 private void draw_menu_icon (Context cc, bool selected) { 478 Text icon; 479 480 icon = new Text ("dropdown_menu", 17); 481 icon.load_font ("icons.bf"); 482 483 if (selected) { 484 Theme.text_color (icon, "Overview Selected Foreground"); 485 } else { 486 Theme.text_color (icon, "Overview Foreground"); 487 } 488 489 icon.draw_at_top (cc, width - 32, 0); 490 } 491 492 private void draw_menu (Context cr) { 493 if (glyphs == null || !version_menu.menu_visible) { 494 return; 495 } 496 497 version_menu.draw_menu (cr); 498 } 499 } 500 501 } 502