Класные таббары
This commit is contained in:
@@ -5,3 +5,5 @@ pub const ellipse = dvui.entypo.circle;
|
|||||||
pub const arc = dvui.entypo.loop;
|
pub const arc = dvui.entypo.loop;
|
||||||
pub const broken = dvui.entypo.flow_line;
|
pub const broken = dvui.entypo.flow_line;
|
||||||
pub const trash = dvui.entypo.trash;
|
pub const trash = dvui.entypo.trash;
|
||||||
|
pub const cross = dvui.entypo.cross;
|
||||||
|
pub const plus = dvui.entypo.plus;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ fn objectTreeRow(open_doc: *WindowContext.OpenDocument, obj: *Object, depth: u32
|
|||||||
if (hovered) {
|
if (hovered) {
|
||||||
const delete_opts: dvui.Options = .{
|
const delete_opts: dvui.Options = .{
|
||||||
.id_extra = row_id +% 1,
|
.id_extra = row_id +% 1,
|
||||||
.margin = dvui.Rect{ .x = 4 },
|
.margin = dvui.Rect{ .x = 4, .w = 6 },
|
||||||
.padding = dvui.Rect.all(2),
|
.padding = dvui.Rect.all(2),
|
||||||
.gravity_y = 0.5,
|
.gravity_y = 0.5,
|
||||||
.gravity_x = 1.0,
|
.gravity_x = 1.0,
|
||||||
|
|||||||
@@ -1,22 +1,112 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const dvui = @import("dvui");
|
const dvui = @import("dvui");
|
||||||
|
const icons = @import("../icons.zig");
|
||||||
const WindowContext = @import("../WindowContext.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 == .press 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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.deinit();
|
||||||
|
|
||||||
|
if (select_row) {
|
||||||
|
callback.* = .{ .select = index };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tabBar(ctx: *WindowContext) void {
|
pub fn tabBar(ctx: *WindowContext) void {
|
||||||
var bar = dvui.box(
|
var bar = dvui.box(
|
||||||
@src(),
|
@src(),
|
||||||
.{ .dir = .horizontal },
|
.{ .dir = .horizontal },
|
||||||
.{ .expand = .horizontal, .min_size_content = .{ .h = 32 }, .background = true, .padding = dvui.Rect.all(4) },
|
.{
|
||||||
|
.expand = .horizontal,
|
||||||
|
.background = true,
|
||||||
|
.padding = .{
|
||||||
|
.x = 12,
|
||||||
|
.w = 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
|
var callback: ?DocCallback = null;
|
||||||
for (ctx.documents.items, 0..) |_, i| {
|
for (ctx.documents.items, 0..) |_, i| {
|
||||||
var buf: [32]u8 = undefined;
|
documentTab(ctx, i, &callback);
|
||||||
const label = std.fmt.bufPrint(&buf, "Doc {d}", .{i + 1}) catch "Doc";
|
}
|
||||||
if (dvui.button(@src(), label, .{}, .{ .id_extra = i })) {
|
if (callback) |action| {
|
||||||
ctx.setActiveDocument(i);
|
switch (action) {
|
||||||
|
.select => |index| ctx.setActiveDocument(index),
|
||||||
|
.close => |index| ctx.closeDocument(index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dvui.button(@src(), "+", .{}, .{})) {
|
|
||||||
|
if (dvui.buttonIcon(@src(), "Create", icons.plus, .{}, .{}, .{
|
||||||
|
.gravity_y = 0,
|
||||||
|
})) {
|
||||||
ctx.addNewDocument() catch |err| {
|
ctx.addNewDocument() catch |err| {
|
||||||
std.debug.print("addNewDocument error: {}\n", .{err});
|
std.debug.print("addNewDocument error: {}\n", .{err});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user