diff --git a/src/WindowContext.zig b/src/WindowContext.zig index df5a241..c97617a 100644 --- a/src/WindowContext.zig +++ b/src/WindowContext.zig @@ -8,6 +8,7 @@ allocator: std.mem.Allocator, canvas_texture: ?dvui.Texture = null, canvas_width: u32 = 400, canvas_height: u32 = 300, +canvas_pos: dvui.Point = dvui.Point{ .x = 0, .y = 0 }, pub fn init(allocator: std.mem.Allocator) WindowContext { return .{ diff --git a/src/main.zig b/src/main.zig index 3339901..32fc560 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const dvui = @import("dvui"); +const dvui_ext = @import("./ui/dvui_ext.zig"); const SDLBackend = @import("sdl-backend"); const Document = @import("Document.zig"); const WindowContext = @import("WindowContext.zig"); @@ -82,10 +83,8 @@ fn gui_frame(ctx: *WindowContext) bool { defer root.deinit(); // Левая панель с фиксированной шириной + var left_panel = dvui.box(@src(), .{ .dir = .vertical }, .{ .expand = .vertical, .min_size_content = .{ .w = 200 }, .background = true }); { - var left_panel = dvui.box(@src(), .{ .dir = .vertical }, .{ .expand = .vertical, .min_size_content = .{ .w = 200 }, .background = true }); - defer left_panel.deinit(); - dvui.label(@src(), "Tools", .{}, .{}); if (dvui.button(@src(), "Fill Random Color", .{}, .{})) { ctx.fillRandomColor() catch |err| { @@ -93,51 +92,54 @@ fn gui_frame(ctx: *WindowContext) bool { }; } } + left_panel.deinit(); // Правая панель - занимает оставшееся пространство + const back = dvui.box( + @src(), + .{ .dir = .horizontal }, + .{ .expand = .both, .padding = dvui.Rect.all(12), .background = true }, + ); { - const back = dvui.box( + const fill_color = Color.white.opacity(0.5); + var right_panel = dvui.box( @src(), - .{ .dir = .horizontal }, - .{ .expand = .both, .padding = dvui.Rect.all(12), .background = true }, - ); - defer back.deinit(); - - { - const fill_color = Color.white.opacity(0.5); - var right_panel = dvui.box( - @src(), - .{ .dir = .vertical }, - .{ - .expand = .both, - .background = true, - .corner_radius = dvui.Rect.all(10), - .color_fill = fill_color, - }, - ); - defer right_panel.deinit(); - - const overlay = dvui.overlay(@src(), .{ + .{ .dir = .vertical }, + .{ .expand = .both, - }); - defer overlay.deinit(); + .background = true, + .padding = dvui.Rect.all(5), + .corner_radius = dvui.Rect.all(24), + .color_fill = fill_color, + }, + ); + { + var textured = dvui_ext.texturedBox(right_panel.data().contentRectScale(), dvui.Rect.all(20)); + { + const overlay = dvui.overlay(@src(), .{ .expand = .both }); + { + // Отобразить canvas внутри контейнера + if (ctx.canvas_texture) |texture| { + _ = dvui.image(@src(), .{ + .source = .{ .texture = texture }, + }, .{ + .margin = .{ .x = ctx.canvas_pos.x, .y = ctx.canvas_pos.y }, + .min_size_content = .{ + .w = @floatFromInt(ctx.canvas_width), + .h = @floatFromInt(ctx.canvas_height), + }, + }); + } - // Отобразить canvas внутри контейнера - if (ctx.canvas_texture) |texture| { - _ = dvui.image(@src(), .{ - .source = .{ .texture = texture }, - }, .{ - .expand = .both, - .min_size_content = .{ - .w = @floatFromInt(ctx.canvas_width), - .h = @floatFromInt(ctx.canvas_height), - }, - }); + dvui.label(@src(), "Canvas", .{}, .{ .gravity_x = 0.5, .gravity_y = 0.0 }); + } + overlay.deinit(); } - - dvui.label(@src(), "Canvas", .{}, .{ .gravity_x = 0.5, .gravity_y = 0.0 }); + textured.deinit(); } + right_panel.deinit(); } + back.deinit(); return true; } diff --git a/src/ui/dvui_ext.zig b/src/ui/dvui_ext.zig new file mode 100644 index 0000000..e6b37d9 --- /dev/null +++ b/src/ui/dvui_ext.zig @@ -0,0 +1,8 @@ +// Расширения для dvui +const std = @import("std"); +const dvui = @import("dvui"); +const TexturedBox = @import("./types/TexturedBox.zig"); + +pub fn texturedBox(rs: dvui.RectScale, corner_radius: dvui.Rect) TexturedBox { + return TexturedBox.init(rs, corner_radius); +} diff --git a/src/ui/types/TexturedBox.zig b/src/ui/types/TexturedBox.zig new file mode 100644 index 0000000..16b3a90 --- /dev/null +++ b/src/ui/types/TexturedBox.zig @@ -0,0 +1,38 @@ +// Отрисовка дочернего контента как текстуры с параметрами скругления +const std = @import("std"); +const dvui = @import("dvui"); +const TexturedBox = @This(); + +parent: dvui.Widget, +rs: dvui.RectScale, +pic: ?dvui.Picture, +corner_radius: dvui.Rect, + +pub fn init(rs: dvui.RectScale, corner_radius: dvui.Rect) TexturedBox { + const parent = dvui.parentGet(); + const pic = dvui.Picture.start(rs.r); + return .{ + .parent = parent, + .corner_radius = corner_radius, + .rs = rs, + .pic = pic, + }; +} + +pub fn deinit(self: *TexturedBox) void { + if (self.pic) |*picture| { + picture.stop(); + + const tex = dvui.textureFromTarget(picture.texture) catch null; + if (tex) |t| { + dvui.Texture.destroyLater(t); + // self.rs.r.y -= 2; + // self.rs.r.x -= 2; + // self.rs.r.h += 2; + // self.rs.r.w += 2; + dvui.renderTexture(t, self.rs, .{ + .corner_radius = self.corner_radius, + }) catch {}; + } + } +}