Skip to content

Commit

Permalink
Saving and loading akira through serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
albfan committed Dec 26, 2019
1 parent 7b8a284 commit c72e1ae
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 7 deletions.
8 changes: 6 additions & 2 deletions src/Lib/Canvas.vala
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ public class Akira.Lib.Canvas : Goo.Canvas {
select_effect = new Goo.CanvasRect (null, real_x, real_y, 0, 0,
"line-width", line_width,
"stroke-color", "#666", null);
select_effect.set_data<bool> ("ignore", true);

update_select_effect (target);

Expand All @@ -548,13 +549,15 @@ public class Akira.Lib.Canvas : Goo.Canvas {

for (int i = 0; i < 9; i++) {
var radius = i == 8 ? nob_size : 0;
nobs[i] = new Goo.CanvasRect (null, 0, 0, nob_size, nob_size,
var nob = new Goo.CanvasRect (null, 0, 0, nob_size, nob_size,
"line-width", line_width,
"radius-x", radius,
"radius-y", radius,
"stroke-color", "#41c9fd",
"fill-color", "#fff", null);
nobs[i].set ("parent", get_root_item ());
nob.set ("parent", get_root_item ());
nob.set_data<bool> ("ignore", true);
nobs[i] = nob;
}

update_nob_position (target);
Expand Down Expand Up @@ -642,6 +645,7 @@ public class Akira.Lib.Canvas : Goo.Canvas {
hover_effect = new Goo.CanvasRect (null, real_x, real_y, real_width, real_height,
"line-width", line_width,
"stroke-color", "#41c9fd", null);
hover_effect.set_data<bool> ("ignore", true);
var transform = Cairo.Matrix.identity ();
item.get_transform (out transform);
hover_effect.set_transform (transform);
Expand Down
220 changes: 215 additions & 5 deletions src/Services/ActionManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public class Akira.Services.ActionManager : Object {

public static Gee.MultiMap<string, string> action_accelerators = new Gee.HashMultiMap<string, string> ();

GLib.File? file;

private const ActionEntry[] ACTION_ENTRIES = {
{ ACTION_NEW_WINDOW, action_new_window },
{ ACTION_OPEN, action_open },
Expand Down Expand Up @@ -128,17 +130,225 @@ public class Akira.Services.ActionManager : Object {
}

private void action_open () {
warning ("open");
var open_dialog = new Gtk.FileChooserDialog ("Open file",
this as Gtk.Window,
Gtk.FileChooserAction.OPEN,
Gtk.Stock.CANCEL,
Gtk.ResponseType.CANCEL,
Gtk.Stock.OPEN,
Gtk.ResponseType.ACCEPT);
add_filters (open_dialog);
open_dialog.local_only = false; //allow for uri
open_dialog.set_modal (true);
open_dialog.response.connect (open_response_cb);
open_dialog.show ();
}

void open_response_cb (Gtk.Dialog dialog, int response_id) {
var open_dialog = dialog as Gtk.FileChooserDialog;

switch (response_id) {
case Gtk.ResponseType.ACCEPT:
file = open_dialog.get_file();

uint8[] file_contents;

try {
file.load_contents (null, out file_contents, null);
}
catch (GLib.Error err) {
error ("%s\n", err.message);
}
Json.Parser parser = new Json.Parser ();
parser.load_from_data ((string) file_contents);

//TODO: You need to register names to be disoverable by name
Type? type_rect = typeof (Goo.CanvasRect);
Type? type_ellipse = typeof (Goo.CanvasEllipse);
Type? type_text = typeof (Goo.CanvasText);

Json.Node node = parser.get_root ();
var root_object_node = node.get_object ();
Json.Array array = root_object_node.get_member ("items").get_array ();
var canvas = window.main_window.main_canvas.canvas;
foreach (unowned Json.Node node_item in array.get_elements ()) {
var object_node = node_item.get_object ();
load_item (object_node);
}
var scale = root_object_node.get_double_member ("scale");
canvas.set_scale (scale);
//TODO: listen to scale on canvas to change the zoom_button
window.headerbar.zoom.zoom_default_button.label = "%.0f%%".printf (scale * 100);

print ("opened: %s\n", (open_dialog.get_filename ()));
break;

case Gtk.ResponseType.CANCEL:
print ("cancelled: FileChooserAction.OPEN\n");
break;
}
dialog.destroy ();
}

private void action_save () {
warning ("save");
void load_item (Json.Object object_node) {
var canvas = window.main_window.main_canvas.canvas;
string type = object_node.get_string_member ("type");
var object_node_item = object_node.get_member ("item");
Goo.CanvasItem item = Json.gobject_deserialize (Type.from_name (type), object_node_item) as Goo.CanvasItem;
if (item != null) {
item.set("parent", canvas.get_root_item ());
var object_node_transform = object_node.get_member ("transform").get_object ();
var transform = Cairo.Matrix.identity ();
transform.xx = object_node_transform.get_double_member ("xx");
transform.xy = object_node_transform.get_double_member ("xy");
transform.yx = object_node_transform.get_double_member ("yx");
transform.yy = object_node_transform.get_double_member ("yy");
transform.x0 = object_node_transform.get_double_member ("x0");
transform.y0 = object_node_transform.get_double_member ("y0");
item.set_transform (transform);
add_artboard_layer (item, type.replace ("GooCanvas", ""));
}
}

private void action_save_as () {
warning ("save_as");
void add_artboard_layer (Goo.CanvasItem item, string type) {
if (type == "Rect") {
type = "Rectangle";
} else if (type == "Ellipse") {
type = "Circle";
}
var artboard = window.main_window.right_sidebar.layers_panel.artboard;
var layer = new Akira.Layouts.Partials.Layer (window, artboard, (Goo.CanvasItemSimple)item,
type, "shape-" + type.down () + "-symbolic", false);
item.set_data<Akira.Layouts.Partials.Layer?> ("layer", layer);
artboard.container.add (layer);
artboard.show_all ();
}

private void action_save (SimpleAction action, Variant? parameter) {
if (file != null) {
this.save_to_file ();
}
else {
action_save_as (action, parameter);
}
}

void save_as_response_cb (Gtk.Dialog dialog, int response_id) {
var save_dialog = dialog as Gtk.FileChooserDialog;

switch (response_id) {
case Gtk.ResponseType.ACCEPT:
file = save_dialog.get_file();
this.save_to_file ();
break;
default:
break;
}
dialog.destroy ();
}

void save_to_file () {
var canvas = window.main_window.main_canvas.canvas;
var root_item = canvas.get_root_item ();

Json.Builder builder = new Json.Builder ();

builder.begin_object ();
builder.set_member_name ("version");
builder.add_string_value ("1.0");

builder.set_member_name ("scale");
builder.add_double_value (canvas.get_scale ());

builder.set_member_name ("items");
builder.begin_array ();
for (int i = 0; i < root_item.get_n_children (); i++) {
Goo.CanvasItem item = root_item.get_child(i);
if (item.get_data<bool>("ignore")) {
continue;
}
Json.Node node = Json.gobject_serialize (item);
builder.begin_object ();
builder.set_member_name ("type");
builder.add_string_value (item.get_type ().name ());
builder.set_member_name ("item");
builder.add_value (node);
var transform = Cairo.Matrix.identity ();
item.get_transform (out transform);
builder.set_member_name ("transform");
builder.begin_object ();
builder.set_member_name("xx");
builder.add_double_value(transform.xx);
builder.set_member_name("yx");
builder.add_double_value(transform.yx);
builder.set_member_name("xy");
builder.add_double_value(transform.xy);
builder.set_member_name("yy");
builder.add_double_value(transform.yy);
builder.set_member_name("x0");
builder.add_double_value(transform.x0);
builder.set_member_name("y0");
builder.add_double_value(transform.y0);
builder.end_object ();
builder.end_object ();
}
builder.end_array ();

builder.end_object ();

Json.Generator generator = new Json.Generator ();
generator.pretty = true;
Json.Node root = builder.get_root ();
generator.set_root (root);

string current_contents = generator.to_data (null);
try {
file.replace_contents (current_contents.data, null, false,
GLib.FileCreateFlags.NONE, null, null);

print ("saved: %s\n", file.get_path ());
}
catch (GLib.Error err) {
error ("%s\n", err.message);
}
}

private void action_save_as (SimpleAction action, Variant? parameter) {
var save_dialog = new Gtk.FileChooserDialog ("Save canvas",
this as Gtk.Window,
Gtk.FileChooserAction.SAVE,
Gtk.Stock.CANCEL,
Gtk.ResponseType.CANCEL,
Gtk.Stock.SAVE,
Gtk.ResponseType.ACCEPT);

save_dialog.set_do_overwrite_confirmation (true);
add_filters (save_dialog);
save_dialog.set_modal (true);
if (file != null) {
try {
(save_dialog as Gtk.FileChooser).set_file (file);
}
catch (GLib.Error error) {
print ("%s\n", error.message);
}
}
save_dialog.response.connect (save_as_response_cb);
save_dialog.show ();
}

private void add_filters (Gtk.FileChooser chooser) {
Gtk.FileFilter filter = new Gtk.FileFilter ();
filter.add_pattern ("*.akira");
filter.set_filter_name ("Akira files");
chooser.add_filter(filter);
filter = new Gtk.FileFilter ();
filter.add_pattern ("*");
filter.set_filter_name ("All files");
chooser.add_filter(filter);
}


private void action_show_pixel_grid () {
warning ("show pixel grid");
}
Expand Down

0 comments on commit c72e1ae

Please sign in to comment.