Files
Zivro/src/ui/tab_bar.zig

118 lines
3.7 KiB
Zig

const std = @import("std");
const dvui = @import("dvui");
const icons = @import("../icons.zig");
const WindowContext = @import("../WindowContext.zig");
const DocCallback = union(enum) {
select: usize,
close: usize,
};
fn documentTab(ctx: *WindowContext, index: usize, callback: *?DocCallback) void {
const row_id: usize = index;
const is_selected = if (ctx.active_document_index) |active| active == index else false;
const focus_color = dvui.themeGet().focus;
var row = dvui.box(
@src(),
.{ .dir = .horizontal },
.{
.id_extra = row_id,
.expand = .none,
.gravity_y = 0.5,
},
);
{
var hovered: bool = false;
var select_row: bool = false;
const row_data = row.data();
// Ручная обработка hover/click по строке без пометки события как handled,
// чтобы кнопка закрытия могла нормально получать свои события.
for (dvui.events()) |*e| {
switch (e.evt) {
.mouse => |*mouse| {
if (!dvui.eventMatchSimple(e, row_data)) continue;
hovered = true;
if (mouse.action == .release and mouse.button == .left) {
select_row = true;
}
},
else => {},
}
}
var overlay = dvui.overlay(@src(), .{
.margin = dvui.Rect{ .x = 4, .w = 4 },
.padding = dvui.Rect{ .x = 12, .y = 0, .w = 0, .h = 0 },
.background = is_selected or hovered,
.color_fill = if (is_selected) focus_color.opacity(0.35) else if (hovered) focus_color.opacity(0.18) else null,
.corner_radius = dvui.Rect.all(4),
});
{
var buf: [32]u8 = undefined;
const label = std.fmt.bufPrint(&buf, "Doc {d}", .{index + 1}) catch "Doc";
dvui.labelNoFmt(@src(), label, .{}, .{
.gravity_x = 0.5,
.gravity_y = 0.5,
.margin = .{ .w = 24 },
});
if (hovered) {
if (dvui.buttonIcon(@src(), "Close", icons.cross, .{}, .{}, .{
.id_extra = row_id +% 1,
.margin = dvui.Rect{ .x = 8, .w = 6 },
.padding = dvui.Rect.all(2),
.gravity_x = 1,
.gravity_y = 0.5,
})) {
callback.* = .{ .close = index };
select_row = false;
}
}
}
overlay.deinit();
if (select_row) {
callback.* = .{ .select = index };
}
}
row.deinit();
}
pub fn tabBar(ctx: *WindowContext) void {
var bar = dvui.box(
@src(),
.{ .dir = .horizontal },
.{
.expand = .horizontal,
.background = true,
.padding = .{
.x = 12,
.w = 12,
},
},
);
{
var callback: ?DocCallback = null;
for (ctx.documents.items, 0..) |_, i| {
documentTab(ctx, i, &callback);
}
if (callback) |action| {
switch (action) {
.select => |index| ctx.setActiveDocument(index),
.close => |index| ctx.closeDocument(index),
}
}
if (dvui.buttonIcon(@src(), "Create", icons.plus, .{}, .{}, .{
.gravity_y = 0,
})) {
ctx.addNewDocument() catch |err| {
std.debug.print("addNewDocument error: {}\n", .{err});
};
}
}
bar.deinit();
}