рефакторинг небольшой

This commit is contained in:
2026-02-25 21:27:02 +03:00
parent 9202b527e4
commit 5c9ec3167a
8 changed files with 25 additions and 42 deletions

View File

@@ -8,7 +8,7 @@ const Rect_i = basic_models.Rect_i;
const Size_i = basic_models.Size_i; const Size_i = basic_models.Size_i;
const Point2_f = @import("models/basic_models.zig").Point2_f; const Point2_f = @import("models/basic_models.zig").Point2_f;
const Color = dvui.Color; const Color = dvui.Color;
const tools = @import("tools.zig");
const Toolbar = @import("Toolbar.zig"); const Toolbar = @import("Toolbar.zig");
const Canvas = @This(); const Canvas = @This();
@@ -29,15 +29,14 @@ _zoom: f32 = 1,
_redraw_pending: bool = false, _redraw_pending: bool = false,
_last_redraw_time_ms: i64 = 0, _last_redraw_time_ms: i64 = 0,
cursor_document_point: ?Point2_f = null, cursor_document_point: ?Point2_f = null,
/// true — рисовать документ (render), false — пример (gradient/squares).
draw_document: bool = true, draw_document: bool = true,
pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine, toolbar: Toolbar) Canvas { pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine) Canvas {
return .{ return .{
.allocator = allocator, .allocator = allocator,
.document = document, .document = document,
.render_engine = engine, .render_engine = engine,
.toolbar = toolbar, .toolbar = Toolbar.init(&tools.default_tools),
}; };
} }

11
src/Tool.zig Normal file
View File

@@ -0,0 +1,11 @@
const Point2_f = @import("models/basic_models.zig").Point2_f;
const Canvas = @import("Canvas.zig");
pub const ToolContext = struct {
canvas: *Canvas,
document_point: Point2_f,
};
pub const Tool = struct {
onCanvasClick: *const fn (*const ToolContext) void,
};

View File

@@ -1,19 +1,13 @@
//! Структура тулбара инструментов. Жизненный цикл совпадает с Canvas. const Tool = @import("Tool.zig");
const tool_interface = @import("tool_interface.zig");
const Toolbar = @This(); const Toolbar = @This();
/// Описание одного инструмента для тулбара.
pub const ToolDescriptor = struct { pub const ToolDescriptor = struct {
name: []const u8, name: []const u8,
/// Иконка в формате TVG (байты).
icon_tvg: []const u8, icon_tvg: []const u8,
/// Реализация интерфейса инструмента (своя для каждого инструмента в tools/). implementation: *const Tool.Tool,
implementation: *const tool_interface.Tool,
}; };
/// Вертикальный тулбар инструментов.
tools: []const ToolDescriptor, tools: []const ToolDescriptor,
selected_index: usize, selected_index: usize,

View File

@@ -5,8 +5,6 @@ const RenderEngine = @import("render/RenderEngine.zig").RenderEngine;
const Document = @import("models/Document.zig"); const Document = @import("models/Document.zig");
const random_document = @import("models/random_document.zig"); const random_document = @import("models/random_document.zig");
const basic_models = @import("models/basic_models.zig"); const basic_models = @import("models/basic_models.zig");
const tools = @import("tools.zig");
const Toolbar = @import("Toolbar.zig");
const WindowContext = @This(); const WindowContext = @This();
@@ -23,7 +21,6 @@ pub const OpenDocument = struct {
allocator, allocator,
&self.document, &self.document,
(&self.cpu_render).renderEngine(), (&self.cpu_render).renderEngine(),
Toolbar.init(&tools.default_tools),
); );
} }

View File

@@ -1,14 +0,0 @@
//! Общий интерфейс инструмента. Реализации живут в каталоге tools/.
const Point2_f = @import("models/basic_models.zig").Point2_f;
/// Контекст вызова: холст и точка в координатах документа.
pub const ToolContext = struct {
canvas: *anyopaque,
document_point: Point2_f,
};
/// Интерфейс инструмента: один метод — клик по холсту в позиции курсора.
pub const Tool = struct {
onClick: *const fn (*const ToolContext) void,
};

View File

@@ -1,5 +1,3 @@
//! Список инструментов по умолчанию для тулбара. Реализации — в каталоге tools/.
const Toolbar = @import("Toolbar.zig"); const Toolbar = @import("Toolbar.zig");
const line = @import("tools/line.zig"); const line = @import("tools/line.zig");
const icons = @import("icons.zig"); const icons = @import("icons.zig");

