From bb825d0225f6499cb5c4fc06c4f21b2005fb48b8 Mon Sep 17 00:00:00 2001 From: Roman Pytkov Date: Thu, 18 Dec 2025 21:49:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BA=D0=B0=D0=BA=D0=BE=D0=B5=20=D1=82=D0=BE?= =?UTF-8?q?=20=D1=81=D0=BA=D1=80=D0=BE=D0=BB=D0=BB=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WindowContext.zig | 11 ++++++++++ src/main.zig | 48 +++++++++++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/WindowContext.zig b/src/WindowContext.zig index c97617a..c8bd763 100644 --- a/src/WindowContext.zig +++ b/src/WindowContext.zig @@ -9,6 +9,11 @@ canvas_texture: ?dvui.Texture = null, canvas_width: u32 = 400, canvas_height: u32 = 300, canvas_pos: dvui.Point = dvui.Point{ .x = 0, .y = 0 }, +canvas_scroll: dvui.ScrollInfo = .{ + .vertical = .given, + .horizontal = .given, + .virtual_size = .{ .w = 2000, .h = 2000 }, +}, pub fn init(allocator: std.mem.Allocator) WindowContext { return .{ @@ -61,6 +66,12 @@ pub fn fillRandomColor(self: *WindowContext) !void { // Создать новую текстуру из пиксельных данных self.canvas_texture = try dvui.textureCreate(pixels, self.canvas_width, self.canvas_height, .linear); + + // Дать скроллам ощутимый диапазон сразу (минимум 2000x2000) + self.canvas_scroll.virtual_size = .{ + .w = @max(2000, @as(f32, @floatFromInt(self.canvas_width))), + .h = @max(2000, @as(f32, @floatFromInt(self.canvas_height))), + }; } /// Отобразить canvas в UI diff --git a/src/main.zig b/src/main.zig index 32fc560..d0f91ef 100644 --- a/src/main.zig +++ b/src/main.zig @@ -90,6 +90,7 @@ fn gui_frame(ctx: *WindowContext) bool { ctx.fillRandomColor() catch |err| { std.debug.print("Error filling canvas: {}\n", .{err}); }; + ctx.canvas_pos = .{ .x = 400, .y = 400 }; } } left_panel.deinit(); @@ -116,24 +117,41 @@ fn gui_frame(ctx: *WindowContext) bool { { var textured = dvui_ext.texturedBox(right_panel.data().contentRectScale(), dvui.Rect.all(20)); { - const overlay = dvui.overlay(@src(), .{ .expand = .both }); + var canvas_box = dvui.box( + @src(), + .{ .dir = .vertical }, + .{ .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), - }, - }); - } - dvui.label(@src(), "Canvas", .{}, .{ .gravity_x = 0.5, .gravity_y = 0.0 }); + + var scroll = dvui.scrollArea( + @src(), + .{ + .scroll_info = &ctx.canvas_scroll, + .vertical_bar = .auto, + .horizontal_bar = .auto, + }, + .{ .expand = .both, .background = false }, + ); + { + // Отобразить canvas внутри scroll area. + // ScrollArea сам двигает дочерние виджеты, поэтому margin не нужен. + 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), + }, + }); + } + } + scroll.deinit(); } - overlay.deinit(); + canvas_box.deinit(); } textured.deinit(); }