начало дерева объектов
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
const std = @import("std");
|
||||
const dvui = @import("dvui");
|
||||
const WindowContext = @import("../WindowContext.zig");
|
||||
const Document = @import("../models/Document.zig");
|
||||
const icons = @import("../icons.zig");
|
||||
const Object = Document.Object;
|
||||
|
||||
const panel_gap: f32 = 12;
|
||||
@@ -8,6 +10,11 @@ const panel_padding: f32 = 5;
|
||||
const panel_radius: f32 = 24;
|
||||
const fill_color = dvui.Color.black.opacity(0.2);
|
||||
|
||||
const ObjectTreeCallback = union(enum) {
|
||||
select: *Object,
|
||||
delete: *Object,
|
||||
};
|
||||
|
||||
fn shapeLabel(shape: Object.ShapeKind) []const u8 {
|
||||
return switch (shape) {
|
||||
.line => "Line",
|
||||
@@ -17,34 +24,92 @@ fn shapeLabel(shape: Object.ShapeKind) []const u8 {
|
||||
};
|
||||
}
|
||||
|
||||
fn objectTreeRow(obj: *const Object, depth: u32, row_id: *usize) void {
|
||||
const id = row_id.*;
|
||||
row_id.* += 1;
|
||||
fn objectTreeRow(open_doc: *WindowContext.OpenDocument, obj: *Object, depth: u32, object_callback: *?ObjectTreeCallback) void {
|
||||
const indent_px = depth * 18;
|
||||
const is_selected: bool = open_doc.selected_object == obj;
|
||||
const row_id = @intFromPtr(obj);
|
||||
|
||||
const focus_color = dvui.themeGet().focus;
|
||||
|
||||
// Визуально строка — это box с подсветкой по hover/selected, а не кнопка.
|
||||
var row = dvui.box(
|
||||
@src(),
|
||||
.{ .dir = .horizontal },
|
||||
.{ .padding = dvui.Rect{ .x = @floatFromInt(indent_px) }, .id_extra = id },
|
||||
.{
|
||||
.id_extra = row_id,
|
||||
.expand = .horizontal,
|
||||
// Постоянной рамки нет; лёгкая заливка по hover и более яркая по selected.
|
||||
// .color_fill = if (is_selected) focus_color.opacity(0.35) else null,
|
||||
.color_fill_hover = focus_color.opacity(0.18),
|
||||
},
|
||||
);
|
||||
{
|
||||
dvui.labelNoFmt(@src(), shapeLabel(obj.shape), .{}, .{ .id_extra = id });
|
||||
var hovered: bool = false;
|
||||
const row_data = row.data();
|
||||
if (dvui.clicked(row_data, .{
|
||||
.hovered = &hovered,
|
||||
})) {
|
||||
object_callback.* = .{ .select = obj };
|
||||
}
|
||||
|
||||
const background = is_selected or hovered;
|
||||
var content = dvui.box(@src(), .{ .dir = .horizontal }, .{
|
||||
.expand = .horizontal,
|
||||
.margin = dvui.Rect{ .x = @floatFromInt(indent_px) },
|
||||
.background = background,
|
||||
.color_fill = if (is_selected) focus_color.opacity(0.35) else if (hovered) focus_color.opacity(0.18) else null,
|
||||
});
|
||||
{
|
||||
dvui.labelNoFmt(
|
||||
@src(),
|
||||
shapeLabel(obj.shape),
|
||||
.{},
|
||||
.{ .id_extra = row_id, .expand = .horizontal },
|
||||
);
|
||||
|
||||
if (is_selected or hovered) {
|
||||
const delete_opts: dvui.Options = .{
|
||||
.id_extra = row_id +% 1,
|
||||
.margin = dvui.Rect{ .x = 4 },
|
||||
.padding = dvui.Rect.all(2),
|
||||
.gravity_y = 0.5,
|
||||
.gravity_x = 1.0,
|
||||
};
|
||||
if (dvui.buttonIcon(@src(), "Delete object", icons.trash, .{}, .{}, delete_opts)) {
|
||||
object_callback.* = .{ .delete = obj };
|
||||
}
|
||||
}
|
||||
}
|
||||
content.deinit();
|
||||
}
|
||||
row.deinit();
|
||||
for (obj.children.items) |*child| {
|
||||
objectTreeRow(child, depth + 1, row_id);
|
||||
objectTreeRow(open_doc, child, depth + 1, object_callback);
|
||||
}
|
||||
}
|
||||
|
||||
fn objectTree(ctx: *WindowContext) void {
|
||||
const active_doc = ctx.activeDocument();
|
||||
var object_callback: ?ObjectTreeCallback = null;
|
||||
if (active_doc) |open_doc| {
|
||||
const doc = &open_doc.document;
|
||||
if (doc.objects.items.len == 0) {
|
||||
dvui.label(@src(), "No objects", .{}, .{});
|
||||
} else {
|
||||
var row_id: usize = 0;
|
||||
for (doc.objects.items) |*obj| {
|
||||
objectTreeRow(obj, 0, &row_id);
|
||||
objectTreeRow(open_doc, obj, 0, &object_callback);
|
||||
}
|
||||
}
|
||||
if (object_callback) |callback| {
|
||||
switch (callback) {
|
||||
.select => |obj| {
|
||||
open_doc.selected_object = obj;
|
||||
},
|
||||
.delete => |obj| {
|
||||
_ = doc.removeObject(obj);
|
||||
open_doc.selected_object = null;
|
||||
open_doc.canvas.requestRedraw();
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user