Объекты в документе

This commit is contained in:
2026-02-23 19:29:21 +03:00
parent 0b287e800d
commit c73d710513
3 changed files with 157 additions and 39 deletions

View File

@@ -1,9 +1,8 @@
const std = @import("std");
const basic_models = @import("basic_models.zig");
const properties = @import("Property.zig");
const Property = properties.Property;
const Size = basic_models.Size;
const ObjectCommon = basic_models.ObjectCommon;
const Point2 = basic_models.Point2;
const Document = @This();
size: Size,
@@ -36,32 +35,93 @@ pub const Layer = struct {
}
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);
}
};
/// Объект на слое: общие свойства + полиморфные данные по тегу (path, rect, ellipse, ...).
/// Полиморфизм через tagged union — без наследования и vtable, диспетчеризация через switch (obj.data).
pub const Object = struct {
common: ObjectCommon,
data: Data,
pub const Data = union(enum) {
path: PathData,
rect: RectData,
ellipse: EllipseData,
};
/// Точки контура (заглушка; позже — владение через Layer/Document allocator)
pub const PathData = struct {};
pub const RectData = struct {
width: f32,
height: f32,
};
pub const EllipseData = struct {
radius_x: f32,
radius_y: f32,
};
/// Тип фигуры: определяет, как RenderEngine интерпретирует свойства и рисует объект.
pub const ShapeKind = enum {
rect,
ellipse,
line,
path,
};
/// Объект на слое: тип фигуры + список полиморфных свойств.
/// Типы объектов (прямоугольник, эллипс, линия) задаются конструкторами,
/// которые создают нужный набор свойств; UI и RenderEngine работают с union Property.
pub const Object = struct {
shape: ShapeKind,
properties: std.ArrayList(Property),
/// Найти свойство по тегу и вернуть вариант union (caller делает switch).
pub fn getProperty(self: Object, tag: std.meta.Tag(Property)) ?Property {
for (self.properties.items) |prop| {
if (std.meta.activeTag(prop) == tag) return prop;
}
return null;
}
/// Установить свойство: если уже есть с таким тегом — заменить, иначе добавить.
pub fn setProperty(self: *Object, allocator: std.mem.Allocator, prop: Property) !void {
for (self.properties.items, 0..) |*p, i| {
if (std.meta.activeTag(p.*) == std.meta.activeTag(prop)) {
self.properties.items[i] = prop;
return;
}
}
try self.properties.append(allocator, prop);
}
/// Клонировать объект (в т.ч. список свойств) для вставки в другой слой/документ.
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 };
}
pub fn deinit(self: *Object, allocator: std.mem.Allocator) void {
self.properties.deinit(allocator);
self.* = undefined;
}
/// Базовый объект с общим набором свойств (для внутреннего использования конструкторами).
fn createWithCommon(allocator: std.mem.Allocator, shape: ShapeKind) !Object {
const common = properties.defaultCommonProperties();
var properties_list = std.ArrayList(Property).empty;
errdefer properties_list.deinit(allocator);
try properties_list.appendSlice(allocator, &common);
return .{ .shape = shape, .properties = properties_list };
}
// --- Публичные конструкторы: базовый объект + одно свойство фигуры ---
pub fn createRect(allocator: std.mem.Allocator) !Object {
var obj = try createWithCommon(allocator, .rect);
errdefer obj.deinit(allocator);
try obj.properties.append(allocator, .{ .size = .{ .width = 100, .height = 100 } });
return obj;
}
pub fn createEllipse(allocator: std.mem.Allocator) !Object {
var obj = try createWithCommon(allocator, .ellipse);
errdefer obj.deinit(allocator);
try obj.properties.append(allocator, .{ .radii = .{ .x = 50, .y = 50 } });
return obj;
}
pub fn createLine(allocator: std.mem.Allocator) !Object {
var obj = try createWithCommon(allocator, .line);
errdefer obj.deinit(allocator);
try obj.properties.append(allocator, .{ .end_point = .{ .x = 100, .y = 0 } });
return obj;
}
};