diff --git a/src/models/Document.zig b/src/models/Document.zig index a0582b7..69d258b 100644 --- a/src/models/Document.zig +++ b/src/models/Document.zig @@ -7,44 +7,27 @@ const Document = @This(); size: Size, allocator: std.mem.Allocator, -layers: std.ArrayList(Layer), +/// Корневые объекты документа (вложенность через Object.children). +objects: std.ArrayList(Object), pub fn init(allocator: std.mem.Allocator, size: Size) Document { return .{ .size = size, .allocator = allocator, - .layers = std.ArrayList(Layer).empty, + .objects = std.ArrayList(Object).empty, }; } pub fn deinit(self: *Document) void { - for (self.layers.items) |*layer| layer.deinit(); - self.layers.deinit(self.allocator); + for (self.objects.items) |*obj| obj.deinit(self.allocator); + self.objects.deinit(self.allocator); } -pub const Layer = struct { - name: [64:0]u8 = .{0} ** 64, - allocator: std.mem.Allocator, - objects: std.ArrayList(Object), - - pub fn init(allocator: std.mem.Allocator) Layer { - return .{ - .allocator = allocator, - .objects = std.ArrayList(Object).empty, - }; - } - - pub fn deinit(self: *Layer) void { - for (self.objects.items) |*obj| obj.deinit(self.allocator); - self.objects.deinit(self.allocator); - } - - /// Добавить объект в слой (клонирует свойства в allocator слоя). - pub fn addObject(self: *Layer, template: Object) !void { - const obj = try template.clone(self.allocator); - try self.objects.append(self.allocator, obj); - } -}; +/// Добавить корневой объект в документ (клонирует в allocator документа). +pub fn addObject(self: *Document, template: Object) !void { + const obj = try template.clone(self.allocator); + try self.objects.append(self.allocator, obj); +} /// Тип фигуры: определяет, как RenderEngine интерпретирует свойства и рисует объект. pub const ShapeKind = enum { @@ -54,12 +37,13 @@ pub const ShapeKind = enum { path, }; -/// Объект на слое: тип фигуры + список полиморфных свойств. -/// Типы объектов (прямоугольник, эллипс, линия) задаются конструкторами, -/// которые создают нужный набор свойств; UI и RenderEngine работают с union Property. +/// Объект документа: тип фигуры, свойства и вложенные дочерние объекты. +/// Типы объектов задаются конструкторами; UI и RenderEngine работают с union Property. pub const Object = struct { shape: ShapeKind, properties: std.ArrayList(Property), + /// Вложенные объекты (дерево). + children: std.ArrayList(Object), /// Найти свойство по тегу и вернуть вариант union (caller делает switch). pub fn getProperty(self: Object, tag: std.meta.Tag(Property)) ?Property { @@ -80,15 +64,34 @@ pub const Object = struct { try self.properties.append(allocator, prop); } - /// Клонировать объект (в т.ч. список свойств) для вставки в другой слой/документ. + /// Добавить дочерний объект (клонирует в переданный allocator). + pub fn addChild(self: *Object, allocator: std.mem.Allocator, template: Object) !void { + const obj = try template.clone(allocator); + try self.children.append(allocator, obj); + } + + /// Клонировать объект рекурсивно (свойства и дети). pub fn clone(self: Object, allocator: std.mem.Allocator) !Object { - var list = std.ArrayList(Property).empty; - errdefer list.deinit(allocator); - try list.appendSlice(allocator, self.properties.items); - return .{ .shape = self.shape, .properties = list }; + var properties_list = std.ArrayList(Property).empty; + errdefer properties_list.deinit(allocator); + try properties_list.appendSlice(allocator, self.properties.items); + + var children_list = std.ArrayList(Object).empty; + errdefer children_list.deinit(allocator); + for (self.children.items) |child| { + try children_list.append(allocator, try child.clone(allocator)); + } + + return .{ + .shape = self.shape, + .properties = properties_list, + .children = children_list, + }; } pub fn deinit(self: *Object, allocator: std.mem.Allocator) void { + for (self.children.items) |*child| child.deinit(allocator); + self.children.deinit(allocator); self.properties.deinit(allocator); self.* = undefined; } @@ -99,7 +102,11 @@ pub const Object = struct { var properties_list = std.ArrayList(Property).empty; errdefer properties_list.deinit(allocator); try properties_list.appendSlice(allocator, &common); - return .{ .shape = shape, .properties = properties_list }; + return .{ + .shape = shape, + .properties = properties_list, + .children = std.ArrayList(Object).empty, + }; } // --- Публичные конструкторы: базовый объект + одно свойство фигуры ---