tiny.zen.diagram.ego.layout
Defined in diagram.ego.
API (14)
Actions
Public operations.
Types and contracts
Public types and contracts.
Values and defaults
Public values and defaults.
Source
Source: lib/zen/src/diagram/ego/layout.zig
zig
const std = @import("std");const root = @import("root.zig");const model = root.model;pub const margin_width_max: u16 = 256;pub const margin_height_min: u16 = 268;pub const margin_height_max: u16 = 520;const wide_leaf_width: u16 = 640;const wide_leaf_height: u16 = 120;const wide_leaf_loop_height: u16 = 152;const wide_leaf_node_width: f32 = 150;const wide_header_y: f32 = 26;const wide_content_top: f32 = 50;const wide_content_bottom: f32 = 408;const vertical_heading_extent: f32 = 18;const vertical_heading_gap: f32 = 16;const vertical_empty_extent: f32 = 32;const vertical_item_gap: f32 = 10;const vertical_flow_gap: f32 = 28;pub const Point = struct { x: f32, y: f32,};pub const Rect = struct { x: f32, y: f32, width: f32, height: f32, pub fn centerX(self: Rect) f32 { return self.x + self.width / 2; } pub fn centerY(self: Rect) f32 { return self.y + self.height / 2; }};pub const More = struct { count: u32, href: []const u8,};pub const Content = union(enum) { node: model.Node, more: More,};pub const Item = struct { box: Rect, content: Content,};pub const Band = struct { items: [model.max_slots_per_band]Item = undefined, count: u8 = 0, heading: Point, empty: Point, pub fn slice(self: *const Band) []const Item { std.debug.assert(self.count <= model.max_slots_per_band); return self.items[0..self.count]; }};pub const Plan = struct { geometry: model.Geometry, subject: Rect, callers: Band, callees: Band, pub fn inspect(network: model.Network, surface: model.Surface) model.Error!Plan { try model.validate(network); const slot_limit = model.slotsPerBand(surface); const callers = try select(network.callers, slot_limit); const callees = try select(network.callees, slot_limit); return switch (surface) { .margin => verticalPlan(network, callers, callees), .wide => horizontalPlan(network, callers, callees), }; }};const Columns = struct { callers: Rect, subject: Rect, callees: Rect,};const Selection = struct { node_count: u8, more_count: u32, fn visibleCount(self: Selection) u8 { return self.node_count + @intFromBool(self.more_count > 0); }};fn horizontalPlan( network: model.Network, callers: Selection, callees: Selection,) Plan { const empty = network.callers.total == 0 and network.callees.total == 0; const geometry = wideGeometry(empty, network.recursive); const columns = horizontalColumns(geometry); var plan = Plan{ .geometry = geometry, .subject = columns.subject, .callers = horizontalBand(columns.callers, geometry), .callees = horizontalBand(columns.callees, geometry), }; placeBand( &plan.callers, network.callers, callers, columns.callers, horizontalFirstY(geometry, callers.visibleCount()), horizontalStep(geometry, callers.visibleCount()), ); placeBand( &plan.callees, network.callees, callees, columns.callees, horizontalFirstY(geometry, callees.visibleCount()), horizontalStep(geometry, callees.visibleCount()), ); return plan;}fn verticalPlan( network: model.Network, callers: Selection, callees: Selection,) Plan { var geometry = marginGeometry(); const center_x = @as(f32, @floatFromInt(geometry.width)) / 2; const callers_extent = verticalBandExtent(geometry, callers.visibleCount()); const callees_extent = verticalBandExtent(geometry, callees.visibleCount()); const callers_top = geometry.outer_inset + vertical_heading_extent + vertical_heading_gap; const subject_y = callers_top + callers_extent + vertical_flow_gap; const calls_header_top = subject_y + geometry.subject_height + vertical_flow_gap; const callees_top = calls_header_top + vertical_heading_extent + vertical_heading_gap; const height = callees_top + callees_extent + geometry.outer_inset; geometry.height = @intFromFloat(height); std.debug.assert(geometry.height >= margin_height_min); std.debug.assert(geometry.height <= margin_height_max); var plan = Plan{ .geometry = geometry, .subject = .{ .x = center_x - geometry.subject_width / 2, .y = subject_y, .width = geometry.subject_width, .height = geometry.subject_height, }, .callers = verticalBand(geometry, callers_top, geometry.outer_inset), .callees = verticalBand(geometry, callees_top, calls_header_top), }; const node_box = Rect{ .x = center_x - geometry.node_width / 2, .y = 0, .width = geometry.node_width, .height = geometry.node_height, }; const step = geometry.node_height + vertical_item_gap; placeBand(&plan.callers, network.callers, callers, node_box, callers_top, step); placeBand(&plan.callees, network.callees, callees, node_box, callees_top, step); return plan;}fn horizontalBand(column: Rect, geometry: model.Geometry) Band { return .{ .heading = .{ .x = column.centerX(), .y = wide_header_y }, .empty = .{ .x = column.centerX(), .y = @as(f32, @floatFromInt(geometry.height)) / 2, }, };}fn verticalBand(geometry: model.Geometry, content_y: f32, heading_top: f32) Band { const center_x = @as(f32, @floatFromInt(geometry.width)) / 2; return .{ .heading = .{ .x = center_x, .y = heading_top + geometry.heading_size }, .empty = .{ .x = center_x, .y = content_y + vertical_empty_extent / 2 }, };}fn placeBand( result: *Band, source: model.Band, selection: Selection, template: Rect, first_y: f32, step: f32,) void { result.count = selection.visibleCount(); std.debug.assert(result.count <= model.max_slots_per_band); var index: u8 = 0; while (index < selection.node_count) : (index += 1) { result.items[index] = .{ .box = placedBox(template, first_y, step, index), .content = .{ .node = source.nodes[index] }, }; } if (selection.more_count == 0) return; result.items[index] = .{ .box = placedBox(template, first_y, step, index), .content = .{ .more = .{ .count = selection.more_count, .href = source.more_href, } }, };}fn placedBox(template: Rect, first_y: f32, step: f32, index: u8) Rect { var result = template; result.y = first_y + step * @as(f32, @floatFromInt(index)); return result;}fn select(source: model.Band, slot_limit: u8) model.Error!Selection { std.debug.assert(slot_limit > 1); std.debug.assert(slot_limit <= model.max_slots_per_band); var node_count: u8 = @intCast(@min(source.nodes.len, slot_limit)); if (source.total > node_count and node_count == slot_limit) node_count -= 1; const result = Selection{ .node_count = node_count, .more_count = source.total - node_count, }; if (result.more_count > 0 and source.more_href.len == 0) { return error.MissingOverflowLink; } return result;}fn horizontalColumns(geometry: model.Geometry) Columns { const width: f32 = @floatFromInt(geometry.width); const subject_x = (width - geometry.subject_width) / 2; return .{ .callers = .{ .x = geometry.outer_inset, .y = 0, .width = geometry.node_width, .height = geometry.node_height, }, .subject = .{ .x = subject_x, .y = (@as(f32, @floatFromInt(geometry.height)) - geometry.subject_height) / 2, .width = geometry.subject_width, .height = geometry.subject_height, }, .callees = .{ .x = width - geometry.outer_inset - geometry.node_width, .y = 0, .width = geometry.node_width, .height = geometry.node_height, }, };}fn horizontalFirstY(geometry: model.Geometry, count: u8) f32 { std.debug.assert(count <= model.wide_slots_per_band); if (count == 1) { return (@as(f32, @floatFromInt(geometry.height)) - geometry.node_height) / 2; } return wide_content_top;}fn horizontalStep(geometry: model.Geometry, count: u8) f32 { std.debug.assert(count <= model.wide_slots_per_band); if (count <= 1) return 0; const span = wide_content_bottom - wide_content_top - geometry.node_height; return span / @as(f32, @floatFromInt(count - 1));}fn verticalBandExtent(geometry: model.Geometry, count: u8) f32 { std.debug.assert(count <= model.margin_slots_per_band); if (count == 0) return vertical_empty_extent; return geometry.node_height * @as(f32, @floatFromInt(count)) + vertical_item_gap * @as(f32, @floatFromInt(count - 1));}fn marginGeometry() model.Geometry { return .{ .arrangement = .vertical, .width = margin_width_max, .height = margin_height_min, .slots_per_band = model.margin_slots_per_band, .outer_inset = 8, .node_width = 208, .subject_width = 232, .node_height = 46, .subject_height = 64, .heading_size = 13, .empty_size = 12.5, .label_size = 13, .context_size = 10.5, .badge_size = 8.5, .subject_label_size = 16, };}fn wideGeometry(empty: bool, recursive: bool) model.Geometry { const leaf_height = if (recursive) wide_leaf_loop_height else wide_leaf_height; return .{ .arrangement = .horizontal, .width = if (empty) wide_leaf_width else 920, .height = if (empty) leaf_height else 420, .slots_per_band = model.wide_slots_per_band, .outer_inset = 20, .node_width = if (empty) wide_leaf_node_width else 240, .subject_width = 260, .node_height = 48, .subject_height = 72, .heading_size = 11, .empty_size = 12, .label_size = 14, .context_size = 10.5, .badge_size = 8.5, .subject_label_size = 18, };}Source: lib/zen/src/diagram/ego/root.zig:1
zig
pub const layout = @import("layout.zig");Audit
| Definitions | 15 |
|---|---|
| Public names | 17 |
| Members | 20 |
| Version | 26.7.0 |
| Revision | daab053ee433 |