initial commit
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 30s
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 30s
This commit is contained in:
103
src/layout/Framing.zig
Normal file
103
src/layout/Framing.zig
Normal file
@@ -0,0 +1,103 @@
|
||||
//! Framing layout for a nested `Layout`s or `Widget`s.
|
||||
//!
|
||||
//! # Example
|
||||
//! ...
|
||||
const std = @import("std");
|
||||
const terminal = @import("../terminal.zig");
|
||||
|
||||
const isTaggedUnion = @import("../event.zig").isTaggedUnion;
|
||||
const Error = @import("../event.zig").Error;
|
||||
const Key = terminal.Key;
|
||||
|
||||
const log = std.log.scoped(.layout_framing);
|
||||
|
||||
pub fn Layout(comptime Event: type) type {
|
||||
if (!isTaggedUnion(Event)) {
|
||||
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
||||
}
|
||||
const Element = union(enum) {
|
||||
layout: @import("../layout.zig").Layout(Event),
|
||||
widget: @import("../widget.zig").Widget(Event),
|
||||
};
|
||||
const Events = std.ArrayList(Event);
|
||||
const Contents = std.ArrayList(u8);
|
||||
return struct {
|
||||
size: terminal.Size = undefined,
|
||||
contents: Contents = undefined,
|
||||
element: Element = undefined,
|
||||
events: Events = undefined,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, element: Element) @This() {
|
||||
return .{
|
||||
.contents = Contents.init(allocator),
|
||||
.element = element,
|
||||
.events = Events.init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.contents.deinit();
|
||||
this.events.deinit();
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle(this: *@This(), event: Event) !*Events {
|
||||
this.events.clearRetainingCapacity();
|
||||
// order is important
|
||||
switch (event) {
|
||||
.resize => |size| {
|
||||
this.size = size;
|
||||
// adjust size according to the containing elements
|
||||
const sub_event = event;
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
else => {
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
return &this.events;
|
||||
}
|
||||
|
||||
pub fn content(this: *@This()) !*Contents {
|
||||
this.contents.clearRetainingCapacity();
|
||||
// TODO: padding contents accordingly
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
const layout_content = try layout.content();
|
||||
try this.contents.appendSlice(layout_content.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
try this.contents.appendSlice(try widget.content());
|
||||
},
|
||||
}
|
||||
return &this.contents;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user