The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

VersionList.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/VersionList.vala.
Fix memory leak
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 using Math; 17 18 namespace BirdFont { 19 20 public class VersionList : DropMenu { 21 public int current_version_id = -1; 22 unowned GlyphCollection glyph_collection; 23 24 public Gee.ArrayList<Glyph> glyphs; 25 26 public VersionList (Glyph? g = null, GlyphCollection glyph_collection) { 27 base (); 28 29 this.glyph_collection = glyph_collection; 30 glyphs = new Gee.ArrayList<Glyph> (); 31 set_direction (MenuDirection.POP_UP); 32 33 MenuAction ma = add_item (t_("New version")); 34 ma.has_delete_button = false; 35 ma.action = (self) => { 36 return_if_fail (self.parent != null); 37 return_if_fail (glyphs.size > 0); 38 39 BirdFont.get_current_font ().touch (); 40 41 add_new_version (); 42 current_version_id = glyphs.get (glyphs.size - 1).version_id; 43 }; 44 45 // delete one version 46 signal_delete_item.connect ((index) => { 47 delete_item (index); 48 }); 49 50 if (g != null) { 51 add_glyph ((!) g); 52 } 53 54 } 55 56 private void delete_item (int index) { 57 int current_version; 58 Font font = BirdFont.get_current_font (); 59 OverView over_view = MainWindow.get_overview (); 60 61 font.touch (); 62 63 index--; // first item is the add new action 64 65 // delete the entire glyph if the last remaining version is removed 66 if (glyphs.size == 1) { 67 over_view.store_undo_state (glyph_collection.copy ()); 68 font.delete_glyph (glyph_collection); 69 return; 70 } 71 72 return_if_fail (0 <= index < glyphs.size); 73 74 font.deleted_glyphs.add (glyph_collection.get_current ()); 75 76 over_view.store_undo_state (glyph_collection.copy ()); 77 78 glyphs.remove_at (index); 79 80 recreate_index (); 81 82 current_version = get_current_version_index (); 83 if (index == current_version) { 84 set_selected_item (get_action_no2 ()); // select the first glyph if the current glyph is deleted 85 } else if (index < current_version) { 86 return_if_fail (0 <= current_version - 1 < glyphs.size); 87 current_version_id = glyphs.get (current_version - 1).version_id; 88 } 89 } 90 91 private int get_current_version_index () { 92 int i = 0; 93 foreach (Glyph g in glyphs) { 94 if (g.version_id == current_version_id) { 95 return i; 96 } 97 i++; 98 } 99 return i; 100 } 101 102 public void set_selected_version (int version_id) { 103 current_version_id = version_id; 104 update_selection (); 105 } 106 107 public Glyph get_current () { 108 Glyph? gl = null; 109 110 foreach (Glyph g in glyphs) { 111 if (g.version_id == current_version_id) { 112 return g; 113 } 114 } 115 116 if (unlikely (glyphs.size > 0)) { 117 warning (@"Can not find current glyph for id $current_version_id"); 118 gl = glyphs.get (glyphs.size - 1); 119 set_selected_version (((!) gl).version_id); 120 return (!) gl; 121 } 122 123 if (unlikely (glyphs.size == 0 && current_version_id == -1)) { 124 warning (@"No glyphs added to collection"); 125 gl = new Glyph.no_lines ("", '\0'); 126 } 127 128 return (!) gl; 129 } 130 131 public void add_new_version () { 132 Glyph g = get_current (); 133 Glyph new_version = g.copy (); 134 new_version.version_id = get_last_id () + 1; 135 add_glyph (new_version); 136 } 137 138 public int get_last_id () { 139 return_val_if_fail (glyphs.size > 0, 1); 140 return glyphs.get (glyphs.size - 1).version_id; 141 } 142 143 private void set_selected_item (MenuAction ma) { 144 int i = ma.index; 145 Glyph current_glyph; 146 Glyph g; 147 148 return_if_fail (0 <= i < glyphs.size); 149 g = glyphs.get (i); 150 151 current_version_id = g.version_id; 152 153 return_if_fail (ma.parent != null); 154 155 ((!)ma.parent).deselect_all (); 156 ma.set_selected (true); 157 158 reload_all_open_glyphs (); 159 160 if (!is_null (BirdFont.current_glyph_collection)) { 161 current_glyph = MainWindow.get_current_glyph (); 162 g.set_allocation (current_glyph.allocation); 163 g.set_default_zoom (); 164 } 165 } 166 167 /** Reload a glyph when a new version is selected. Updates the path 168 * in glyph view, not from disk but from the glyph table. 169 */ 170 void reload_all_open_glyphs () { 171 TabBar b; 172 Tab tab; 173 Tab? tn; 174 Glyph glyph; 175 Glyph updated_glyph; 176 Glyph? ug; 177 Font font = BirdFont.get_current_font (); 178 StringBuilder uni = new StringBuilder (); 179 180 if (is_null (MainWindow.get_tab_bar ())) { 181 return; 182 } 183 184 b = MainWindow.get_tab_bar (); 185 186 for (int i = 0; i < b.get_length (); i++) { 187 tn = b.get_nth (i); 188 189 if (tn == null) { 190 warning ("tab is null"); 191 return; 192 } 193 194 tab = (!) tn; 195 196 if (! (tab.get_display () is Glyph)) { 197 continue; 198 } 199 200 glyph = (Glyph) tab.get_display (); 201 uni.truncate (0); 202 uni.append_unichar (glyph.unichar_code); 203 ug = font.get_glyph (uni.str); 204 205 if (ug == null) { 206 return; 207 } 208 209 updated_glyph = (!) ug; 210 tab.set_display (updated_glyph); 211 updated_glyph.view_zoom = glyph.view_zoom; 212 updated_glyph.view_offset_x = glyph.view_offset_x; 213 updated_glyph.view_offset_y = glyph.view_offset_y; 214 } 215 } 216 217 public void add_glyph (Glyph new_version, bool selected = true) { 218 MenuAction ma; 219 int v; 220 221 v = new_version.version_id; 222 glyphs.add (new_version); 223 224 ma = add_item (t_("Version") + @" $v"); 225 ma.index = (int) glyphs.size - 1; 226 227 ma.action = (self) => { 228 Font font = BirdFont.get_current_font (); 229 set_selected_item (self); 230 font.touch (); 231 }; 232 233 if (selected) { 234 set_selected_item (ma); 235 } 236 237 update_selection (); 238 } 239 240 bool has_version (int id) { 241 foreach (Glyph g in glyphs) { 242 if (g.version_id == id) { 243 return true; 244 } 245 } 246 return false; 247 } 248 249 void update_selection () { 250 if (has_version (current_version_id)) { 251 set_selected_item (get_action_index (get_current_version_index () + 1)); // the first item is the "new version" 252 } 253 } 254 255 } 256 257 } 258