Commit 098a15a
Copy and paste glyphs in overview tab
Changed files (5)
modifiedlibbirdfont/ClipTool.valamodifiedlibbirdfont/ExportTool.valamodifiedlibbirdfont/GlyphCollection.valamodifiedlibbirdfont/OverView.valamodifiedlibbirdfont/OverViewItem.vala
Diff
@@ -28,7 +28,25 @@ public class ClipTool : Tool { data = svg_data + bf_data; MainWindow.native_window.set_clipboard (data); MainWindow.native_window.set_inkscape_clipboard (data);- } + }+ + if (fd is OverView) {+ MainWindow.get_overview ().copy ();+ } + }++ /** Copy entire glyph. */+ public static void copy_glyph (Glyph glyph) {+ string svg_data;+ string bf_data;+ string data;+ + svg_data = ExportTool.export_to_inkscape_clipboard (glyph, false);+ bf_data = export_paths_to_birdfont_clipboard (glyph, false);+ + data = svg_data + bf_data;+ MainWindow.native_window.set_clipboard (data);+ MainWindow.native_window.set_inkscape_clipboard (data); } public static void paste_in_place () {@@ -58,6 +76,10 @@ public class ClipTool : Tool { if (fd is KerningDisplay) { paste_letters_to_kerning_tab (); }+ + if (fd is OverView) {+ MainWindow.get_overview ().paste ();+ } } static void paste_paths (bool paste_guide_lines) {@@ -95,11 +117,14 @@ public class ClipTool : Tool { SvgParser.import_svg_data (data); } - ((!)destination).update_view (); + ((!)destination).update_view (); } static string export_selected_paths_to_birdfont_clipboard () {- Glyph glyph = MainWindow.get_current_glyph ();+ return export_paths_to_birdfont_clipboard (MainWindow.get_current_glyph (), true);+ }+ + static string export_paths_to_birdfont_clipboard (Glyph glyph, bool selected = false) { StringBuilder s = new StringBuilder (); Path new_path; List<Path> paths = new List<Path> ();@@ -115,7 +140,13 @@ public class ClipTool : Tool { s.append (@"$(glyph.right_limit)"); s.append ("\n"); - if (glyph.path_list.size > 0) {+ if (!selected) {+ foreach (Path path in glyph.path_list) {+ s.append ("BF path: ");+ s.append (BirdFontFile.get_point_data (path));+ s.append ("\n");+ }+ } else if (glyph.path_list.size > 0) { foreach (Path path in glyph.active_paths) { s.append ("BF path: "); s.append (BirdFontFile.get_point_data (path));@@ -28,7 +28,10 @@ public class ExportTool : GLib.Object { } public static string export_current_glyph_to_string (bool only_selected_paths = false) {- Glyph glyph = MainWindow.get_current_glyph ();+ return export_to_string (MainWindow.get_current_glyph (), only_selected_paths);+ }++ public static string export_to_string (Glyph glyph, bool only_selected_paths) { string name; StringBuilder s; @@ -49,7 +52,7 @@ public class ExportTool : GLib.Object { s.append (@"<g id=\"$(name)\">\n"); - s.append (get_svg_path_elements (only_selected_paths));+ s.append (get_svg_path_elements (glyph, only_selected_paths)); s.append ("</g>\n"); s.append ("</svg>");@@ -58,6 +61,10 @@ public class ExportTool : GLib.Object { } public static string export_current_glyph_to_inkscape_clipboard (bool only_selected_paths = false) {+ return export_to_inkscape_clipboard (MainWindow.get_current_glyph (), only_selected_paths);+ }+ + public static string export_to_inkscape_clipboard (Glyph glyph, bool only_selected_paths = false) { StringBuilder s; s = new StringBuilder ();@@ -72,14 +79,13 @@ public class ExportTool : GLib.Object { max="0,0" /> """); - s.append (get_svg_path_elements (only_selected_paths));+ s.append (get_svg_path_elements (glyph, only_selected_paths)); s.append ("</svg>"); return s.str; } - private static string get_svg_path_elements (bool only_selected_paths) {- Glyph glyph = MainWindow.get_current_glyph ();+ private static string get_svg_path_elements (Glyph glyph, bool only_selected_paths) { string glyph_svg; StringBuilder s; string name;@@ -51,6 +51,10 @@ public class GlyphCollection : GLib.Object { return unicode.str; } + public void set_unicode_character (unichar c) {+ unicode_character = c;+ }+ public unichar get_unicode_character () { return unicode_character; }@@ -1,5 +1,5 @@ /*- Copyright (C) 2012 Johan Mattsson+ Copyright (C) 2012 2014 Johan Mattsson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -21,6 +21,10 @@ public class OverView : FontDisplay { public WidgetAllocation allocation = new WidgetAllocation (); OverViewItem selected_item = new OverViewItem (null, '\0', 0, 0);++ Gee.ArrayList<GlyphCollection> copied_glyphs = new Gee.ArrayList<GlyphCollection> ();+ Gee.ArrayList<GlyphCollection> selected_items = new Gee.ArrayList<GlyphCollection> (); + int selected = 0; int first_visible = 0; int rows = 0;@@ -38,7 +42,7 @@ public class OverView : FontDisplay { Gee.ArrayList<OverViewItem> visible_items = new Gee.ArrayList<OverViewItem> (); /** List for undo commands. */- Gee.ArrayList<GlyphCollection> deleted_glyphs = new Gee.ArrayList<GlyphCollection> ();+ Gee.ArrayList<OverViewUndoItem> undo_items = new Gee.ArrayList<OverViewUndoItem> (); /** Show all characters that has been drawn. */ bool all_available = true;@@ -87,24 +91,13 @@ public class OverView : FontDisplay { selected = tabs.select_char (name.str); if (!selected) {- if (all_available) {- fg = font.get_glyph_collection_by_name (name.str);- } else {- fg = font.get_glyph_collection (name.str);- }-- if (fg != null) {- glyph_collection = (!) fg;- glyph = glyph_collection.get_current ();- } else {- glyph_collection = new GlyphCollection (character, name.str);- glyph = new Glyph (name.str, character);- glyph_collection.insert_glyph (glyph, true);- font.add_glyph_collection (glyph_collection);- }+ glyph_collection = add_character_to_font (character); + glyph = glyph_collection.get_current (); tabs.add_tab (glyph); + selected_items.add (glyph_collection);+ canvas = MainWindow.get_glyph_canvas (); canvas.set_current_glyph (glyph_collection.get_current ()); @@ -115,6 +108,43 @@ public class OverView : FontDisplay { update_scrollbar (); } + public GlyphCollection add_empty_character_to_font (unichar character) {+ return add_character_to_font (character, true);+ }+ + public GlyphCollection add_character_to_font (unichar character, bool empty = false) {+ StringBuilder name = new StringBuilder ();+ TabBar tabs = MainWindow.get_tab_bar ();+ Font font = BirdFont.get_current_font ();+ GlyphCollection? fg;+ Glyph glyph;+ GlyphCollection glyph_collection;+ GlyphCanvas canvas;+ + name.append_unichar (character);++ if (all_available) {+ fg = font.get_glyph_collection_by_name (name.str);+ } else {+ fg = font.get_glyph_collection (name.str);+ }++ if (fg != null) {+ glyph_collection = (!) fg;+ } else {+ glyph_collection = new GlyphCollection (character, name.str);+ + if (!empty) {+ glyph = new Glyph (name.str, character);+ glyph_collection.insert_glyph (glyph, true);+ }+ + font.add_glyph_collection (glyph_collection);+ }+ + return glyph_collection;+ }+ public static void search () { OverView ow = MainWindow.get_overview (); TextListener listener = new TextListener (t_("Search"), ow.search_query, t_("Filter"));@@ -284,7 +314,7 @@ public class OverView : FontDisplay { return i - 1; } - void update_item_list () {+ void update_item_list (int item_list_length = -1) { string character_string; Font f = BirdFont.get_current_font (); GlyphCollection? glyphs = null;@@ -298,15 +328,18 @@ public class OverView : FontDisplay { items_per_row = get_items_per_row (); rows = (int) (allocation.height / OverViewItem.full_height ()) + 2; - visible_items.clear ();+ if (item_list_length == -1) {+ item_list_length = items_per_row * rows;+ } + visible_items.clear (); visible_items = new Gee.ArrayList<OverViewItem> (); // update item list index = (uint32) first_visible; x = OverViewItem.margin; y = OverViewItem.margin;- for (int i = 0; i < items_per_row * rows; i++) {+ for (int i = 0; i < item_list_length; i++) { if (all_available) { if (! (0 <= index < f.length ())) { break;@@ -338,6 +371,10 @@ public class OverView : FontDisplay { item.selected = (i == selected); + if (glyphs != null) {+ item.selected |= selected_items.index_of ((!) glyphs) != -1;+ }+ visible_items.add (item); index++; }@@ -658,27 +695,35 @@ public class OverView : FontDisplay { public override void undo () { Font font = BirdFont.get_current_font ();- GlyphCollection previous_collection;+ OverViewUndoItem previous_collection; - if (deleted_glyphs.size == 0) {+ if (undo_items.size == 0) { return; } - previous_collection = deleted_glyphs.get (deleted_glyphs.size - 1);+ previous_collection = undo_items.get (undo_items.size - 1); // remove the old glyph and add the new one- font.delete_glyph (previous_collection);- font.add_glyph_collection (previous_collection);+ foreach (GlyphCollection g in previous_collection.glyphs) {+ font.delete_glyph (g);+ font.add_glyph_collection (g);+ } - deleted_glyphs.remove_at (deleted_glyphs.size - 1);+ undo_items.remove_at (undo_items.size - 1); redraw_area (0, 0, allocation.width, allocation.height); } public void store_undo_state (GlyphCollection gc) {- deleted_glyphs.add (gc);+ OverViewUndoItem i = new OverViewUndoItem ();+ i.glyphs.add (gc);+ store_undo_items (i); } + public void store_undo_items (OverViewUndoItem i) {+ undo_items.add (i);+ }+ bool select_visible_character (unichar c) { int i = 0; @@ -787,8 +832,31 @@ public class OverView : FontDisplay { character_info = i; } + public int get_selected_index () {+ GlyphCollection gc;+ int index = 0;+ + if (selected_items.size == 0) {+ return 0;+ }+ + gc = selected_items.get (0);+ + foreach (OverViewItem i in visible_items) {+ + if (i.glyphs != null && gc == ((!) i.glyphs)) {+ break;+ }+ + index++;+ }+ + return index;+ }+ public override void button_press (uint button, double x, double y) { int index = 0;+ int selected_index = -1; if (character_info != null) { character_info = null;@@ -800,11 +868,31 @@ public class OverView : FontDisplay { if (i.click (button, x, y)) { selected = index; selected_item = get_selected_item ();+ + if (KeyBindings.has_shift ()) {+ if (selected_item.glyphs != null) {+ + selected_index = selected_items.index_of ((!) selected_item.glyphs);+ if (selected_index == -1) {+ selected_items.add ((!) selected_item.glyphs);+ } else {+ return_if_fail (0 <= selected_index < selected_items.size);+ selected_items.remove_at (selected_index);+ selected = get_selected_index ();+ selected_item = get_selected_item ();+ }+ }+ } else {+ selected_items.clear ();+ if (selected_item.glyphs != null) {+ selected_items.add ((!) selected_item.glyphs);+ }+ } }- index++; } + update_item_list (); redraw_area (0, 0, allocation.width, allocation.height); } @@ -975,6 +1063,100 @@ public class OverView : FontDisplay { cr.show_text (line); cr.restore (); }+ + public void copy () {+ copied_glyphs.clear ();+ + foreach (GlyphCollection gc in selected_items) {+ copied_glyphs.add (gc.copy ());+ }+ + if (copied_glyphs.size != 0) {+ ClipTool.copy_glyph (selected_items.get (copied_glyphs.size - 1).get_current ());+ }+ }+ + public void paste () {+ GlyphCollection gc = new GlyphCollection ('\0', "");+ GlyphCollection? c;+ Glyph glyph;+ uint32 index;+ int i;+ int skip = 0;+ string character_string;+ Gee.ArrayList<GlyphCollection> glyps = new Gee.ArrayList<GlyphCollection> ();+ Font f = BirdFont.get_current_font ();+ OverViewUndoItem undo_item;+ + copied_glyphs.sort ((a, b) => {+ return (int) ((GlyphCollection) a).get_unicode_character () + - (int) ((GlyphCollection) b).get_unicode_character ();+ });+ + // FIXME: copy and paste to unicode character + 1 + + index = (uint32) first_visible + selected;+ for (i = 0; i < copied_glyphs.size; i++) {+ if (all_available) {+ if (f.length () == 0) {+ c = add_empty_character_to_font (+ glyps.get (i).get_unicode_character ()); + } else if (index >= f.length ()) {+ c = add_empty_character_to_font (+ ((!)f.get_glyph_collection_indice (f.length () - 1)).get_unicode_character () + i);+ } else {+ c = f.get_glyph_collection_indice ((uint32) index);+ }+ + if (c == null) {+ c = add_empty_character_to_font (copied_glyphs.get (i).get_unicode_character ());+ }+ + return_if_fail (c != null);+ gc = (!) c; + } else { + if (i != 0) {+ skip = (int) copied_glyphs.get (i).get_unicode_character ();+ skip -= (int) copied_glyphs.get (i - 1).get_unicode_character ();+ skip -= 1;+ }+ + character_string = glyph_range.get_char ((uint32) (index + skip));+ c = f.get_glyph_collection_by_name (character_string);+ + if (c == null) {+ gc = add_empty_character_to_font (character_string.get_char ());+ } else {+ gc = (!) c;+ }+ }+ + glyps.add (gc);+ index++;+ }++ undo_item = new OverViewUndoItem ();+ foreach (GlyphCollection g in glyps) {+ undo_item.glyphs.add (g.copy ());+ }+ store_undo_items (undo_item);+ + i = 0;+ foreach (GlyphCollection g in glyps) {+ glyph = copied_glyphs.get (i).get_current ().copy ();+ glyph.version_id = (glyph.version_id == -1 || g.length () == 0) ? 1 : g.get_last_id () + 1;+ glyph.unichar_code = g.get_unicode_character ();+ glyph.name = (!) glyph.unichar_code.to_string ();+ g.insert_glyph (glyph, true);+ i++;+ }+ + f.touch ();+ }+ + public class OverViewUndoItem {+ public Gee.ArrayList<GlyphCollection> glyphs = new Gee.ArrayList<GlyphCollection> ();+ } } }@@ -18,7 +18,7 @@ using Math; namespace BirdFont { public class OverViewItem : GLib.Object {- public unichar character = 'A'; // FIXME: + public unichar character = 'A'; public GlyphCollection? glyphs; public double x; public double y;@@ -41,6 +41,10 @@ public class OverViewItem : GLib.Object { this.info = new CharacterInfo (character); } + public void set_selected (bool s) {+ selected = s;+ }+ public static double full_width () { return width + margin; }@@ -52,13 +56,13 @@ public class OverViewItem : GLib.Object { public bool click (uint button, double px, double py) { bool a; GlyphCollection g;- selected = (x <= px <= x + width) && (y <= py <= y + height);+ bool s = (x <= px <= x + width) && (y <= py <= y + height); if (has_icons () && glyphs != null) { g = (!) glyphs; a = g.get_version_list ().menu_item_action (px, py); // select one item on the menu if (a) {- return selected;+ return s; } g.get_version_list ().menu_icon_action (px, py); // click in the open menu@@ -68,7 +72,7 @@ public class OverViewItem : GLib.Object { MainWindow.get_overview ().set_character_info (info); } - return selected;+ return s; } public void double_click (uint button, double px, double py) {