feat(model): implement Elm architecture
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m2s
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m2s
Now the `App` contains a state which is a user-defined `struct` which is passed to the `handle` and `contents` callbacks for `Container`'s and `Element`'s. Built-in `Element`'s shall not access the `App.Model` and should therefore never cause any side-effects. User-defined events shall be used to act as *messages* to cause potential side-effects for the model. This is the reason why only the `handle` callback has a non-const pointer to the `App.Model`. The `contents` callback can only access the `App.Model` read-only to use for generating the *view* (in context of the elm architecture).
This commit is contained in:
308
src/element.zig
308
src/element.zig
@@ -9,7 +9,7 @@
|
||||
// FIX known issues:
|
||||
// - hold fewer instances of the `Allocator`
|
||||
|
||||
pub fn Element(Event: type) type {
|
||||
pub fn Element(Model: type, Event: type) type {
|
||||
return struct {
|
||||
ptr: *anyopaque = undefined,
|
||||
vtable: *const VTable = &.{},
|
||||
@@ -17,8 +17,8 @@ pub fn Element(Event: type) type {
|
||||
pub const VTable = struct {
|
||||
resize: ?*const fn (ctx: *anyopaque, size: Point) void = null,
|
||||
reposition: ?*const fn (ctx: *anyopaque, origin: Point) void = null,
|
||||
handle: ?*const fn (ctx: *anyopaque, event: Event) anyerror!void = null,
|
||||
content: ?*const fn (ctx: *anyopaque, cells: []Cell, size: Point) anyerror!void = null,
|
||||
handle: ?*const fn (ctx: *anyopaque, model: *Model, event: Event) anyerror!void = null,
|
||||
content: ?*const fn (ctx: *anyopaque, model: *const Model, cells: []Cell, size: Point) anyerror!void = null,
|
||||
};
|
||||
|
||||
/// Resize the corresponding `Element` with the given *size*.
|
||||
@@ -34,15 +34,16 @@ pub fn Element(Event: type) type {
|
||||
}
|
||||
|
||||
/// Handle the received event. The event is one of the user provided
|
||||
/// events or a system event, with the exception of the `.size`
|
||||
/// `Event` as every `Container` already handles that event.
|
||||
/// events or a system event. The model can be updated through the
|
||||
/// provided pointer.
|
||||
///
|
||||
/// In case of user errors this function should return an error. This
|
||||
/// error may then be used by the application to display information
|
||||
/// about the user error.
|
||||
pub inline fn handle(this: @This(), event: Event) !void {
|
||||
/// about the error to the user and is left intentionally up to the
|
||||
/// implementation to decide.
|
||||
pub inline fn handle(this: @This(), model: *Model, event: Event) !void {
|
||||
if (this.vtable.handle) |handle_fn|
|
||||
try handle_fn(this.ptr, event);
|
||||
try handle_fn(this.ptr, model, event);
|
||||
}
|
||||
|
||||
/// Write content into the `cells` of the `Container`. The associated
|
||||
@@ -51,7 +52,7 @@ pub fn Element(Event: type) type {
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// - Caller owns `cells` slice and ensures that the size usually by assertion:
|
||||
/// - Caller owns `cells` slice and ensures the size usually by assertion:
|
||||
/// ```zig
|
||||
/// std.debug.assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
/// ```
|
||||
@@ -60,9 +61,21 @@ pub fn Element(Event: type) type {
|
||||
/// non-recoverable (i.e. an allocation error, system error, etc.).
|
||||
/// Otherwise user specific errors should be caught using the `handle`
|
||||
/// function before the rendering of the `Container` happens.
|
||||
pub inline fn content(this: @This(), cells: []Cell, size: Point) !void {
|
||||
///
|
||||
/// - The provided model may be used as a read-only reference to create
|
||||
/// the contents for the `cells`. Changes should only be done through
|
||||
/// the `handle` callback.
|
||||
///
|
||||
/// - When facing layout problems it might help to enable the
|
||||
/// build option for debug rendering, which renders corresponding
|
||||
/// placeholders.
|
||||
/// - **e** for `Element`
|
||||
/// - **c** for `Container`
|
||||
/// - **s** for `Separator`
|
||||
/// - **r** for `Rectangle`
|
||||
pub inline fn content(this: @This(), model: *const Model, cells: []Cell, size: Point) !void {
|
||||
if (this.vtable.content) |content_fn| {
|
||||
try content_fn(this.ptr, cells, size);
|
||||
try content_fn(this.ptr, model, cells, size);
|
||||
|
||||
// DEBUG render corresponding top left corner of this `Element` *red*
|
||||
// - only rendered if the corresponding associated element renders contents into the `Container`
|
||||
@@ -74,16 +87,16 @@ pub fn Element(Event: type) type {
|
||||
}
|
||||
}
|
||||
};
|
||||
} // Element(Event: type)
|
||||
} // Element(Model: type, Event: type)
|
||||
|
||||
pub fn Alignment(Event: type) type {
|
||||
pub fn Alignment(Model: type, Event: type) type {
|
||||
return struct {
|
||||
/// `Size` of the actual contents that should be aligned.
|
||||
size: Point = .{},
|
||||
/// Alignment Configuration to use for aligning the associated contents of this `Element`.
|
||||
configuration: Configuration,
|
||||
/// `Container` to render in alignment. It needs to use the sizing options accordingly to be effective.
|
||||
container: Container(Event),
|
||||
container: Container(Model, Event),
|
||||
|
||||
/// Configuration for Alignment
|
||||
pub const Configuration = packed struct {
|
||||
@@ -105,14 +118,14 @@ pub fn Alignment(Event: type) type {
|
||||
pub const center: @This() = .{ .v = .center, .h = .center };
|
||||
};
|
||||
|
||||
pub fn init(container: Container(Event), configuration: Configuration) @This() {
|
||||
pub fn init(container: Container(Model, Event), configuration: Configuration) @This() {
|
||||
return .{
|
||||
.container = container,
|
||||
.configuration = configuration,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -146,18 +159,18 @@ pub fn Alignment(Event: type) type {
|
||||
this.container.reposition(origin);
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, model: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
try this.container.handle(event);
|
||||
try this.container.handle(model, event);
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, model: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
const origin = this.container.origin;
|
||||
const csize = this.container.size;
|
||||
|
||||
const container_cells = try this.container.content();
|
||||
const container_cells = try this.container.content(model);
|
||||
defer this.container.allocator.free(container_cells);
|
||||
|
||||
outer: for (0..csize.y) |row| {
|
||||
@@ -171,9 +184,9 @@ pub fn Alignment(Event: type) type {
|
||||
}
|
||||
}
|
||||
};
|
||||
} // Alignment(Event: type)
|
||||
} // Alignment(Model: type, Event: type)
|
||||
|
||||
pub fn Scrollable(Event: type) type {
|
||||
pub fn Scrollable(Model: type, Event: type) type {
|
||||
return struct {
|
||||
/// `Size` of the actual contents where the anchor and the size is
|
||||
/// representing the size and location on screen.
|
||||
@@ -184,7 +197,7 @@ pub fn Scrollable(Event: type) type {
|
||||
/// Anchor of the viewport of the scrollable `Container`.
|
||||
anchor: Point = .{},
|
||||
/// The actual `Container`, that is scrollable.
|
||||
container: Container(Event),
|
||||
container: Container(Model, Event),
|
||||
/// Whether the scrollable contents should show a scroll bar or not.
|
||||
/// The scroll bar will only be shown if required and enabled. With the
|
||||
/// corresponding provided color if to be shown.
|
||||
@@ -204,14 +217,14 @@ pub fn Scrollable(Event: type) type {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init(container: Container(Event), configuration: Configuration) @This() {
|
||||
pub fn init(container: Container(Model, Event), configuration: Configuration) @This() {
|
||||
return .{
|
||||
.container = container,
|
||||
.configuration = configuration,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -255,7 +268,7 @@ pub fn Scrollable(Event: type) type {
|
||||
this.container.reposition(.{});
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, model: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
switch (event) {
|
||||
// TODO other means to scroll except with the mouse? (i.e. Ctrl-u/d, k/j, etc.?)
|
||||
@@ -274,7 +287,7 @@ pub fn Scrollable(Event: type) type {
|
||||
const max_anchor_x = this.container_size.x -| this.size.x;
|
||||
this.anchor.x = @min(this.anchor.x + 1, max_anchor_x);
|
||||
},
|
||||
else => try this.container.handle(.{
|
||||
else => try this.container.handle(model, .{
|
||||
.mouse = .{
|
||||
.x = mouse.x + this.anchor.x,
|
||||
.y = mouse.y + this.anchor.y,
|
||||
@@ -283,14 +296,14 @@ pub fn Scrollable(Event: type) type {
|
||||
},
|
||||
}),
|
||||
},
|
||||
else => try this.container.handle(event),
|
||||
else => try this.container.handle(model, event),
|
||||
}
|
||||
}
|
||||
|
||||
fn render_container(container: Container(Event), cells: []Cell, container_size: Point) !void {
|
||||
fn render_container(container: Container(Model, Event), model: *const Model, cells: []Cell, container_size: Point) !void {
|
||||
const size = container.size;
|
||||
const origin = container.origin;
|
||||
const contents = try container.content();
|
||||
const contents = try container.content(model);
|
||||
|
||||
const anchor = (@as(usize, origin.y) * @as(usize, container_size.x)) + @as(usize, origin.x);
|
||||
|
||||
@@ -306,10 +319,10 @@ pub fn Scrollable(Event: type) type {
|
||||
// free immediately
|
||||
container.allocator.free(contents);
|
||||
|
||||
for (container.elements.items) |child| try render_container(child, cells, size);
|
||||
for (container.elements.items) |child| try render_container(child, model, cells, size);
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, model: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
assert(cells.len == @as(usize, this.size.x) * @as(usize, this.size.y));
|
||||
@@ -317,9 +330,9 @@ pub fn Scrollable(Event: type) type {
|
||||
const offset_y: usize = if (this.configuration.y_axis) 1 else 0;
|
||||
|
||||
const container_size = this.container.size;
|
||||
const container_cells = try this.container.content();
|
||||
const container_cells = try this.container.content(model);
|
||||
|
||||
for (this.container.elements.items) |child| try render_container(child, container_cells, container_size);
|
||||
for (this.container.elements.items) |child| try render_container(child, model, container_cells, container_size);
|
||||
|
||||
const anchor = (@as(usize, this.anchor.y) * @as(usize, container_size.x)) + @as(usize, this.anchor.x);
|
||||
for (0..size.y - offset_y) |row| {
|
||||
@@ -368,12 +381,12 @@ pub fn Scrollable(Event: type) type {
|
||||
this.container.allocator.free(container_cells);
|
||||
}
|
||||
};
|
||||
} // Scrollable(Event: type)
|
||||
} // Scrollable(Model: type, Event: type)
|
||||
|
||||
// TODO features
|
||||
// - clear input (with and without retaining of capacity) through an public api
|
||||
// - make handle / content functions public
|
||||
pub fn Input(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
pub fn Input(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
// NOTE the struct is necessary, as otherwise I cannot point to the function I want to return
|
||||
const input_struct = struct {
|
||||
pub fn input_fn(accept_event: meta.FieldEnum(Event)) type {
|
||||
@@ -430,7 +443,7 @@ pub fn Input(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
this.input.deinit(this.allocator);
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -440,7 +453,7 @@ pub fn Input(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, _: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
switch (event) {
|
||||
.key => |key| {
|
||||
@@ -554,7 +567,7 @@ pub fn Input(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, _: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
|
||||
@@ -581,9 +594,9 @@ pub fn Input(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
};
|
||||
return input_struct.input_fn;
|
||||
} // Input(Event: type, Queue: type)
|
||||
} // Input(Model: type, Event: type, Queue: type)
|
||||
|
||||
pub fn Button(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
pub fn Button(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
// NOTE the struct is necessary, as otherwise I cannot point to the function I want to return
|
||||
const button_struct = struct {
|
||||
pub fn button_fn(accept_event: meta.FieldEnum(Event)) type {
|
||||
@@ -618,7 +631,7 @@ pub fn Button(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -628,7 +641,7 @@ pub fn Button(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, _: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
switch (event) {
|
||||
// TODO should this also support key presses to accept?
|
||||
@@ -637,7 +650,7 @@ pub fn Button(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, _: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
|
||||
@@ -659,9 +672,9 @@ pub fn Button(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
};
|
||||
return button_struct.button_fn;
|
||||
} // Button(Event: type, Queue: type)
|
||||
} // Button(Model: type, Event: type, Queue: type)
|
||||
|
||||
pub fn RadioButton(Event: type) type {
|
||||
pub fn RadioButton(Model: type, Event: type) type {
|
||||
return struct {
|
||||
configuration: Configuration,
|
||||
value: bool,
|
||||
@@ -683,7 +696,7 @@ pub fn RadioButton(Event: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -693,7 +706,7 @@ pub fn RadioButton(Event: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, _: *Model, event: Event) !void {
|
||||
var this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
switch (event) {
|
||||
// TODO should this also support key presses to accept?
|
||||
@@ -704,7 +717,7 @@ pub fn RadioButton(Event: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, _: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
|
||||
@@ -723,9 +736,9 @@ pub fn RadioButton(Event: type) type {
|
||||
}
|
||||
}
|
||||
};
|
||||
} // RadioButton(Event: type)
|
||||
} // RadioButton(Model: type, Event: type)
|
||||
|
||||
pub fn Selection(Event: type) fn (type) type {
|
||||
pub fn Selection(Model: type, Event: type) fn (type) type {
|
||||
const selection_struct = struct {
|
||||
pub fn selection_fn(Enum: type) type {
|
||||
switch (@typeInfo(Enum)) {
|
||||
@@ -751,7 +764,7 @@ pub fn Selection(Event: type) fn (type) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -761,7 +774,7 @@ pub fn Selection(Event: type) fn (type) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, _: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
switch (event) {
|
||||
.mouse => |mouse| if (mouse.y == 0) {
|
||||
@@ -840,7 +853,7 @@ pub fn Selection(Event: type) fn (type) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, _: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
if (this.configuration.label.len + 4 + this.width >= cells.len) return Error.TooSmall;
|
||||
@@ -865,9 +878,9 @@ pub fn Selection(Event: type) fn (type) type {
|
||||
}
|
||||
};
|
||||
return selection_struct.selection_fn;
|
||||
} // Selection(Enum: type)
|
||||
} // Selection(Model: type, Event: type)
|
||||
|
||||
pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
pub fn Progress(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
// NOTE the struct is necessary, as otherwise I cannot point to the function I want to return
|
||||
const progress_struct = struct {
|
||||
pub fn progress_fn(progress_event: meta.FieldEnum(Event)) type {
|
||||
@@ -910,7 +923,7 @@ pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
pub fn element(this: *@This()) Element(Model, Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
@@ -920,7 +933,7 @@ pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
fn handle(ctx: *anyopaque, _: *Model, event: Event) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
// TODO should this `Element` trigger a completion event? (I don't think that this is useful?)
|
||||
switch (event) {
|
||||
@@ -932,7 +945,7 @@ pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Point) !void {
|
||||
fn content(ctx: *anyopaque, _: *const Model, cells: []Cell, size: Point) !void {
|
||||
const this: *@This() = @ptrCast(@alignCast(ctx));
|
||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||
|
||||
@@ -965,7 +978,7 @@ pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type {
|
||||
}
|
||||
};
|
||||
return progress_struct.progress_fn;
|
||||
} // Progress(Event: type, Queue: type)
|
||||
} // Progress(Model: type, Event: type, Queue: type)
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
@@ -990,8 +1003,10 @@ test "scrollable vertical" {
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var box: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var box: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.sides = .all,
|
||||
.color = .red,
|
||||
@@ -1016,9 +1031,9 @@ test "scrollable vertical" {
|
||||
}, .{}));
|
||||
defer box.deinit();
|
||||
|
||||
var scrollable: Scrollable(event.SystemEvent) = .init(box, .disabled);
|
||||
var scrollable: Scrollable(Model, event.SystemEvent) = .init(box, .disabled);
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.color = .green,
|
||||
.sides = .vertical,
|
||||
@@ -1031,11 +1046,11 @@ test "scrollable vertical" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.top.zon"), renderer.screen);
|
||||
|
||||
// scroll down 15 times (exactly to the end)
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_down,
|
||||
.kind = .press,
|
||||
@@ -1043,11 +1058,11 @@ test "scrollable vertical" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.bottom.zon"), renderer.screen);
|
||||
|
||||
// further scrolling down will not change anything
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_down,
|
||||
.kind = .press,
|
||||
@@ -1055,7 +1070,7 @@ test "scrollable vertical" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.bottom.zon"), renderer.screen);
|
||||
}
|
||||
|
||||
@@ -1068,8 +1083,10 @@ test "scrollable vertical with scrollbar" {
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var box: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var box: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.sides = .all,
|
||||
.color = .red,
|
||||
@@ -1094,9 +1111,9 @@ test "scrollable vertical with scrollbar" {
|
||||
}, .{}));
|
||||
defer box.deinit();
|
||||
|
||||
var scrollable: Scrollable(event.SystemEvent) = .init(box, .enabled(.white));
|
||||
var scrollable: Scrollable(Model, event.SystemEvent) = .init(box, .enabled(.white));
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.color = .green,
|
||||
.sides = .vertical,
|
||||
@@ -1109,11 +1126,11 @@ test "scrollable vertical with scrollbar" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.scrollbar.top.zon"), renderer.screen);
|
||||
|
||||
// scroll down 15 times (exactly to the end)
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_down,
|
||||
.kind = .press,
|
||||
@@ -1121,11 +1138,11 @@ test "scrollable vertical with scrollbar" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.scrollbar.bottom.zon"), renderer.screen);
|
||||
|
||||
// further scrolling down will not change anything
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_down,
|
||||
.kind = .press,
|
||||
@@ -1133,7 +1150,7 @@ test "scrollable vertical with scrollbar" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.scrollbar.bottom.zon"), renderer.screen);
|
||||
}
|
||||
|
||||
@@ -1146,8 +1163,10 @@ test "scrollable horizontal" {
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var box: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var box: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.sides = .all,
|
||||
.color = .red,
|
||||
@@ -1172,9 +1191,9 @@ test "scrollable horizontal" {
|
||||
}, .{}));
|
||||
defer box.deinit();
|
||||
|
||||
var scrollable: Scrollable(event.SystemEvent) = .init(box, .disabled);
|
||||
var scrollable: Scrollable(Model, event.SystemEvent) = .init(box, .disabled);
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.color = .green,
|
||||
.sides = .horizontal,
|
||||
@@ -1187,11 +1206,11 @@ test "scrollable horizontal" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.left.zon"), renderer.screen);
|
||||
|
||||
// scroll right 15 times (exactly to the end)
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_right,
|
||||
.kind = .press,
|
||||
@@ -1199,11 +1218,11 @@ test "scrollable horizontal" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.right.zon"), renderer.screen);
|
||||
|
||||
// further scrolling right will not change anything
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_right,
|
||||
.kind = .press,
|
||||
@@ -1211,7 +1230,7 @@ test "scrollable horizontal" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.right.zon"), renderer.screen);
|
||||
}
|
||||
|
||||
@@ -1224,8 +1243,10 @@ test "scrollable horizontal with scrollbar" {
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var box: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var box: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.sides = .all,
|
||||
.color = .red,
|
||||
@@ -1250,9 +1271,9 @@ test "scrollable horizontal with scrollbar" {
|
||||
}, .{}));
|
||||
defer box.deinit();
|
||||
|
||||
var scrollable: Scrollable(event.SystemEvent) = .init(box, .enabled(.white));
|
||||
var scrollable: Scrollable(Model, event.SystemEvent) = .init(box, .enabled(.white));
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.border = .{
|
||||
.color = .green,
|
||||
.sides = .horizontal,
|
||||
@@ -1265,11 +1286,11 @@ test "scrollable horizontal with scrollbar" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.scrollbar.left.zon"), renderer.screen);
|
||||
|
||||
// scroll right 15 times (exactly to the end)
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_right,
|
||||
.kind = .press,
|
||||
@@ -1277,11 +1298,11 @@ test "scrollable horizontal with scrollbar" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.scrollbar.right.zon"), renderer.screen);
|
||||
|
||||
// further scrolling right will not change anything
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.button = .wheel_right,
|
||||
.kind = .press,
|
||||
@@ -1289,7 +1310,7 @@ test "scrollable horizontal with scrollbar" {
|
||||
.y = 5,
|
||||
},
|
||||
});
|
||||
try renderer.render(Container(event.SystemEvent), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.scrollbar.right.zon"), renderer.screen);
|
||||
}
|
||||
|
||||
@@ -1297,11 +1318,12 @@ test "alignment center" {
|
||||
const allocator = std.testing.allocator;
|
||||
const event = @import("event.zig");
|
||||
const testing = @import("testing.zig");
|
||||
const Model = struct {};
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var aligned_container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var aligned_container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 5 },
|
||||
@@ -1310,24 +1332,25 @@ test "alignment center" {
|
||||
}, .{});
|
||||
defer aligned_container.deinit();
|
||||
|
||||
var alignment: Alignment(event.SystemEvent) = .init(aligned_container, .center);
|
||||
var alignment: Alignment(Model, event.SystemEvent) = .init(aligned_container, .center);
|
||||
try container.append(try .init(allocator, .{}, alignment.element()));
|
||||
|
||||
try testing.expectContainerScreen(.{
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
}, &container, @import("test/element/alignment.center.zon"));
|
||||
}, @TypeOf(container), &container, Model, @import("test/element/alignment.center.zon"));
|
||||
}
|
||||
|
||||
test "alignment left" {
|
||||
const allocator = std.testing.allocator;
|
||||
const event = @import("event.zig");
|
||||
const testing = @import("testing.zig");
|
||||
const Model = struct {};
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var aligned_container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var aligned_container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 5 },
|
||||
@@ -1336,7 +1359,7 @@ test "alignment left" {
|
||||
}, .{});
|
||||
defer aligned_container.deinit();
|
||||
|
||||
var alignment: Alignment(event.SystemEvent) = .init(aligned_container, .{
|
||||
var alignment: Alignment(Model, event.SystemEvent) = .init(aligned_container, .{
|
||||
.h = .start,
|
||||
.v = .center,
|
||||
});
|
||||
@@ -1345,18 +1368,19 @@ test "alignment left" {
|
||||
try testing.expectContainerScreen(.{
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
}, &container, @import("test/element/alignment.left.zon"));
|
||||
}, @TypeOf(container), &container, Model, @import("test/element/alignment.left.zon"));
|
||||
}
|
||||
|
||||
test "alignment right" {
|
||||
const allocator = std.testing.allocator;
|
||||
const event = @import("event.zig");
|
||||
const testing = @import("testing.zig");
|
||||
const Model = struct {};
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var aligned_container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var aligned_container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 5 },
|
||||
@@ -1365,7 +1389,7 @@ test "alignment right" {
|
||||
}, .{});
|
||||
defer aligned_container.deinit();
|
||||
|
||||
var alignment: Alignment(event.SystemEvent) = .init(aligned_container, .{
|
||||
var alignment: Alignment(Model, event.SystemEvent) = .init(aligned_container, .{
|
||||
.h = .end,
|
||||
.v = .center,
|
||||
});
|
||||
@@ -1374,18 +1398,19 @@ test "alignment right" {
|
||||
try testing.expectContainerScreen(.{
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
}, &container, @import("test/element/alignment.right.zon"));
|
||||
}, @TypeOf(container), &container, Model, @import("test/element/alignment.right.zon"));
|
||||
}
|
||||
|
||||
test "alignment top" {
|
||||
const allocator = std.testing.allocator;
|
||||
const event = @import("event.zig");
|
||||
const testing = @import("testing.zig");
|
||||
const Model = struct {};
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var aligned_container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var aligned_container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 5 },
|
||||
@@ -1394,7 +1419,7 @@ test "alignment top" {
|
||||
}, .{});
|
||||
defer aligned_container.deinit();
|
||||
|
||||
var alignment: Alignment(event.SystemEvent) = .init(aligned_container, .{
|
||||
var alignment: Alignment(Model, event.SystemEvent) = .init(aligned_container, .{
|
||||
.h = .center,
|
||||
.v = .start,
|
||||
});
|
||||
@@ -1403,18 +1428,19 @@ test "alignment top" {
|
||||
try testing.expectContainerScreen(.{
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
}, &container, @import("test/element/alignment.top.zon"));
|
||||
}, @TypeOf(container), &container, Model, @import("test/element/alignment.top.zon"));
|
||||
}
|
||||
|
||||
test "alignment bottom" {
|
||||
const allocator = std.testing.allocator;
|
||||
const event = @import("event.zig");
|
||||
const testing = @import("testing.zig");
|
||||
const Model = struct {};
|
||||
|
||||
var container: Container(event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, event.SystemEvent) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var aligned_container: Container(event.SystemEvent) = try .init(allocator, .{
|
||||
var aligned_container: Container(Model, event.SystemEvent) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 5 },
|
||||
@@ -1423,7 +1449,7 @@ test "alignment bottom" {
|
||||
}, .{});
|
||||
defer aligned_container.deinit();
|
||||
|
||||
var alignment: Alignment(event.SystemEvent) = .init(aligned_container, .{
|
||||
var alignment: Alignment(Model, event.SystemEvent) = .init(aligned_container, .{
|
||||
.h = .center,
|
||||
.v = .end,
|
||||
});
|
||||
@@ -1432,7 +1458,7 @@ test "alignment bottom" {
|
||||
try testing.expectContainerScreen(.{
|
||||
.x = 30,
|
||||
.y = 20,
|
||||
}, &container, @import("test/element/alignment.bottom.zon"));
|
||||
}, @TypeOf(container), &container, Model, @import("test/element/alignment.bottom.zon"));
|
||||
}
|
||||
|
||||
test "input element" {
|
||||
@@ -1444,8 +1470,10 @@ test "input element" {
|
||||
});
|
||||
const testing = @import("testing.zig");
|
||||
const Queue = @import("queue.zig").Queue(Event, 256);
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var container: Container(Event) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, Event) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
const size: Point = .{
|
||||
@@ -1454,10 +1482,10 @@ test "input element" {
|
||||
};
|
||||
var queue: Queue = .{};
|
||||
|
||||
var input_element: Input(Event, Queue)(.accept) = .init(allocator, &queue, .init(.black));
|
||||
var input_element: Input(Model, Event, Queue)(.accept) = .init(allocator, &queue, .init(.black));
|
||||
defer input_element.deinit();
|
||||
|
||||
const input_container: Container(Event) = try .init(allocator, .{
|
||||
const input_container: Container(Model, Event) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .green },
|
||||
.size = .{
|
||||
.dim = .{ .x = 12, .y = 2 },
|
||||
@@ -1472,25 +1500,25 @@ test "input element" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/input.without.text.zon"), renderer.screen);
|
||||
|
||||
// press 'a' 15 times
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.key = .{ .cp = 'a' },
|
||||
});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/input.with.text.zon"), renderer.screen);
|
||||
|
||||
// press 'a' 15 times
|
||||
for (0..15) |_| try container.handle(.{
|
||||
for (0..15) |_| try container.handle(&model, .{
|
||||
.key = .{ .cp = 'a' },
|
||||
});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/input.with.text.overflow.zon"), renderer.screen);
|
||||
|
||||
// test the accepting of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.key = .{ .cp = input.Enter },
|
||||
});
|
||||
const accept_event = queue.pop();
|
||||
@@ -1521,12 +1549,14 @@ test "button" {
|
||||
.y = 20,
|
||||
};
|
||||
var queue: Queue = .{};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var container: Container(Event) = try .init(allocator, .{}, .{});
|
||||
var container: Container(Model, Event) = try .init(allocator, .{}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var button: Button(Event, Queue)(.accept) = .init(&queue, .init(.default, "Button"));
|
||||
const button_container: Container(Event) = try .init(allocator, .{
|
||||
var button: Button(Model, Event, Queue)(.accept) = .init(&queue, .init(.default, "Button"));
|
||||
const button_container: Container(Model, Event) = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .blue },
|
||||
}, button.element());
|
||||
try container.append(button_container);
|
||||
@@ -1536,11 +1566,11 @@ test "button" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/button.zon"), renderer.screen);
|
||||
|
||||
// test the accepting of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.mouse = .{
|
||||
.x = 5,
|
||||
.y = 3,
|
||||
@@ -1570,8 +1600,10 @@ test "progress" {
|
||||
.y = 20,
|
||||
};
|
||||
var queue: Queue = .{};
|
||||
const Model = struct {};
|
||||
var model: Model = .{};
|
||||
|
||||
var container: Container(Event) = try .init(allocator, .{
|
||||
var container: Container(Model, Event) = try .init(allocator, .{
|
||||
.layout = .{
|
||||
.padding = .all(1),
|
||||
},
|
||||
@@ -1579,12 +1611,12 @@ test "progress" {
|
||||
}, .{});
|
||||
defer container.deinit();
|
||||
|
||||
var progress: Progress(Event, Queue)(.progress) = .init(&queue, .{
|
||||
var progress: Progress(Model, Event, Queue)(.progress) = .init(&queue, .{
|
||||
.percent = .{ .enabled = true },
|
||||
.fg = .green,
|
||||
.bg = .grey,
|
||||
});
|
||||
const progress_container: Container(Event) = try .init(allocator, .{}, progress.element());
|
||||
const progress_container: Container(Model, Event) = try .init(allocator, .{}, progress.element());
|
||||
try container.append(progress_container);
|
||||
|
||||
var renderer: testing.Renderer = .init(allocator, size);
|
||||
@@ -1592,42 +1624,42 @@ test "progress" {
|
||||
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/progress_zero.zon"), renderer.screen);
|
||||
|
||||
// test the progress of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.progress = 25,
|
||||
});
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/progress_one_quarter.zon"), renderer.screen);
|
||||
|
||||
// test the progress of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.progress = 50,
|
||||
});
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/progress_half.zon"), renderer.screen);
|
||||
|
||||
// test the progress of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.progress = 75,
|
||||
});
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/progress_three_quarter.zon"), renderer.screen);
|
||||
|
||||
// test the progress of the `Element`
|
||||
try container.handle(.{
|
||||
try container.handle(&model, .{
|
||||
.progress = 100,
|
||||
});
|
||||
container.resize(size);
|
||||
container.reposition(.{});
|
||||
try renderer.render(Container(Event), &container);
|
||||
try renderer.render(@TypeOf(container), &container, Model, &.{});
|
||||
// try testing.expectEqualCells(.{}, renderer.size, @import("test/element/progress_one_hundred.zon"), renderer.screen);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user