diff --git a/src/config.zig b/src/config.zig index f2a65e6..94ec3e9 100644 --- a/src/config.zig +++ b/src/config.zig @@ -36,6 +36,11 @@ show_fileicons: bool = true, start_debugger_on_crash: bool = false, +widget_style: WidgetStyle = .compact, +palette_style: WidgetStyle = .bars_top_bottom, +panel_style: WidgetStyle = .compact, +home_style: WidgetStyle = .bars_left_right, + include_files: []const u8 = "", pub const DigitStyle = enum { @@ -56,3 +61,25 @@ pub const IndentMode = enum { spaces, tabs, }; + +pub const WidgetType = enum { + none, + palette, + panel, + home, +}; + +pub const WidgetStyle = enum { + compact, + spacious, + boxed, + double_boxed, + rounded_boxed, + single_double_top_bottom_boxed, + single_double_left_right_boxed, + dotted_boxed, + thick_boxed, + extra_thick_boxed, + bars_top_bottom, + bars_left_right, +}; diff --git a/src/tui/Menu.zig b/src/tui/Menu.zig index 58b832b..7d51ab2 100644 --- a/src/tui/Menu.zig +++ b/src/tui/Menu.zig @@ -14,7 +14,7 @@ pub const scroll_lines = 3; pub fn Options(context: type) type { return struct { ctx: Context, - style: Widget.Style.Type, + style: Widget.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, diff --git a/src/tui/Widget.zig b/src/tui/Widget.zig index 653f2ea..2195259 100644 --- a/src/tui/Widget.zig +++ b/src/tui/Widget.zig @@ -10,6 +10,8 @@ pub const Box = @import("Box.zig"); pub const Theme = @import("theme"); pub const themes = @import("themes").themes; pub const scopes = @import("themes").scopes; +pub const Type = @import("config").WidgetType; +pub const StyleTag = @import("config").WidgetStyle; pub const Style = @import("WidgetStyle.zig"); ptr: *anyopaque, diff --git a/src/tui/WidgetList.zig b/src/tui/WidgetList.zig index 012dcd1..b799c04 100644 --- a/src/tui/WidgetList.zig +++ b/src/tui/WidgetList.zig @@ -6,6 +6,7 @@ const tp = @import("thespian"); const Plane = @import("renderer").Plane; +const tui = @import("tui.zig"); const Widget = @import("Widget.zig"); const Box = @import("Box.zig"); @@ -33,16 +34,16 @@ 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: Widget.Style.Type, +widget_type: Widget.Type, pub fn createH(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) error{OutOfMemory}!*Self { return createHStyled(allocator, parent, name, layout_, .none); } -pub fn createHStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: Widget.Style.Type) error{OutOfMemory}!*Self { +pub fn createHStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, widget_type: Widget.Type) error{OutOfMemory}!*Self { const self = try allocator.create(Self); errdefer allocator.destroy(self); - self.* = try init(allocator, parent, name, .horizontal, layout_, Box{}, style); + self.* = try init(allocator, parent, name, .horizontal, layout_, Box{}, widget_type); self.plane.hide(); return self; } @@ -51,10 +52,10 @@ pub fn createV(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: return createVStyled(allocator, parent, name, layout_, .none); } -pub fn createVStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, style: Widget.Style.Type) !*Self { +pub fn createVStyled(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout, widget_type: Widget.Type) !*Self { const self = try allocator.create(Self); errdefer allocator.destroy(self); - self.* = try init(allocator, parent, name, .vertical, layout_, Box{}, style); + self.* = try init(allocator, parent, name, .vertical, layout_, Box{}, widget_type); self.plane.hide(); return self; } @@ -67,7 +68,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: Widget.Style.Type) !Self { +fn init(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, layout_: Layout, box_: Box, widget_type: Widget.Type) !Self { var self: Self = .{ .plane = undefined, .parent = parent, @@ -75,10 +76,10 @@ fn init(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, .widgets = ArrayList(WidgetState).init(allocator), .layout_ = layout_, .direction = dir, - .style = style, + .widget_type = widget_type, .deco_box = undefined, }; - const padding = Widget.Style.from_type(self.style).padding; + const padding = tui.get_widget_style(self.widget_type).padding; self.deco_box = self.from_client_box(box_, padding); self.plane = try Plane.init(&self.deco_box.opts(name), parent); return self; @@ -163,7 +164,7 @@ 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 widget_style = tui.get_widget_style(self.widget_type); const padding = widget_style.padding; for (self.widgets.items) |*w| if (!w.layout.eql(w.widget.layout())) { self.refresh_layout(padding); @@ -192,7 +193,7 @@ 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, widget_style: *const Widget.Style) void { - const style = Widget.Style.theme_style_from_type(self.style, theme); + const style = Widget.Style.theme_style_from_type(self.widget_type, theme); const padding = widget_style.padding; const border = widget_style.border; const plane = &self.plane; @@ -297,7 +298,7 @@ fn refresh_layout(self: *Self, padding: Widget.Style.Margin) void { } pub fn handle_resize(self: *Self, box: Widget.Box) void { - const padding = Widget.Style.from_type(self.style).padding; + const padding = tui.get_widget_style(self.widget_type).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); diff --git a/src/tui/WidgetStyle.zig b/src/tui/WidgetStyle.zig index 6af0bad..4f91d71 100644 --- a/src/tui/WidgetStyle.zig +++ b/src/tui/WidgetStyle.zig @@ -1,12 +1,8 @@ padding: Margin = Margin.@"0", border: Border = Border.blank, -pub const Type = enum { - none, - palette, - panel, - home, -}; +pub const WidgetType = @import("config").WidgetType; +pub const WidgetStyle = @import("config").WidgetStyle; pub const Padding = struct { pub const Unit = u16; @@ -116,31 +112,7 @@ const bars_left_right: @This() = .{ .border = Border.@"thick box (octant)", }; -pub fn from_type(style_type: Type) *const @This() { - return switch (style_type) { - .none => none_style, - .palette => palette_style, - .panel => panel_style, - .home => home_style, - }; -} - -pub const Styles = enum { - compact, - spacious, - boxed, - double_boxed, - rounded_boxed, - single_double_top_bottom_boxed, - single_double_left_right_boxed, - dotted_boxed, - thick_boxed, - extra_thick_boxed, - bars_top_bottom, - bars_left_right, -}; - -pub fn from_tag(tag: Styles) *const @This() { +pub fn from_tag(tag: WidgetStyle) *const @This() { return switch (tag) { .compact => &compact, .spacious => &spacious, @@ -157,60 +129,9 @@ pub fn from_tag(tag: Styles) *const @This() { }; } -pub fn next_tag(tag: Styles) Styles { - const new_value = @intFromEnum(tag) + 1; - return if (new_value > @intFromEnum(Styles.bars_left_right)) .compact else @enumFromInt(new_value); -} +const Theme = @import("Widget.zig").Theme; -pub fn set_type_style(style_type: Type, tag: Styles) void { - const ref = type_style(style_type); - ref.* = from_tag(tag); -} - -pub fn set_next_style(style_type: Type) void { - const tag_ref = type_tag(style_type); - const new_tag = next_tag(tag_ref.*); - const style_ref = type_style(style_type); - tag_ref.* = new_tag; - style_ref.* = from_tag(new_tag); -} - -var none_style: *const @This() = from_tag(none_tag_default); -var palette_style: *const @This() = from_tag(palette_tag_default); -var panel_style: *const @This() = from_tag(panel_tag_default); -var home_style: *const @This() = from_tag(home_tag_default); - -fn type_style(style_type: Type) **const @This() { - return switch (style_type) { - .none => &none_style, - .palette => &palette_style, - .panel => &panel_style, - .home => &home_style, - }; -} - -const none_tag_default: Styles = .compact; -const palette_tag_default: Styles = .compact; -const panel_tag_default: Styles = .compact; -const home_tag_default: Styles = .compact; - -var none_tag: Styles = none_tag_default; -var palette_tag: Styles = palette_tag_default; -var panel_tag: Styles = panel_tag_default; -var home_tag: Styles = home_tag_default; - -fn type_tag(style_type: Type) *Styles { - return switch (style_type) { - .none => &none_tag, - .palette => &palette_tag, - .panel => &panel_tag, - .home => &home_tag, - }; -} - -const Widget = @import("Widget.zig"); - -pub fn theme_style_from_type(style_type: Type, theme: *const Widget.Theme) Widget.Theme.Style { +pub fn theme_style_from_type(style_type: WidgetType, theme: *const Theme) Theme.Style { return switch (style_type) { .none => theme.editor, .palette => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor_widget.bg }, diff --git a/src/tui/filelist_view.zig b/src/tui/filelist_view.zig index 4108be0..7544dce 100644 --- a/src/tui/filelist_view.zig +++ b/src/tui/filelist_view.zig @@ -36,7 +36,7 @@ selected: ?usize = null, box: Widget.Box = .{}, const path_column_ratio = 4; -const widget_style_type: Widget.Style.Type = .panel; +const widget_type: Widget.Type = .panel; const Entry = struct { path: []const u8, @@ -58,7 +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, + .style = widget_type, .on_render = handle_render_menu, .on_scroll = EventHandler.bind(self, Self.handle_scroll), .on_click4 = mouse_click_button4, @@ -87,7 +87,7 @@ 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; + const padding = tui.get_widget_style(widget_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; diff --git a/src/tui/home.zig b/src/tui/home.zig index b1ffcdf..fb785e3 100644 --- a/src/tui/home.zig +++ b/src/tui/home.zig @@ -81,7 +81,7 @@ home_style_bufs: [][]const u8, const Self = @This(); -const widget_style_type: Widget.Style.Type = .home; +const widget_type: Widget.Type = .home; pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { const logger = log.logger("home"); @@ -101,7 +101,7 @@ pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { .plane = n, .menu = try Menu.create(*Self, allocator, w.plane.*, .{ .ctx = self, - .style = widget_style_type, + .style = widget_type, .on_render = menu_on_render, }), .input_namespace = keybind.get_namespace(), @@ -125,7 +125,7 @@ pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { self.max_desc_len = @max(self.max_desc_len, description.len + hint.len + 5); try self.add_menu_command(command_name, description, hint, self.menu); } - const padding = Widget.Style.from_type(widget_style_type).padding; + const padding = tui.get_widget_style(widget_type).padding; self.menu_len = self.menu_count + padding.top + padding.bottom; self.position_menu(15, 9); return w; @@ -155,7 +155,7 @@ 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(); - const padding = Widget.Style.from_type(widget_style_type).padding; + const padding = tui.get_widget_style(widget_type).padding; self.menu_label_max = @max(self.menu_label_max, label.len); self.menu_w = self.menu_label_max + 2 + padding.left + padding.right; } @@ -401,11 +401,12 @@ const cmds = struct { pub const home_menu_activate_meta: Meta = .{}; pub fn home_next_widget_style(self: *Self, _: Ctx) Result { - Widget.Style.set_next_style(widget_style_type); - const padding = Widget.Style.from_type(widget_style_type).padding; + tui.set_next_style(widget_type); + const padding = tui.get_widget_style(widget_type).padding; self.menu_len = self.menu_count + padding.top + padding.bottom; self.menu_w = self.menu_label_max + 2 + padding.left + padding.right; tui.need_render(); + try tui.save_config(); } pub const home_next_widget_style_meta: Meta = .{}; diff --git a/src/tui/mode/overlay/open_recent.zig b/src/tui/mode/overlay/open_recent.zig index 6126315..cd934da 100644 --- a/src/tui/mode/overlay/open_recent.zig +++ b/src/tui/mode/overlay/open_recent.zig @@ -23,7 +23,7 @@ const ModalBackground = @import("../../ModalBackground.zig"); const Self = @This(); const max_recent_files: usize = 25; -const widget_style_type: Widget.Style.Type = .palette; +const widget_type: Widget.Type = .palette; allocator: std.mem.Allocator, f: usize = 0, @@ -49,7 +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, + .style = widget_type, .on_render = on_render_menu, .prepare_resize = prepare_resize_menu, }), @@ -371,9 +371,10 @@ const cmds = struct { pub const overlay_toggle_inputview_meta: Meta = .{}; pub fn overlay_next_widget_style(self: *Self, _: Ctx) Result { - Widget.Style.set_next_style(widget_style_type); + tui.set_next_style(widget_type); self.do_resize(); tui.need_render(); + try tui.save_config(); } pub const overlay_next_widget_style_meta: Meta = .{}; diff --git a/src/tui/mode/overlay/palette.zig b/src/tui/mode/overlay/palette.zig index d5c2472..cfadc52 100644 --- a/src/tui/mode/overlay/palette.zig +++ b/src/tui/mode/overlay/palette.zig @@ -20,7 +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; +const widget_type: Widget.Type = .palette; pub fn Create(options: type) type { return struct { @@ -58,7 +58,7 @@ pub fn Create(options: type) type { }), .menu = try Menu.create(*Self, allocator, tui.plane(), .{ .ctx = self, - .style = widget_style_type, + .style = widget_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, @@ -256,7 +256,7 @@ pub fn Create(options: type) type { var i = n; while (i > 0) : (i -= 1) self.menu.select_down(); - const padding = Widget.Style.from_type(widget_style_type).padding; + const padding = tui.get_widget_style(widget_type).padding; self.do_resize(padding); tui.refresh_hover(); self.selection_updated(); @@ -533,10 +533,11 @@ pub fn Create(options: type) type { pub const overlay_toggle_inputview_meta: Meta = .{}; pub fn overlay_next_widget_style(self: *Self, _: Ctx) Result { - Widget.Style.set_next_style(widget_style_type); - const padding = Widget.Style.from_type(widget_style_type).padding; + tui.set_next_style(widget_type); + const padding = tui.get_widget_style(widget_type).padding; self.do_resize(padding); tui.need_render(); + try tui.save_config(); } pub const overlay_next_widget_style_meta: Meta = .{}; diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 416dc50..f2b2549 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -1562,3 +1562,39 @@ fn load_theme_file_internal(allocator: std.mem.Allocator, theme_name: []const u8 defer allocator.free(json_str); return try std.json.parseFromSlice(Widget.Theme, allocator, json_str, .{ .allocate = .alloc_always }); } + +pub const WidgetType = @import("config").WidgetType; +pub const ConfigWidgetStyle = @import("config").WidgetStyle; +pub const WidgetStyle = @import("WidgetStyle.zig"); + +pub fn get_widget_style(widget_type: WidgetType) *const WidgetStyle { + const config_ = config(); + return switch (widget_type) { + .none => WidgetStyle.from_tag(config_.widget_style), + .palette => WidgetStyle.from_tag(config_.palette_style), + .panel => WidgetStyle.from_tag(config_.panel_style), + .home => WidgetStyle.from_tag(config_.home_style), + }; +} + +pub fn set_next_style(widget_type: WidgetType) void { + const ref = widget_type_config_variable(widget_type); + ref.* = next_widget_style(ref.*); + const self = current(); + self.logger.print("{s} style {s}", .{ @tagName(widget_type), @tagName(ref.*) }); +} + +fn next_widget_style(tag: ConfigWidgetStyle) ConfigWidgetStyle { + const new_value = @intFromEnum(tag) + 1; + return if (new_value > @intFromEnum(ConfigWidgetStyle.bars_left_right)) .compact else @enumFromInt(new_value); +} + +fn widget_type_config_variable(widget_type: WidgetType) *ConfigWidgetStyle { + const config_ = config_mut(); + return switch (widget_type) { + .none => &config_.widget_style, + .palette => &config_.palette_style, + .panel => &config_.panel_style, + .home => &config_.home_style, + }; +}