intermediate #1
47
README.md
47
README.md
@@ -73,16 +73,12 @@ the primary use-case for myself to create this library in the first place.
|
||||
## Roadmap
|
||||
|
||||
- [ ] Container rendering
|
||||
- [ ] Layout
|
||||
- [x] Layout
|
||||
- [x] direction
|
||||
- [x] vertical
|
||||
- [x] horizontal
|
||||
- [x] padding
|
||||
- [x] gap
|
||||
- [x] alignment (removed - for now at least)
|
||||
- center
|
||||
- left
|
||||
- right
|
||||
- [x] sizing (removed - for now at least)
|
||||
- width
|
||||
- height
|
||||
@@ -96,10 +92,23 @@ the primary use-case for myself to create this library in the first place.
|
||||
- [x] corners
|
||||
- [x] separators
|
||||
- [x] Rectangle
|
||||
- [ ] Scroll
|
||||
- [ ] User control
|
||||
- [x] event handling
|
||||
- [x] user content
|
||||
- [ ] Default `Element` implementations
|
||||
- [ ] Scrollable
|
||||
- [ ] user input handling
|
||||
- [ ] vertical
|
||||
- [ ] horizontal
|
||||
- [ ] scroll bar(s)
|
||||
- [ ] scroll bar(s) rendering
|
||||
- [ ] vertical
|
||||
- [ ] horizontal
|
||||
- [ ] Content alignment (i.e. standard calculations done with the provided `Size`)
|
||||
- [ ] Text display
|
||||
- [ ] User input
|
||||
- [ ] single line
|
||||
- [ ] multi line
|
||||
- [ ] min size? (I don't have access to the `.resize` `Event`..)
|
||||
|
||||
Decorations should respect the layout and the viewport accordingly. This means
|
||||
that scrollbars are always visible (except there is no need to have a scrollbar)
|
||||
@@ -119,6 +128,30 @@ This still has one issue: Layout of child elements that are already too large
|
||||
scrollbar given the right parameters however. The scrolling input action would
|
||||
then also be implemented by the user.
|
||||
|
||||
Open questions are regarding the sizing options (i.e. how is the size of a
|
||||
`Container` actually controlled?, how should it be controlled?, etc.). There
|
||||
should be support for the child elements to provide some kind of 'list'
|
||||
functionality built-in.
|
||||
|
||||
**REMINDER**: (mostly for myself) The library should be and remain simple. This
|
||||
means that some code for using the library may be duplicated, but this is not
|
||||
the main goal. Others may provide more re-usable code snippets that build on top
|
||||
of this library instead.
|
||||
|
||||
### User specific event handling and content rendering
|
||||
|
||||
For interactions controlled by the user each container can use an `Element`
|
||||
interface which contains functions which are called by the `Container`
|
||||
during event handling (i.e. `fn handle(..)`) and during rendering (i.e. `fn
|
||||
content(..)`) to provide user specific content and user interaction. The
|
||||
`Element` may be stateful, but may also be stateless and then be re-used in
|
||||
multiple different `Container`s.
|
||||
|
||||
Composing multiple `Element`s currently requires the implementation of a wrapper
|
||||
which contains the `Element`s that need to be handled (should work pretty well
|
||||
for stateless `Element`s). Such *stateless* `Element`s may be provided by this
|
||||
library.
|
||||
|
||||
### Input
|
||||
|
||||
How is the user input handled in the containers? Should there be active
|
||||
|
||||
@@ -6,7 +6,7 @@ const Key = zterm.Key;
|
||||
|
||||
const log = std.log.scoped(.example);
|
||||
|
||||
pub const ExampleElement = struct {
|
||||
pub const ExampleElement = packed struct {
|
||||
pub fn element(this: *@This()) App.Element {
|
||||
return .{
|
||||
.ptr = this,
|
||||
|
||||
@@ -185,17 +185,6 @@ pub const Rectangle = packed struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Scroll configuration struct
|
||||
pub const Scroll = packed struct {
|
||||
/// Enable horizontal scrolling for this element
|
||||
horizontal: bool = false,
|
||||
/// Enable vertical scrolling for this element
|
||||
vertical: bool = false,
|
||||
|
||||
// TODO: rendering enhancements:
|
||||
// - render corresponding scroll-bars?
|
||||
};
|
||||
|
||||
/// Layout configuration struct
|
||||
pub const Layout = packed struct {
|
||||
/// control the direction in which child elements are laid out
|
||||
@@ -244,7 +233,6 @@ pub fn Container(comptime Event: type) type {
|
||||
pub const Properties = packed struct {
|
||||
border: Border = .{},
|
||||
rectangle: Rectangle = .{},
|
||||
scroll: Scroll = .{},
|
||||
layout: Layout = .{},
|
||||
};
|
||||
|
||||
@@ -328,9 +316,7 @@ pub fn Container(comptime Event: type) type {
|
||||
break :blk rows - element_rows * len;
|
||||
},
|
||||
};
|
||||
// TODO: make sure that items cannot underflow in size!
|
||||
// - make their size and position still according (even if outside of the visible space!)
|
||||
// - don't render them then accordingly -> avoid index out of bounce accesses!
|
||||
|
||||
for (this.elements.items) |*element| {
|
||||
var element_size: Size = undefined;
|
||||
switch (layout.direction) {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
//! Interface for Element's which describe the contents of a `Container`.
|
||||
const std = @import("std");
|
||||
|
||||
const Cell = @import("cell.zig");
|
||||
const Size = @import("size.zig").Size;
|
||||
|
||||
@@ -12,12 +14,57 @@ pub fn Element(Event: type) type {
|
||||
content: ?*const fn (ctx: *anyopaque, cells: []Cell, size: Size) anyerror!void = null,
|
||||
};
|
||||
|
||||
/// Handle the received event. The event is one of the user provided
|
||||
/// events or a system event, with the exception of the `.resize`
|
||||
/// `Event` as every `Container` already handles that event.
|
||||
///
|
||||
/// 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 {
|
||||
if (this.vtable.handle) |handle_fn| try handle_fn(this.ptr, event);
|
||||
if (this.vtable.handle) |handle_fn|
|
||||
try handle_fn(this.ptr, event);
|
||||
}
|
||||
|
||||
/// Write content into the `cells` of the `Container`. The associated
|
||||
/// `cells` slice has the size of (`size.cols * size.rows`). The
|
||||
/// renderer will know where to place the contents on the screen.
|
||||
///
|
||||
/// This function should only fail with an error if the error is
|
||||
/// 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: Size) !void {
|
||||
if (this.vtable.content) |content_fn| try content_fn(this.ptr, cells, size);
|
||||
if (this.vtable.content) |content_fn|
|
||||
try content_fn(this.ptr, cells, size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// This is an empty template implementation for an Element type which `zterm` may provide.
|
||||
///
|
||||
/// TODO: Should elements need to be composible with each other, such that they may build complexer outputs?
|
||||
/// - the goal would rather be to have re-usable parts of handlers and/or content functions which serve similar functionalities.
|
||||
pub fn Template(Event: type) type {
|
||||
return packed struct {
|
||||
pub fn element(this: *@This()) Element(Event) {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
.handle = handle,
|
||||
.content = content,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn handle(ctx: *anyopaque, event: Event) !void {
|
||||
_ = ctx;
|
||||
_ = event;
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, cells: []Cell, size: Size) !void {
|
||||
_ = ctx;
|
||||
std.debug.assert(cells.len == @as(usize, size.cols) * @as(usize, size.rows));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user