rem: Scroll from Propierties of Container
Updated the corresponding documentation and ideas for how to realize scrollable contents.
This commit is contained in:
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
|
## Roadmap
|
||||||
|
|
||||||
- [ ] Container rendering
|
- [ ] Container rendering
|
||||||
- [ ] Layout
|
- [x] Layout
|
||||||
- [x] direction
|
- [x] direction
|
||||||
- [x] vertical
|
- [x] vertical
|
||||||
- [x] horizontal
|
- [x] horizontal
|
||||||
- [x] padding
|
- [x] padding
|
||||||
- [x] gap
|
- [x] gap
|
||||||
- [x] alignment (removed - for now at least)
|
|
||||||
- center
|
|
||||||
- left
|
|
||||||
- right
|
|
||||||
- [x] sizing (removed - for now at least)
|
- [x] sizing (removed - for now at least)
|
||||||
- width
|
- width
|
||||||
- height
|
- height
|
||||||
@@ -96,10 +92,23 @@ the primary use-case for myself to create this library in the first place.
|
|||||||
- [x] corners
|
- [x] corners
|
||||||
- [x] separators
|
- [x] separators
|
||||||
- [x] Rectangle
|
- [x] Rectangle
|
||||||
- [ ] Scroll
|
- [ ] User control
|
||||||
|
- [x] event handling
|
||||||
|
- [x] user content
|
||||||
|
- [ ] Default `Element` implementations
|
||||||
|
- [ ] Scrollable
|
||||||
|
- [ ] user input handling
|
||||||
- [ ] vertical
|
- [ ] vertical
|
||||||
- [ ] horizontal
|
- [ ] 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
|
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)
|
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
|
scrollbar given the right parameters however. The scrolling input action would
|
||||||
then also be implemented by the user.
|
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
|
### Input
|
||||||
|
|
||||||
How is the user input handled in the containers? Should there be active
|
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);
|
const log = std.log.scoped(.example);
|
||||||
|
|
||||||
pub const ExampleElement = struct {
|
pub const ExampleElement = packed struct {
|
||||||
pub fn element(this: *@This()) App.Element {
|
pub fn element(this: *@This()) App.Element {
|
||||||
return .{
|
return .{
|
||||||
.ptr = this,
|
.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
|
/// Layout configuration struct
|
||||||
pub const Layout = packed struct {
|
pub const Layout = packed struct {
|
||||||
/// control the direction in which child elements are laid out
|
/// 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 {
|
pub const Properties = packed struct {
|
||||||
border: Border = .{},
|
border: Border = .{},
|
||||||
rectangle: Rectangle = .{},
|
rectangle: Rectangle = .{},
|
||||||
scroll: Scroll = .{},
|
|
||||||
layout: Layout = .{},
|
layout: Layout = .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -328,9 +316,7 @@ pub fn Container(comptime Event: type) type {
|
|||||||
break :blk rows - element_rows * len;
|
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| {
|
for (this.elements.items) |*element| {
|
||||||
var element_size: Size = undefined;
|
var element_size: Size = undefined;
|
||||||
switch (layout.direction) {
|
switch (layout.direction) {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//! Interface for Element's which describe the contents of a `Container`.
|
//! Interface for Element's which describe the contents of a `Container`.
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Cell = @import("cell.zig");
|
const Cell = @import("cell.zig");
|
||||||
const Size = @import("size.zig").Size;
|
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,
|
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 {
|
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 {
|
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