mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-28 16:14:16 +02:00
Shortcut
This commit is contained in:
parent
b7d73746ad
commit
68d2e9ae5b
@ -29,7 +29,7 @@ use frozen_state::FrozenState;
|
||||
use crate::{
|
||||
canvas::Painter,
|
||||
constants,
|
||||
tuine::{Application, Element, Flex, ViewContext},
|
||||
tuine::{Application, Element, Flex, Shortcut, ViewContext},
|
||||
units::data_units::DataUnit,
|
||||
Pid,
|
||||
};
|
||||
@ -241,7 +241,10 @@ impl Application for AppState {
|
||||
Flex::column()
|
||||
.with_flex_child(
|
||||
Flex::row_with_children(vec![
|
||||
FlexElement::new(TextTable::new(ctx, vec!["A", "B", "C"])),
|
||||
FlexElement::new(Shortcut::with_child(TextTable::new(
|
||||
ctx,
|
||||
vec!["A", "B", "C"],
|
||||
))),
|
||||
FlexElement::new(TextTable::new(ctx, vec!["D", "E", "F"])),
|
||||
]),
|
||||
1,
|
||||
|
@ -15,7 +15,7 @@ use super::{Bounds, DrawContext, Event, LayoutNode, Size, StateContext, Status};
|
||||
pub trait TmpComponent<Message> {
|
||||
/// Draws the component.
|
||||
fn draw<Backend>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, Backend>,
|
||||
) where
|
||||
Backend: tui::backend::Backend;
|
||||
@ -24,7 +24,7 @@ pub trait TmpComponent<Message> {
|
||||
///
|
||||
/// Defaults to just ignoring the event.
|
||||
fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
Status::Ignored
|
||||
|
@ -6,7 +6,7 @@ pub struct Block {}
|
||||
|
||||
impl<Message> TmpComponent<Message> for Block {
|
||||
fn draw<B>(
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: DrawContext<'_>,
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: &DrawContext<'_>,
|
||||
_frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
@ -15,7 +15,7 @@ impl<Message> TmpComponent<Message> for Block {
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: DrawContext<'_>, _event: Event,
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: &DrawContext<'_>, _event: Event,
|
||||
_messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
Status::Ignored
|
||||
|
@ -6,7 +6,7 @@ pub struct Carousel {}
|
||||
|
||||
impl<Message> TmpComponent<Message> for Carousel {
|
||||
fn draw<B>(
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: DrawContext<'_>,
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: &DrawContext<'_>,
|
||||
_frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
@ -15,7 +15,7 @@ impl<Message> TmpComponent<Message> for Carousel {
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: DrawContext<'_>, _event: Event,
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: &DrawContext<'_>, _event: Event,
|
||||
_messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
Status::Ignored
|
||||
|
@ -1,4 +1,4 @@
|
||||
use tui::{backend::Backend, Frame};
|
||||
use tui::{backend::Backend, layout::Rect, Frame};
|
||||
|
||||
use crate::tuine::{
|
||||
Bounds, DrawContext, Element, Event, LayoutNode, Size, StateContext, Status, TmpComponent,
|
||||
@ -15,16 +15,22 @@ pub struct Container<'a, Message> {
|
||||
}
|
||||
|
||||
impl<'a, Message> Container<'a, Message> {
|
||||
pub fn with_child(child: Element<'a, Message>) -> Self {
|
||||
pub fn with_child<C>(child: C) -> Self
|
||||
where
|
||||
C: Into<Element<'a, Message>>,
|
||||
{
|
||||
Self {
|
||||
width: None,
|
||||
height: None,
|
||||
child: Some(child.into()),
|
||||
child: Some(Box::new(child.into())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn child(mut self, child: Option<Element<'a, Message>>) -> Self {
|
||||
self.child = child.map(|c| c.into());
|
||||
pub fn child<C>(mut self, child: Option<C>) -> Self
|
||||
where
|
||||
C: Into<Element<'a, Message>>,
|
||||
{
|
||||
self.child = child.map(|c| Box::new(c.into()));
|
||||
self
|
||||
}
|
||||
|
||||
@ -41,25 +47,25 @@ impl<'a, Message> Container<'a, Message> {
|
||||
|
||||
impl<'a, Message> TmpComponent<Message> for Container<'a, Message> {
|
||||
fn draw<B>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
{
|
||||
if let Some(child) = &mut self.child {
|
||||
if let Some(child_draw_ctx) = draw_ctx.children().next() {
|
||||
child.draw(state_ctx, child_draw_ctx, frame)
|
||||
child.draw(state_ctx, &child_draw_ctx, frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
if let Some(child) = &mut self.child {
|
||||
if let Some(child_draw_ctx) = draw_ctx.children().next() {
|
||||
return child.on_event(state_ctx, child_draw_ctx, event, messages);
|
||||
return child.on_event(state_ctx, &child_draw_ctx, event, messages);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +100,7 @@ impl<'a, Message> TmpComponent<Message> for Container<'a, Message> {
|
||||
};
|
||||
|
||||
let child_size = child.layout(child_bounds, &mut child_node);
|
||||
child_node.rect = Rect::new(0, 0, child_size.width, child_size.height);
|
||||
node.children = vec![child_node];
|
||||
|
||||
// Note that this is implicitly bounded by our above calculations,
|
||||
|
16
src/tuine/component/base/empty.rs
Normal file
16
src/tuine/component/base/empty.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use tui::{backend::Backend, Frame};
|
||||
|
||||
use crate::tuine::{DrawContext, StateContext, TmpComponent};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Empty {}
|
||||
|
||||
impl<Message> TmpComponent<Message> for Empty {
|
||||
fn draw<B>(
|
||||
&mut self, _state_ctx: &mut StateContext<'_>, _draw_ctx: &DrawContext<'_>,
|
||||
_frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
{
|
||||
}
|
||||
}
|
@ -87,7 +87,7 @@ impl<'a, Message> Flex<'a, Message> {
|
||||
|
||||
impl<'a, Message> TmpComponent<Message> for Flex<'a, Message> {
|
||||
fn draw<B>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
@ -97,17 +97,17 @@ impl<'a, Message> TmpComponent<Message> for Flex<'a, Message> {
|
||||
.zip(draw_ctx.children())
|
||||
.for_each(|(child, child_draw_ctx)| {
|
||||
if child_draw_ctx.should_draw() {
|
||||
child.draw(state_ctx, child_draw_ctx, frame);
|
||||
child.draw(state_ctx, &child_draw_ctx, frame);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
for (child, child_draw_ctx) in self.children.iter_mut().zip(draw_ctx.children()) {
|
||||
match child.on_event(state_ctx, child_draw_ctx, event, messages) {
|
||||
match child.on_event(state_ctx, &child_draw_ctx, event, messages) {
|
||||
Status::Captured => {
|
||||
return Status::Captured;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ impl<'a, Message> FlexElement<'a, Message> {
|
||||
}
|
||||
|
||||
pub(crate) fn draw<B>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
@ -49,7 +49,7 @@ impl<'a, Message> FlexElement<'a, Message> {
|
||||
}
|
||||
|
||||
pub(crate) fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
self.element.on_event(state_ctx, draw_ctx, event, messages)
|
||||
|
@ -15,3 +15,6 @@ pub use carousel::Carousel;
|
||||
|
||||
pub mod container;
|
||||
pub use container::Container;
|
||||
|
||||
pub mod empty;
|
||||
pub use empty::Empty;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crossterm::event::KeyEvent;
|
||||
use rustc_hash::FxHashMap;
|
||||
use tui::{backend::Backend, Frame};
|
||||
use tui::{backend::Backend, layout::Rect, Frame};
|
||||
|
||||
use crate::tuine::{
|
||||
Bounds, DrawContext, Element, Event, LayoutNode, Size, StateContext, Status, TmpComponent,
|
||||
@ -18,7 +17,7 @@ pub struct Shortcut<'a, Message> {
|
||||
dyn Fn(
|
||||
&mut Element<'a, Message>,
|
||||
&mut StateContext<'_>,
|
||||
DrawContext<'_>,
|
||||
&DrawContext<'_>,
|
||||
Event,
|
||||
&mut Vec<Message>,
|
||||
) -> Status,
|
||||
@ -27,41 +26,73 @@ pub struct Shortcut<'a, Message> {
|
||||
}
|
||||
|
||||
impl<'a, Message> Shortcut<'a, Message> {
|
||||
pub fn with_child(child: Element<'a, Message>) -> Self {
|
||||
pub fn with_child<C>(child: C) -> Self
|
||||
where
|
||||
C: Into<Element<'a, Message>>,
|
||||
{
|
||||
Self {
|
||||
child: Some(child.into()),
|
||||
child: Some(Box::new(child.into())),
|
||||
shortcuts: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn child<C>(mut self, child: Option<C>) -> Self
|
||||
where
|
||||
C: Into<Element<'a, Message>>,
|
||||
{
|
||||
self.child = child.map(|c| Box::new(c.into()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn shortcut(
|
||||
mut self, event: Event,
|
||||
f: Box<
|
||||
dyn Fn(
|
||||
&mut Element<'a, Message>,
|
||||
&mut StateContext<'_>,
|
||||
&DrawContext<'_>,
|
||||
Event,
|
||||
&mut Vec<Message>,
|
||||
) -> Status,
|
||||
>,
|
||||
) -> Self {
|
||||
self.shortcuts.insert(event, f);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn remove_shortcut(mut self, event: &Event) -> Self {
|
||||
self.shortcuts.remove(event);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message> TmpComponent<Message> for Shortcut<'a, Message> {
|
||||
fn draw<B>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
{
|
||||
if let Some(child) = &mut self.child {
|
||||
if let Some(child_draw_ctx) = draw_ctx.children().next() {
|
||||
child.draw(state_ctx, child_draw_ctx, frame)
|
||||
child.draw(state_ctx, &child_draw_ctx, frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
if let Some(child_draw_ctx) = draw_ctx.children().next() {
|
||||
if let Some(child) = &mut self.child {
|
||||
match child.on_event(state_ctx, child_draw_ctx, event, messages) {
|
||||
match child.on_event(state_ctx, &child_draw_ctx, event, messages) {
|
||||
Status::Captured => {
|
||||
return Status::Captured;
|
||||
}
|
||||
Status::Ignored => {
|
||||
if let Some(f) = self.shortcuts.get(&event) {
|
||||
return f(child, state_ctx, child_draw_ctx, event, messages);
|
||||
return f(child, state_ctx, &child_draw_ctx, event, messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,6 +103,19 @@ impl<'a, Message> TmpComponent<Message> for Shortcut<'a, Message> {
|
||||
}
|
||||
|
||||
fn layout(&self, bounds: Bounds, node: &mut LayoutNode) -> Size {
|
||||
todo!()
|
||||
if let Some(child) = &self.child {
|
||||
let mut child_node = LayoutNode::default();
|
||||
let child_size = child.layout(bounds, &mut child_node);
|
||||
|
||||
child_node.rect = Rect::new(0, 0, child_size.width, child_size.height);
|
||||
node.children = vec![child_node];
|
||||
|
||||
child_size
|
||||
} else {
|
||||
Size {
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ impl<'a, Message> TextTable<'a, Message> {
|
||||
|
||||
impl<'a, Message> TmpComponent<Message> for TextTable<'a, Message> {
|
||||
fn draw<B>(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
|
||||
frame: &mut Frame<'_, B>,
|
||||
) where
|
||||
B: Backend,
|
||||
@ -220,7 +220,7 @@ impl<'a, Message> TmpComponent<Message> for TextTable<'a, Message> {
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: DrawContext<'_>, event: Event,
|
||||
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>, event: Event,
|
||||
messages: &mut Vec<Message>,
|
||||
) -> Status {
|
||||
use crate::tuine::MouseBoundIntersect;
|
||||
|
@ -2,8 +2,8 @@ use enum_dispatch::enum_dispatch;
|
||||
use tui::Frame;
|
||||
|
||||
use super::{
|
||||
Block, Bounds, Carousel, Container, DrawContext, Event, Flex, LayoutNode, Shortcut, Size,
|
||||
StateContext, Status, TextTable, TmpComponent,
|
||||
Block, Bounds, Carousel, Container, DrawContext, Empty, Event, Flex, LayoutNode, Shortcut,
|
||||
Size, StateContext, Status, TextTable, TmpComponent,
|
||||
};
|
||||
|
||||
/// An [`Element`] is an instantiated [`Component`].
|
||||
@ -15,4 +15,5 @@ pub enum Element<'a, Message> {
|
||||
Flex(Flex<'a, Message>),
|
||||
Shortcut(Shortcut<'a, Message>),
|
||||
TextTable(TextTable<'a, Message>),
|
||||
Empty,
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ fn on_event<A>(
|
||||
let mut state_ctx = StateContext::new(&mut app_data.state_map);
|
||||
let draw_ctx = DrawContext::root(&layout);
|
||||
|
||||
match user_interface.on_event(&mut state_ctx, draw_ctx, event, &mut messages) {
|
||||
match user_interface.on_event(&mut state_ctx, &draw_ctx, event, &mut messages) {
|
||||
Status::Captured => {
|
||||
// TODO: What to do on capture?
|
||||
}
|
||||
@ -124,7 +124,7 @@ where
|
||||
let mut state_ctx = StateContext::new(&mut app_data.state_map);
|
||||
let draw_ctx = DrawContext::root(&layout);
|
||||
|
||||
user_interface.draw(&mut state_ctx, draw_ctx, frame);
|
||||
user_interface.draw(&mut state_ctx, &draw_ctx, frame);
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user