Compare commits

...

3 commits

Author SHA1 Message Date
b97b8e8fb7
feat: auto hide tabs widget if there are less than {n} tabs
This can be configured via an integer argument in the bar widget descriptor, or
via the tab styles configuration file. A value of 0 will effectively disable
auto hide.
2025-08-03 17:08:53 +02:00
dfcc825e4b
feat: auto hide bars with empty widget layouts 2025-08-03 16:17:05 +02:00
ce204d650a
feat: add WidgetList support for overriding layouts 2025-08-03 16:16:15 +02:00
3 changed files with 30 additions and 5 deletions

View file

@ -24,12 +24,14 @@ parent: Plane,
allocator: Allocator,
widgets: ArrayList(WidgetState),
layout_: Layout,
layout_empty: bool = true,
direction: Direction,
box: ?Widget.Box = null,
ctx: ?*anyopaque = null,
on_render: *const fn (ctx: ?*anyopaque, theme: *const Widget.Theme) void = on_render_default,
after_render: *const fn (ctx: ?*anyopaque, theme: *const Widget.Theme) void = on_render_default,
on_resize: *const fn (ctx: ?*anyopaque, self: *Self, pos_: Widget.Box) void = on_resize_default,
on_layout: *const fn (ctx: ?*anyopaque, self: *Self) Widget.Layout = on_layout_default,
pub fn createH(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) error{OutOfMemory}!*Self {
const self = try allocator.create(Self);
@ -71,7 +73,7 @@ pub fn widget(self: *Self) Widget {
}
pub fn layout(self: *Self) Widget.Layout {
return self.layout_;
return self.on_layout(self.ctx, self);
}
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
@ -214,6 +216,10 @@ fn on_resize_default(_: ?*anyopaque, self: *Self, pos: Widget.Box) void {
self.resize(pos);
}
fn on_layout_default(_: ?*anyopaque, self: *Self) Widget.Layout {
return self.layout_;
}
pub fn resize(self: *Self, pos_: Widget.Box) void {
self.box = pos_;
var pos = pos_;
@ -235,6 +241,7 @@ pub fn resize(self: *Self, pos_: Widget.Box) void {
},
}
}
self.layout_empty = avail == total and dynamics == 0;
const dyn_size = avail / if (dynamics > 0) dynamics else 1;
const rounded: usize = if (dyn_size * dynamics < avail) avail - dyn_size * dynamics else 0;

View file

@ -12,6 +12,7 @@ pub fn create(allocator: std.mem.Allocator, parent: Plane, config: []const u8, s
var w = try WidgetList.createH(allocator, parent, "statusbar", .{ .static = 1 });
if (style == .grip) w.after_render = render_grip;
w.ctx = w;
w.on_layout = on_layout;
var it = std.mem.splitScalar(u8, config, ' ');
while (it.next()) |widget_name| {
try w.add(status_widget.create(widget_name, allocator, w.plane, event_handler) catch |e| switch (e) {
@ -22,6 +23,13 @@ pub fn create(allocator: std.mem.Allocator, parent: Plane, config: []const u8, s
return w.widget();
}
fn on_layout(_: ?*anyopaque, w: *WidgetList) Widget.Layout {
return if (w.layout_empty)
.{ .static = 0 }
else
.{ .static = 1 };
}
fn render_grip(ctx: ?*anyopaque, theme: *const Widget.Theme) void {
const w: *WidgetList = @ptrCast(@alignCast(ctx.?));
if (w.hover()) {

View file

@ -11,7 +11,11 @@ const Widget = @import("../Widget.zig");
const WidgetList = @import("../WidgetList.zig");
const Button = @import("../Button.zig");
const default_min_tabs = 2;
const @"style.config" = struct {
default_minimum_tabs_shown: usize = 2,
dirty_indicator: []const u8 = "",
spacer: []const u8 = "|",
@ -52,10 +56,11 @@ const @"style.config" = struct {
};
pub const Style = @"style.config";
pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget {
pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler, arg: ?[]const u8) @import("widget.zig").CreateError!Widget {
const min_tabs = if (arg) |str_size| std.fmt.parseInt(usize, str_size, 10) catch null else null;
const self = try allocator.create(TabBar);
errdefer allocator.destroy(self);
self.* = try TabBar.init(allocator, parent, event_handler);
self.* = try TabBar.init(allocator, parent, event_handler, min_tabs);
return Widget.to(self);
}
@ -67,6 +72,7 @@ const TabBar = struct {
event_handler: ?EventHandler,
tabs: []TabBarTab = &[_]TabBarTab{},
active_buffer_ref: ?usize = null,
minimum_tabs_shown: usize,
tab_style: Style,
tab_style_bufs: [][]const u8,
@ -78,7 +84,7 @@ const TabBar = struct {
widget: Widget,
};
fn init(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler) !Self {
fn init(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler, min_tabs: ?usize) !Self {
var w = try WidgetList.createH(allocator, parent, "tabs", .dynamic);
w.ctx = w;
const tab_style, const tab_style_bufs = root.read_config(Style, allocator);
@ -90,6 +96,7 @@ const TabBar = struct {
.event_handler = event_handler,
.tab_style = tab_style,
.tab_style_bufs = tab_style_bufs,
.minimum_tabs_shown = min_tabs orelse tab_style.default_minimum_tabs_shown,
};
}
@ -101,7 +108,10 @@ const TabBar = struct {
}
pub fn layout(self: *Self) Widget.Layout {
return self.widget_list_widget.layout();
return if (self.tabs.len >= self.minimum_tabs_shown)
self.widget_list_widget.layout()
else
.{ .static = 0 };
}
pub fn update(self: *Self) void {