View File

@@ -1,21 +1,19 @@
//! Инструмент «Линия»: создаёт линию в позиции клика.
const Canvas = @import("../Canvas.zig"); const Canvas = @import("../Canvas.zig");
const tool_interface = @import("../tool_interface.zig"); const Tool = @import("../Tool.zig");
const shape = @import("../models/shape/shape.zig"); const shape = @import("../models/shape/shape.zig");
fn onClick(ctx: *const tool_interface.ToolContext) void { fn onCanvasClick(ctx: *const Tool.ToolContext) void {
const canvas: *Canvas = @alignCast(@ptrCast(ctx.canvas)); const canvas = ctx.canvas;
var obj = shape.createObject(canvas.document.allocator, .line) catch return; var obj = shape.createObject(canvas.document.allocator, .line) catch return;
defer obj.deinit(canvas.allocator);
obj.setProperty(canvas.document.allocator, .{ .data = .{ .position = ctx.document_point } }) catch { obj.setProperty(canvas.document.allocator, .{ .data = .{ .position = ctx.document_point } }) catch {
obj.deinit(canvas.document.allocator); obj.deinit(canvas.document.allocator);
return; return;
}; };
canvas.document.addObject(obj) catch { canvas.document.addObject(obj) catch {
obj.deinit(canvas.document.allocator);
return; return;
}; };
canvas.requestRedraw(); canvas.requestRedraw();
} }
pub const tool = tool_interface.Tool{ .onClick = onClick }; pub const tool = Tool.Tool{ .onCanvasClick = onCanvasClick };

View File

@@ -3,7 +3,7 @@ const dvui = @import("dvui");
const dvui_ext = @import("dvui_ext.zig"); const dvui_ext = @import("dvui_ext.zig");
const Canvas = @import("../Canvas.zig"); const Canvas = @import("../Canvas.zig");
const Rect_i = @import("../models/basic_models.zig").Rect_i; const Rect_i = @import("../models/basic_models.zig").Rect_i;
const tool_interface = @import("../tool_interface.zig"); const Tool = @import("../Tool.zig");
pub fn canvasView(canvas: *Canvas, content_rect_scale: dvui.RectScale) void { pub fn canvasView(canvas: *Canvas, content_rect_scale: dvui.RectScale) void {
var textured = dvui_ext.texturedBox(content_rect_scale, dvui.Rect.all(20)); var textured = dvui_ext.texturedBox(content_rect_scale, dvui.Rect.all(20));
@@ -163,11 +163,11 @@ fn handleCanvasMouse(canvas: *Canvas, scroll: anytype) void {
canvas.cursor_document_point = if (canvas.isContentPointOnDocument(content_pt, natural_scale)) doc_pt else null; canvas.cursor_document_point = if (canvas.isContentPointOnDocument(content_pt, natural_scale)) doc_pt else null;
if (canvas.cursor_document_point) |point| { if (canvas.cursor_document_point) |point| {
if (canvas.toolbar.currentDescriptor()) |desc| { if (canvas.toolbar.currentDescriptor()) |desc| {
var ctx = tool_interface.ToolContext{ var ctx = Tool.ToolContext{
.canvas = canvas, .canvas = canvas,
.document_point = point, .document_point = point,
}; };
desc.implementation.onClick(&ctx); desc.implementation.onCanvasClick(&ctx);
} }
} }
}, },
@@ -198,7 +198,7 @@ fn drawToolbar(canvas: *Canvas) void {
const is_selected = (canvas.toolbar.selected_index == i); const is_selected = (canvas.toolbar.selected_index == i);
const opts: dvui.Options = .{ const opts: dvui.Options = .{
.id_extra = i, .id_extra = i,
.color_fill = if (is_selected) dvui.Color.transparent else undefined, .color_fill = if (is_selected) dvui.themeGet().fill else undefined,
}; };
if (dvui.buttonIcon(@src(), tool_desc.name, tool_desc.icon_tvg, .{}, .{}, opts)) { if (dvui.buttonIcon(@src(), tool_desc.name, tool_desc.icon_tvg, .{}, .{}, opts)) {
canvas.toolbar.select(i); canvas.toolbar.select(i);