diff --git a/src/tui/Menu.zig b/src/tui/Menu.zig index 601c4e3..58b832b 100644 --- a/src/tui/Menu.zig +++ b/src/tui/Menu.zig @@ -14,6 +14,7 @@ pub const scroll_lines = 3; pub fn Options(context: type) type { return struct { ctx: Context, + style: Widget.Style.Type, on_click: *const fn (ctx: context, button: *Button.State(*State(Context))) void = do_nothing, on_click4: *const fn (menu: **State(Context), button: *Button.State(*State(Context))) void = do_nothing_click, @@ -60,7 +61,7 @@ pub fn Options(context: type) type { pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) !*State(ctx_type) { const self = try allocator.create(State(ctx_type)); errdefer allocator.destroy(self); - const container = try WidgetList.createHStyled(allocator, parent, @typeName(@This()), .dynamic, Widget.Style.thick_boxed); + const container = try WidgetList.createHStyled(allocator, parent, @typeName(@This()), .dynamic, opts.style); self.* = .{ .allocator = allocator, .menu = try WidgetList.createV(allocator, container.plane, @typeName(@This()), .dynamic), diff --git a/src/tui/WidgetList.zig b/src/tui/WidgetList.zig index 96fb03c..012dcd1 100644 --- a/src/tui/WidgetList.zig +++ b/src/tui/WidgetList.zig @@ -33,13 +33,13 @@ after_render: *const fn (ctx: ?*anyopaque, theme: *const Widget.Theme) void = on prepare_resize: *const fn (ctx: ?*anyopaque, self: *Self, box: Widget.Box) Widget.Box = prepare_resize_default, after_resize: *const fn (ctx: ?*anyopaque, self: *Self, box: Widget.Box) void = after_resize_default, on_layout: *const fn (ctx: ?*anyopaque, self: *Self) Widget.Layout = on_layout_default, -style: *const Widget.Style, +style: Widget.Style.Type, pub fn createH(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) error{OutOfMemory}!*Self { - return createHStyled(allocator, parent, name, layout_, Widget.Style.default); + return createHStyled(allocator, parent, name, layout_, .none); } -pub fn createHStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: *const Widget.Style) error{OutOfMemory}!*Self { +pub fn createHStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: Widget.Style.Type) error{OutOfMemory}!*Self { const self = try allocator.create(Self); errdefer allocator.destroy(self); self.* = try init(allocator, parent, name, .horizontal, layout_, Box{}, style); @@ -48,10 +48,10 @@ pub fn createHStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, la } pub fn createV(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) !*Self { - return createVStyled(allocator, parent, name, layout_, Widget.Style.default); + return createVStyled(allocator, parent, name, layout_, .none); } -pub fn createVStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: *const Widget.Style) !*Self { +pub fn createVStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: Widget.Style.Type) !*Self { const self = try allocator.create(Self); errdefer allocator.destroy(self); self.* = try init(allocator, parent, name, .vertical, layout_, Box{}, style); @@ -67,7 +67,7 @@ pub fn createBox(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: D return self; } -fn init(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, layout_: Layout, box_: Box, style: *const Widget.Style) !Self { +fn init(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, layout_: Layout, box_: Box, style: Widget.Style.Type) !Self { var self: Self = .{ .plane = undefined, .parent = parent, @@ -78,7 +78,8 @@ fn init(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, .style = style, .deco_box = undefined, }; - self.deco_box = self.from_client_box(box_); + const padding = Widget.Style.from_type(self.style).padding; + self.deco_box = self.from_client_box(box_, padding); self.plane = try Plane.init(&self.deco_box.opts(name), parent); return self; } @@ -162,15 +163,17 @@ pub fn update(self: *Self) void { } pub fn render(self: *Self, theme: *const Widget.Theme) bool { + const widget_style = Widget.Style.from_type(self.style); + const padding = widget_style.padding; for (self.widgets.items) |*w| if (!w.layout.eql(w.widget.layout())) { - self.refresh_layout(); + self.refresh_layout(padding); break; }; self.on_render(self.ctx, theme); - self.render_decoration(theme); + self.render_decoration(theme, widget_style); - const client_box = self.to_client_box(self.deco_box); + const client_box = self.to_client_box(self.deco_box, padding); var more = false; for (self.widgets.items) |*w| { @@ -188,12 +191,12 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool { fn on_render_default(_: ?*anyopaque, _: *const Widget.Theme) void {} -fn render_decoration(self: *Self, theme: *const Widget.Theme) void { - const style = theme.editor_gutter_modified; +fn render_decoration(self: *Self, theme: *const Widget.Theme, widget_style: *const Widget.Style) void { + const style = Widget.Style.theme_style_from_type(self.style, theme); + const padding = widget_style.padding; + const border = widget_style.border; const plane = &self.plane; const box = self.deco_box; - const padding = self.style.padding; - const border = self.style.border; plane.set_style(style); plane.fill(" "); @@ -289,19 +292,19 @@ fn get_loc_b(self: *Self, pos: *Widget.Box) *usize { }; } -fn refresh_layout(self: *Self) void { - return self.handle_resize(self.to_client_box(self.deco_box)); +fn refresh_layout(self: *Self, padding: Widget.Style.Margin) void { + return self.handle_resize(self.to_client_box(self.deco_box, padding)); } pub fn handle_resize(self: *Self, box: Widget.Box) void { - const client_box_ = self.prepare_resize(self.ctx, self, self.to_client_box(box)); - self.deco_box = self.from_client_box(client_box_); - self.do_resize(); - self.after_resize(self.ctx, self, self.to_client_box(self.deco_box)); + const padding = Widget.Style.from_type(self.style).padding; + const client_box_ = self.prepare_resize(self.ctx, self, self.to_client_box(box, padding)); + self.deco_box = self.from_client_box(client_box_, padding); + self.do_resize(padding); + self.after_resize(self.ctx, self, self.to_client_box(self.deco_box, padding)); } -pub inline fn to_client_box(self: *const Self, box_: Widget.Box) Widget.Box { - const padding = self.style.padding; +pub inline fn to_client_box(_: *const Self, box_: Widget.Box, padding: Widget.Style.Margin) Widget.Box { const total_y_padding = padding.top + padding.bottom; const total_x_padding = padding.left + padding.right; var box = box_; @@ -312,8 +315,7 @@ pub inline fn to_client_box(self: *const Self, box_: Widget.Box) Widget.Box { return box; } -inline fn from_client_box(self: *const Self, box_: Widget.Box) Widget.Box { - const padding = self.style.padding; +inline fn from_client_box(_: *const Self, box_: Widget.Box, padding: Widget.Style.Margin) Widget.Box { const total_y_padding = padding.top + padding.bottom; const total_x_padding = padding.left + padding.right; const y = if (box_.y < padding.top) padding.top else box_.y; @@ -340,8 +342,8 @@ pub fn resize(self: *Self, box: Widget.Box) void { return self.handle_resize(box); } -fn do_resize(self: *Self) void { - const client_box = self.to_client_box(self.deco_box); +fn do_resize(self: *Self, padding: Widget.Style.Margin) void { + const client_box = self.to_client_box(self.deco_box, padding); const deco_box = self.deco_box; self.plane.move_yx(@intCast(deco_box.y), @intCast(deco_box.x)) catch return; self.plane.resize_simple(@intCast(deco_box.h), @intCast(deco_box.w)) catch return; diff --git a/src/tui/WidgetStyle.zig b/src/tui/WidgetStyle.zig index 5a94afa..818c913 100644 --- a/src/tui/WidgetStyle.zig +++ b/src/tui/WidgetStyle.zig @@ -1,7 +1,13 @@ padding: Margin = Margin.@"0", -inner_padding: Margin = Margin.@"0", border: Border = Border.blank, +pub const Type = enum { + none, + palette, + panel, + home, +}; + pub const Padding = struct { pub const Unit = u16; }; @@ -69,13 +75,33 @@ pub const thick_boxed_static: @This() = .{ pub const thick_boxed = &thick_boxed_static; pub const bars_top_bottom_static: @This() = .{ - .padding = Margin.top_bottom_1, - .border = Border.thick_box, + .padding = Margin.@"top/bottom/1", + .border = Border.@"thick box (octant)", }; pub const bars_top_bottom = &bars_top_bottom_static; pub const bars_left_right_static: @This() = .{ - .padding = Margin.left_right_1, + .padding = Margin.@"left/right/1", .border = Border.box, }; pub const bars_left_right = &bars_left_right_static; + +pub fn from_type(style_type: Type) *const @This() { + return switch (style_type) { + .none => default, + .palette => thick_boxed, + .panel => default, + .home => default, + }; +} + +const Widget = @import("Widget.zig"); + +pub fn theme_style_from_type(style_type: Type, theme: *const Widget.Theme) Widget.Theme.Style { + return switch (style_type) { + .none => theme.editor, + .palette => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor_widget.bg }, + .panel => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor.bg }, + .home => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor.bg }, + }; +} diff --git a/src/tui/filelist_view.zig b/src/tui/filelist_view.zig index cc1e289..2e65a0c 100644 --- a/src/tui/filelist_view.zig +++ b/src/tui/filelist_view.zig @@ -36,6 +36,7 @@ selected: ?usize = null, box: Widget.Box = .{}, const path_column_ratio = 4; +const widget_style_type: Widget.Style.Type = .panel; const Entry = struct { path: []const u8, @@ -57,6 +58,7 @@ pub fn create(allocator: Allocator, parent: Plane) !Widget { .entries = std.ArrayList(Entry).init(allocator), .menu = try Menu.create(*Self, allocator, tui.plane(), .{ .ctx = self, + .style = widget_style_type, .on_render = handle_render_menu, .on_scroll = EventHandler.bind(self, Self.handle_scroll), .on_click4 = mouse_click_button4, @@ -85,11 +87,12 @@ fn scrollbar_style(sb: *scrollbar_v, theme: *const Widget.Theme) Widget.Theme.St } pub fn handle_resize(self: *Self, pos: Widget.Box) void { + const padding = Widget.Style.from_type(widget_style_type).padding; self.plane.move_yx(@intCast(pos.y), @intCast(pos.x)) catch return; self.plane.resize_simple(@intCast(pos.h), @intCast(pos.w)) catch return; self.box = pos; self.menu.container.resize(self.box); - const client_box = self.menu.container.to_client_box(pos); + const client_box = self.menu.container.to_client_box(pos, padding); self.view_rows = client_box.h; self.view_cols = client_box.w; self.update_scrollbar(); diff --git a/src/tui/home.zig b/src/tui/home.zig index 198d68f..686c411 100644 --- a/src/tui/home.zig +++ b/src/tui/home.zig @@ -79,6 +79,8 @@ home_style_bufs: [][]const u8, const Self = @This(); +const widget_style_type: Widget.Style.Type = .home; + pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { const logger = log.logger("home"); const self = try allocator.create(Self); @@ -95,7 +97,11 @@ pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { .allocator = allocator, .parent = parent.plane.*, .plane = n, - .menu = try Menu.create(*Self, allocator, w.plane.*, .{ .ctx = self, .on_render = menu_on_render }), + .menu = try Menu.create(*Self, allocator, w.plane.*, .{ + .ctx = self, + .style = widget_style_type, + .on_render = menu_on_render, + }), .input_namespace = keybind.get_namespace(), .home_style = home_style, .home_style_bufs = home_style_bufs, @@ -145,7 +151,8 @@ fn add_menu_command(self: *Self, command_name: []const u8, description: []const _ = try writer.write(leader); try writer.print(" :{s}", .{hint}); const label = fis.getWritten(); - self.menu_w = @max(self.menu_w, label.len + 1 + menu.container.style.padding.left + menu.container.style.padding.right); + const padding = Widget.Style.from_type(widget_style_type).padding; + self.menu_w = @max(self.menu_w, label.len + 1 + padding.left + padding.right); } var value = std.ArrayList(u8).init(self.allocator); diff --git a/src/tui/mode/overlay/open_recent.zig b/src/tui/mode/overlay/open_recent.zig index 499c229..0582129 100644 --- a/src/tui/mode/overlay/open_recent.zig +++ b/src/tui/mode/overlay/open_recent.zig @@ -23,6 +23,7 @@ const ModalBackground = @import("../../ModalBackground.zig"); const Self = @This(); const max_recent_files: usize = 25; +const widget_style_type: Widget.Style.Type = .palette; allocator: std.mem.Allocator, f: usize = 0, @@ -48,6 +49,7 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode { .modal = try ModalBackground.create(*Self, allocator, tui.mainview_widget(), .{ .ctx = self }), .menu = try Menu.create(*Self, allocator, tui.plane(), .{ .ctx = self, + .style = widget_style_type, .on_render = on_render_menu, .prepare_resize = prepare_resize_menu, }), diff --git a/src/tui/mode/overlay/palette.zig b/src/tui/mode/overlay/palette.zig index d85b1c9..caa79c1 100644 --- a/src/tui/mode/overlay/palette.zig +++ b/src/tui/mode/overlay/palette.zig @@ -20,6 +20,7 @@ const ModalBackground = @import("../../ModalBackground.zig"); pub const Menu = @import("../../Menu.zig"); const max_menu_width = 80; +const widget_style_type: Widget.Style.Type = .palette; pub fn Create(options: type) type { return struct { @@ -57,6 +58,7 @@ pub fn Create(options: type) type { }), .menu = try Menu.create(*Self, allocator, tui.plane(), .{ .ctx = self, + .style = widget_style_type, .on_render = if (@hasDecl(options, "on_render_menu")) options.on_render_menu else on_render_menu, .prepare_resize = prepare_resize_menu, .after_resize = after_resize_menu, @@ -169,9 +171,9 @@ pub fn Create(options: type) type { // self.start_query(0) catch {}; } - fn do_resize(self: *Self) void { + fn do_resize(self: *Self, padding: Widget.Style.Margin) void { const box = self.prepare_resize(); - self.menu.resize(self.menu.container.to_client_box(box)); + self.menu.resize(self.menu.container.to_client_box(box, padding)); self.after_resize(); } @@ -253,7 +255,8 @@ pub fn Create(options: type) type { var i = n; while (i > 0) : (i -= 1) self.menu.select_down(); - self.do_resize(); + const padding = Widget.Style.from_type(widget_style_type).padding; + self.do_resize(padding); tui.refresh_hover(); self.selection_updated(); }