Начало фикса json
This commit is contained in:
@@ -92,7 +92,7 @@ pub fn exampleReset(self: *Canvas) !void {
|
||||
}
|
||||
|
||||
pub fn addRandomShapes(self: *Canvas) !void {
|
||||
try random_document.addRandomShapes(self.document, std.crypto.random);
|
||||
try random_document.addRandomShapes(self.document, self.allocator, std.crypto.random);
|
||||
self.requestRedraw();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ pub const OpenDocument = struct {
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, self: *OpenDocument) void {
|
||||
const default_size = basic_models.Size_f{ .w = 800, .h = 600 };
|
||||
self.document = Document.init(allocator, default_size);
|
||||
self.document = Document.init(default_size);
|
||||
self.cpu_render = CpuRenderEngine.init(allocator, .Squares);
|
||||
self.canvas = Canvas.init(
|
||||
allocator,
|
||||
@@ -38,8 +38,8 @@ pub const OpenDocument = struct {
|
||||
self.selected_object_id = null;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *OpenDocument) void {
|
||||
self.document.deinit();
|
||||
pub fn deinit(self: *OpenDocument, allocator: std.mem.Allocator) void {
|
||||
self.document.deinit(allocator);
|
||||
self.canvas.deinit();
|
||||
}
|
||||
};
|
||||
@@ -60,7 +60,7 @@ pub fn init(allocator: std.mem.Allocator) !WindowContext {
|
||||
|
||||
pub fn deinit(self: *WindowContext) void {
|
||||
for (self.documents.items) |ptr| {
|
||||
ptr.deinit();
|
||||
ptr.deinit(self.allocator);
|
||||
self.allocator.destroy(ptr);
|
||||
}
|
||||
self.documents.deinit(self.allocator);
|
||||
@@ -85,7 +85,7 @@ pub fn addDocument(self: *WindowContext, doc: Document) !void {
|
||||
const ptr = try self.allocator.create(OpenDocument);
|
||||
errdefer self.allocator.destroy(ptr);
|
||||
var doc_mut = doc;
|
||||
errdefer doc_mut.deinit();
|
||||
errdefer doc_mut.deinit(self.allocator);
|
||||
OpenDocument.initWithDocument(self.allocator, ptr, doc_mut);
|
||||
try self.documents.append(self.allocator, ptr);
|
||||
self.active_document_index = self.documents.items.len - 1;
|
||||
@@ -100,7 +100,7 @@ pub fn setActiveDocument(self: *WindowContext, index: usize) void {
|
||||
pub fn closeDocument(self: *WindowContext, index: usize) void {
|
||||
if (index >= self.documents.items.len) return;
|
||||
const open_doc = self.documents.items[index];
|
||||
open_doc.deinit();
|
||||
open_doc.deinit(self.allocator);
|
||||
self.allocator.destroy(open_doc);
|
||||
_ = self.documents.orderedRemove(index);
|
||||
|
||||
|
||||
@@ -7,71 +7,69 @@ pub const Object = @import("Object.zig");
|
||||
const shape = @import("shape/shape.zig");
|
||||
|
||||
size: Size_f,
|
||||
allocator: std.mem.Allocator,
|
||||
objects: std.ArrayList(Object),
|
||||
next_object_id: u64,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, size: Size_f) Document {
|
||||
pub fn init(size: Size_f) Document {
|
||||
return .{
|
||||
.size = size,
|
||||
.allocator = allocator,
|
||||
.objects = std.ArrayList(Object).empty,
|
||||
.next_object_id = 1,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Document) void {
|
||||
for (self.objects.items) |*obj| obj.deinit(self.allocator);
|
||||
self.objects.deinit(self.allocator);
|
||||
pub fn deinit(self: *Document, allocator: std.mem.Allocator) void {
|
||||
for (self.objects.items) |*obj| obj.deinit(allocator);
|
||||
self.objects.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn addObject(self: *Document, template: Object) !void {
|
||||
const obj = try template.clone(self.allocator, &self.next_object_id);
|
||||
try self.objects.append(self.allocator, obj);
|
||||
pub fn addObject(self: *Document, allocator: std.mem.Allocator, template: Object) !void {
|
||||
const obj = try template.clone(allocator, &self.next_object_id);
|
||||
try self.objects.append(allocator, obj);
|
||||
}
|
||||
|
||||
/// Добавляет объект в документ: как ребёнка родителя (если id найден), иначе в корень.
|
||||
pub fn addObjectUnderParentId(self: *Document, parent_id: ?u64, template: Object) !void {
|
||||
pub fn addObjectUnderParentId(self: *Document, allocator: std.mem.Allocator, parent_id: ?u64, template: Object) !void {
|
||||
if (parent_id) |id| {
|
||||
if (self.findObjectById(id)) |parent| {
|
||||
try parent.addChild(self.allocator, template, &self.next_object_id);
|
||||
try parent.addChild(allocator, template, &self.next_object_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
try self.addObject(template);
|
||||
try self.addObject(allocator, template);
|
||||
}
|
||||
|
||||
pub fn addShape(self: *Document, parent: ?*Object, shape_kind: Object.ShapeKind) !void {
|
||||
const obj = try shape.createObject(self.allocator, shape_kind);
|
||||
pub fn addShape(self: *Document, allocator: std.mem.Allocator, parent: ?*Object, shape_kind: Object.ShapeKind) !void {
|
||||
const obj = try shape.createObject(allocator, shape_kind);
|
||||
if (parent) |p| {
|
||||
try p.addChild(self.allocator, obj, &self.next_object_id);
|
||||
try p.addChild(allocator, obj, &self.next_object_id);
|
||||
} else {
|
||||
try self.addObject(obj);
|
||||
try self.addObject(allocator, obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// Удаляет объект из документа (из корня или из детей родителя). Возвращает true, если объект был найден и удалён.
|
||||
pub fn removeObject(self: *Document, obj: *Object) bool {
|
||||
pub fn removeObject(self: *Document, allocator: std.mem.Allocator, obj: *Object) bool {
|
||||
for (self.objects.items, 0..) |*item, i| {
|
||||
if (item == obj) {
|
||||
var removed = self.objects.orderedRemove(i);
|
||||
removed.deinit(self.allocator);
|
||||
removed.deinit(allocator);
|
||||
return true;
|
||||
}
|
||||
if (removeFromChildren(self.allocator, &item.children, obj)) return true;
|
||||
if (removeFromChildren(allocator, &item.children, obj)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Удаляет объект по id. Возвращает true, если объект был найден и удалён.
|
||||
pub fn removeObjectById(self: *Document, obj_id: u64) bool {
|
||||
pub fn removeObjectById(self: *Document, allocator: std.mem.Allocator, obj_id: u64) bool {
|
||||
for (self.objects.items, 0..) |*item, i| {
|
||||
if (item.id == obj_id) {
|
||||
var removed = self.objects.orderedRemove(i);
|
||||
removed.deinit(self.allocator);
|
||||
removed.deinit(allocator);
|
||||
return true;
|
||||
}
|
||||
if (removeFromChildrenById(self.allocator, &item.children, obj_id)) return true;
|
||||
if (removeFromChildrenById(allocator, &item.children, obj_id)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,13 @@ pub fn saveToFile(doc: *const Document, path: []const u8) !void {
|
||||
|
||||
var buffer: [4096]u8 = undefined;
|
||||
var writer = file.writer(&buffer);
|
||||
var jw: std.json.Stringify = .{
|
||||
.writer = &writer.interface,
|
||||
.options = .{ .whitespace = .indent_2 },
|
||||
};
|
||||
|
||||
try writeDocument(&jw, doc);
|
||||
try std.json.Stringify.value(
|
||||
doc,
|
||||
.{ .whitespace = .indent_2 },
|
||||
&writer.interface,
|
||||
);
|
||||
|
||||
try writer.interface.flush();
|
||||
}
|
||||
|
||||
@@ -158,11 +159,10 @@ fn parseDocumentValue(allocator: std.mem.Allocator, value: std.json.Value) !Docu
|
||||
|
||||
var document = Document{
|
||||
.size = size,
|
||||
.allocator = allocator,
|
||||
.objects = std.ArrayList(Object).empty,
|
||||
.next_object_id = 1,
|
||||
};
|
||||
errdefer document.deinit();
|
||||
errdefer document.deinit(allocator);
|
||||
|
||||
const objects_val = try getField(obj, "objects");
|
||||
const objects_arr = try expectArray(objects_val);
|
||||
|
||||
@@ -90,17 +90,16 @@ fn randomizeObjectProperties(allocator: std.mem.Allocator, doc_size: *const Size
|
||||
}
|
||||
|
||||
/// Создаёт в документе случайные фигуры (line, ellipse, broken).
|
||||
pub fn addRandomShapes(doc: *Document, rng: std.Random) !void {
|
||||
pub fn addRandomShapes(doc: *Document, allocator: std.mem.Allocator, rng: std.Random) !void {
|
||||
const max_total: usize = 80;
|
||||
var total_count: usize = 0;
|
||||
const allocator = doc.allocator;
|
||||
|
||||
const n_root = rng.intRangeLessThan(usize, 6, 15);
|
||||
for (0..n_root) |_| {
|
||||
if (total_count >= max_total) break;
|
||||
var obj = try shape.createObject(allocator, randomShapeKind(rng));
|
||||
try randomizeObjectProperties(allocator, &doc.size, &obj, rng);
|
||||
try doc.addObject(obj);
|
||||
try doc.addObject(allocator, obj);
|
||||
total_count += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ pub const ToolContext = struct {
|
||||
pub fn addObject(self: *const ToolContext, template: Document.Object) !void {
|
||||
var obj = template;
|
||||
const local_pos = self.computeLocalPosition();
|
||||
try obj.setProperty(self.canvas.document.allocator, .{ .data = .{ .position = local_pos } });
|
||||
try self.canvas.document.addObjectUnderParentId(self.selected_object_id, obj);
|
||||
try obj.setProperty(self.canvas.allocator, .{ .data = .{ .position = local_pos } });
|
||||
try self.canvas.document.addObjectUnderParentId(self.canvas.allocator, self.selected_object_id, obj);
|
||||
self.canvas.requestRedraw();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const shape = @import("../../models/shape/shape.zig");
|
||||
|
||||
fn onCanvasClick(ctx: *const Tool.ToolContext) !void {
|
||||
const canvas = ctx.canvas;
|
||||
var obj = shape.createObject(canvas.document.allocator, .arc) catch return;
|
||||
var obj = shape.createObject(canvas.allocator, .arc) catch return;
|
||||
defer obj.deinit(canvas.allocator);
|
||||
try ctx.addObject(obj);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ const shape = @import("../../models/shape/shape.zig");
|
||||
|
||||
fn onCanvasClick(ctx: *const Tool.ToolContext) !void {
|
||||
const canvas = ctx.canvas;
|
||||
var obj = shape.createObject(canvas.document.allocator, .broken) catch return;
|
||||
var obj = shape.createObject(canvas.allocator, .broken) catch return;
|
||||
defer obj.deinit(canvas.allocator);
|
||||
try ctx.addObject(obj);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ const shape = @import("../../models/shape/shape.zig");
|
||||
|
||||
fn onCanvasClick(ctx: *const Tool.ToolContext) !void {
|
||||
const canvas = ctx.canvas;
|
||||
var obj = shape.createObject(canvas.document.allocator, .ellipse) catch return;
|
||||
var obj = shape.createObject(canvas.allocator, .ellipse) catch return;
|
||||
defer obj.deinit(canvas.allocator);
|
||||
try ctx.addObject(obj);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const shape = @import("../../models/shape/shape.zig");
|
||||
|
||||
fn onCanvasClick(ctx: *const Tool.ToolContext) !void {
|
||||
const canvas = ctx.canvas;
|
||||
var obj = shape.createObject(canvas.document.allocator, .line) catch return;
|
||||
var obj = shape.createObject(canvas.allocator, .line) catch return;
|
||||
defer obj.deinit(canvas.allocator);
|
||||
try ctx.addObject(obj);
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
changed = res.changed or changed;
|
||||
}
|
||||
if (changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .position = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .position = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
@@ -431,7 +431,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
subrow.deinit();
|
||||
if (res.changed) {
|
||||
next = degrees * std.math.pi / 180.0;
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .angle = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .angle = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
}
|
||||
@@ -456,28 +456,28 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
changed = res.changed or changed;
|
||||
}
|
||||
if (changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .scale = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .scale = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
.visible => |v| {
|
||||
var next = v;
|
||||
if (dvui.checkbox(@src(), &next, "Visible", .{})) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .visible = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .visible = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
.opacity => |opacity| {
|
||||
var next = opacity;
|
||||
if (dvui.sliderEntry(@src(), "{d:0.2}", .{ .value = &next, .min = 0.0, .max = 1.0, .interval = 0.01 }, .{ .expand = .horizontal })) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .opacity = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .opacity = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
.locked => |v| {
|
||||
var next = v;
|
||||
if (dvui.checkbox(@src(), &next, "Locked", .{})) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .locked = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .locked = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
@@ -502,7 +502,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
changed = res.changed or changed;
|
||||
}
|
||||
if (changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .size = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .size = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
@@ -527,7 +527,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
changed = res.changed or changed;
|
||||
}
|
||||
if (changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .radii = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .radii = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
@@ -556,7 +556,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
changed = res.changed or changed;
|
||||
}
|
||||
if (changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .end_point = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .end_point = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
},
|
||||
@@ -578,7 +578,7 @@ fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Prope
|
||||
const res = dvui.textEntryNumber(@src(), T, .{ .value = &next, .min = @as(T, 0.0), .max = @as(T, 100.0) }, .{ .expand = .horizontal });
|
||||
subrow.deinit();
|
||||
if (res.changed) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .thickness = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .thickness = next } }) catch {};
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
}
|
||||
@@ -597,9 +597,9 @@ fn drawColorEditor(canvas: *Canvas, obj: *Document.Object, rgba: u32, is_fill: b
|
||||
)) {
|
||||
const next = colorToRgba(hsv.toColor());
|
||||
if (is_fill) {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .fill_rgba = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .fill_rgba = next } }) catch {};
|
||||
} else {
|
||||
obj.setProperty(canvas.document.allocator, .{ .data = .{ .stroke_rgba = next } }) catch {};
|
||||
obj.setProperty(canvas.allocator, .{ .data = .{ .stroke_rgba = next } }) catch {};
|
||||
}
|
||||
canvas.requestRedraw();
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ fn objectTree(ctx: *WindowContext) void {
|
||||
}
|
||||
},
|
||||
.delete => |obj_id| {
|
||||
_ = doc.removeObjectById(obj_id);
|
||||
_ = doc.removeObjectById(ctx.allocator, obj_id);
|
||||
if (open_doc.selected_object_id == obj_id)
|
||||
open_doc.selected_object_id = null;
|
||||
open_doc.canvas.requestRedraw();
|
||||
|
||||
Reference in New Issue
Block a user