mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-27 07:34:27 +02:00
hmm
This commit is contained in:
parent
f1ec2fd70f
commit
bf81a389b8
@ -43,8 +43,15 @@ pub struct FinalWidget {
|
|||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum LayoutRule {
|
pub enum LayoutRule {
|
||||||
|
/// Let the child decide how big to make the current node.
|
||||||
Child,
|
Child,
|
||||||
|
|
||||||
|
/// Expand to whatever space is left; the `ratio` determines how
|
||||||
|
/// much space to take if there are more than one
|
||||||
|
/// [`LayoutRule::Expand`] component.
|
||||||
Expand { ratio: u32 },
|
Expand { ratio: u32 },
|
||||||
|
|
||||||
|
/// Take up exactly `length` space if possible.
|
||||||
Length { length: u16 },
|
Length { length: u16 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
pub mod base;
|
pub mod base;
|
||||||
pub use base::*;
|
pub use base::*;
|
||||||
|
|
||||||
|
pub mod widget;
|
||||||
|
pub use widget::*;
|
||||||
|
|
||||||
use tui::{layout::Rect, Frame};
|
use tui::{layout::Rect, Frame};
|
||||||
|
|
||||||
use super::{Event, Status};
|
use super::{Bounds, Context, Event, LayoutNode, Size, Status};
|
||||||
|
|
||||||
/// A component displays information and can be interacted with.
|
/// A component displays information and can be interacted with.
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -11,14 +14,23 @@ pub trait Component<Message, Backend>
|
|||||||
where
|
where
|
||||||
Backend: tui::backend::Backend,
|
Backend: tui::backend::Backend,
|
||||||
{
|
{
|
||||||
/// Handles an [`Event`]. Defaults to just ignoring the event.
|
/// Draws the component.
|
||||||
fn on_event(&mut self, bounds: Rect, event: Event, messages: &mut Vec<Message>) -> Status {
|
fn draw(&mut self, area: Rect, context: &Context, frame: &mut Frame<'_, Backend>);
|
||||||
|
|
||||||
|
/// How a component should react to an [`Event`].
|
||||||
|
///
|
||||||
|
/// Defaults to just ignoring the event.
|
||||||
|
fn on_event(&mut self, area: Rect, event: Event, messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the desired layout of the component. Defaults to returning
|
/// How a component should size itself and its children, given some [`Bounds`].
|
||||||
fn layout(&self) {}
|
///
|
||||||
|
/// Defaults to returning a [`Size`] that fills up the bounds given.
|
||||||
/// Draws the component.
|
fn layout(&self, bounds: Bounds) -> Size {
|
||||||
fn draw(&mut self, bounds: Rect, frame: &mut Frame<'_, Backend>);
|
Size {
|
||||||
|
width: bounds.max_width,
|
||||||
|
height: bounds.max_height,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use tui::{backend::Backend, layout::Rect, Frame};
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
use crate::tuice::{Component, Event, Status};
|
use crate::tuice::{Component, Context, Event, Status};
|
||||||
|
|
||||||
pub struct Block {}
|
pub struct Block {}
|
||||||
|
|
||||||
@ -8,11 +8,11 @@ impl<Message, B> Component<Message, B> for Block
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn draw(&mut self, _bounds: Rect, _frame: &mut Frame<'_, B>) {
|
fn draw(&mut self, _area: Rect, _context: &Context, _frame: &mut Frame<'_, B>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, _bounds: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use tui::{backend::Backend, layout::Rect, Frame};
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
use crate::tuice::{Component, Event, Status};
|
use crate::tuice::{Component, Context, Event, Status};
|
||||||
|
|
||||||
pub struct Carousel {}
|
pub struct Carousel {}
|
||||||
|
|
||||||
@ -8,11 +8,11 @@ impl<Message, B> Component<Message, B> for Carousel
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn draw(&mut self, _bounds: Rect, _frame: &mut Frame<'_, B>) {
|
fn draw(&mut self, _area: Rect, _context: &Context, _frame: &mut Frame<'_, B>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, _bounds: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use tui::{backend::Backend, layout::Rect, Frame};
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
use crate::tuice::{Component, Event, Status};
|
use crate::tuice::{Component, Context, Event, Status};
|
||||||
|
|
||||||
pub struct Column {}
|
pub struct Column {}
|
||||||
|
|
||||||
@ -8,11 +8,11 @@ impl<Message, B> Component<Message, B> for Column
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn draw(&mut self, _bounds: Rect, _frame: &mut Frame<'_, B>) {
|
fn draw(&mut self, _area: Rect, _context: &Context, _frame: &mut Frame<'_, B>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, _bounds: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
src/tuice/component/base/container.rs
Normal file
68
src/tuice/component/base/container.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
|
use crate::tuice::{Bounds, Component, Context, Event, LayoutNode, Length, Size, Status};
|
||||||
|
|
||||||
|
pub struct Container<'a, Message, B>
|
||||||
|
where
|
||||||
|
B: Backend,
|
||||||
|
{
|
||||||
|
width: Length,
|
||||||
|
height: Length,
|
||||||
|
child: Box<dyn Component<Message, B> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Message, B> Container<'a, Message, B>
|
||||||
|
where
|
||||||
|
B: Backend,
|
||||||
|
{
|
||||||
|
pub fn new(child: Box<dyn Component<Message, B> + 'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
width: Length::Flex,
|
||||||
|
height: Length::Flex,
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Message, B> Component<Message, B> for Container<'a, Message, B>
|
||||||
|
where
|
||||||
|
B: Backend,
|
||||||
|
{
|
||||||
|
fn draw(&mut self, area: Rect, _context: &Context, _frame: &mut Frame<'_, B>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(&self, bounds: Bounds) -> Size {
|
||||||
|
let width = match self.width {
|
||||||
|
Length::Flex => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Length::FlexRatio(ratio) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Length::Fixed(length) => length.clamp(bounds.min_width, bounds.max_width),
|
||||||
|
Length::Child => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let height = match self.height {
|
||||||
|
Length::Flex => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Length::FlexRatio(ratio) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Length::Fixed(length) => length.clamp(bounds.min_height, bounds.max_height),
|
||||||
|
Length::Child => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Size { height, width }
|
||||||
|
}
|
||||||
|
}
|
@ -15,3 +15,9 @@ pub use block::Block;
|
|||||||
|
|
||||||
pub mod carousel;
|
pub mod carousel;
|
||||||
pub use carousel::Carousel;
|
pub use carousel::Carousel;
|
||||||
|
|
||||||
|
pub mod sized_box;
|
||||||
|
pub use sized_box::SizedBox;
|
||||||
|
|
||||||
|
pub mod container;
|
||||||
|
pub use container::Container;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use tui::{backend::Backend, layout::Rect, Frame};
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
use crate::tuice::{Component, Event, Status};
|
use crate::tuice::{Bounds, Component, Context, Event, Size, Status};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Row<'a, Message, B>
|
pub struct Row<'a, Message, B>
|
||||||
@ -29,14 +29,14 @@ impl<'a, Message, B> Component<Message, B> for Row<'a, Message, B>
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn draw(&mut self, bounds: Rect, frame: &mut Frame<'_, B>) {
|
fn draw(&mut self, area: Rect, context: &Context, frame: &mut Frame<'_, B>) {
|
||||||
self.children.iter_mut().for_each(|child| {
|
self.children.iter_mut().for_each(|child| {
|
||||||
// TODO: This is just temp! We need layout!
|
// TODO: This is just temp! We need layout!
|
||||||
child.draw(bounds, frame);
|
child.draw(area, context, frame);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, _bounds: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use tui::{backend::Backend, layout::Rect, Frame};
|
use tui::{backend::Backend, layout::Rect, Frame};
|
||||||
|
|
||||||
use crate::tuice::{Component, Event, Status};
|
use crate::tuice::{Component, Context, Event, Status};
|
||||||
|
|
||||||
/// A [`Component`] to handle keyboard shortcuts and assign actions to them.
|
/// A [`Component`] to handle keyboard shortcuts and assign actions to them.
|
||||||
///
|
///
|
||||||
@ -11,11 +11,11 @@ impl<Message, B> Component<Message, B> for Shortcut
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn draw(&mut self, _bounds: Rect, _frame: &mut Frame<'_, B>) {
|
fn draw(&mut self, _area: Rect, _context: &Context, _frame: &mut Frame<'_, B>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, _bounds: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
fn on_event(&mut self, _area: Rect, _event: Event, _messages: &mut Vec<Message>) -> Status {
|
||||||
Status::Ignored
|
Status::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
src/tuice/component/base/sized_box.rs
Normal file
59
src/tuice/component/base/sized_box.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use tui::backend::Backend;
|
||||||
|
|
||||||
|
use crate::tuice::{Component, Length};
|
||||||
|
|
||||||
|
pub struct SizedBox<'a, Message, B>
|
||||||
|
where
|
||||||
|
B: Backend,
|
||||||
|
{
|
||||||
|
width: Length,
|
||||||
|
height: Length,
|
||||||
|
child: Box<dyn Component<Message, B> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Message, B> SizedBox<'a, Message, B>
|
||||||
|
where
|
||||||
|
B: Backend,
|
||||||
|
{
|
||||||
|
/// Creates a new [`SizedBox`] for a child component
|
||||||
|
/// with a [`Length::Flex`] width and height.
|
||||||
|
pub fn new(child: Box<dyn Component<Message, B> + 'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
width: Length::Flex,
|
||||||
|
height: Length::Flex,
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`SizedBox`] for a child component
|
||||||
|
/// with a [`Length::Flex`] height.
|
||||||
|
pub fn with_width(child: Box<dyn Component<Message, B> + 'a>, width: Length) -> Self {
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
height: Length::Flex,
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`SizedBox`] for a child component
|
||||||
|
/// with a [`Length::Flex`] width.
|
||||||
|
pub fn with_height(child: Box<dyn Component<Message, B> + 'a>, height: Length) -> Self {
|
||||||
|
Self {
|
||||||
|
width: Length::Flex,
|
||||||
|
height,
|
||||||
|
child,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the width of the [`SizedBox`].
|
||||||
|
pub fn width(mut self, width: Length) -> Self {
|
||||||
|
self.width = width;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the height of the [`SizedBox`].
|
||||||
|
pub fn height(mut self, height: Length) -> Self {
|
||||||
|
self.height = height;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::TABLE_GAP_HEIGHT_LIMIT,
|
constants::TABLE_GAP_HEIGHT_LIMIT,
|
||||||
tuice::{Component, Event, Status},
|
tuice::{Component, Context, Event, Status},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::table_column::{TextColumn, TextColumnConstraint};
|
pub use self::table_column::{TextColumn, TextColumnConstraint};
|
||||||
@ -179,7 +179,55 @@ impl<'a, Message, B> Component<Message, B> for TextTable<'a, Message>
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn on_event(&mut self, bounds: Rect, event: Event, messages: &mut Vec<Message>) -> Status {
|
fn draw(&mut self, area: Rect, context: &Context, frame: &mut Frame<'_, B>) {
|
||||||
|
self.table_gap = if !self.show_gap
|
||||||
|
|| (self.rows.len() + 2 > area.height.into() && area.height < TABLE_GAP_HEIGHT_LIMIT)
|
||||||
|
{
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
let table_extras = 1 + self.table_gap;
|
||||||
|
let scrollable_height = area.height.saturating_sub(table_extras);
|
||||||
|
self.update_column_widths(area);
|
||||||
|
|
||||||
|
// Calculate widths first, since we need them later.
|
||||||
|
let widths = self
|
||||||
|
.column_widths
|
||||||
|
.iter()
|
||||||
|
.map(|column| Constraint::Length(*column))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Then calculate rows. We truncate the amount of data read based on height,
|
||||||
|
// as well as truncating some entries based on available width.
|
||||||
|
let data_slice = {
|
||||||
|
// Note: `get_list_start` already ensures `start` is within the bounds of the number of items, so no need to check!
|
||||||
|
let start = self
|
||||||
|
.state
|
||||||
|
.display_start_index(area, scrollable_height as usize);
|
||||||
|
let end = min(self.state.num_items(), start + scrollable_height as usize);
|
||||||
|
|
||||||
|
self.rows[start..end].to_vec()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Now build up our headers...
|
||||||
|
let header = Row::new(self.columns.iter().map(|column| column.name.clone()))
|
||||||
|
.style(self.style_sheet.table_header)
|
||||||
|
.bottom_margin(self.table_gap);
|
||||||
|
|
||||||
|
let mut table = Table::new(data_slice)
|
||||||
|
.header(header)
|
||||||
|
.style(self.style_sheet.text);
|
||||||
|
|
||||||
|
if self.show_selected_entry {
|
||||||
|
table = table.highlight_style(self.style_sheet.selected_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.render_stateful_widget(table.widths(&widths), area, self.state.tui_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_event(&mut self, area: Rect, event: Event, messages: &mut Vec<Message>) -> Status {
|
||||||
use crate::tuice::MouseBoundIntersect;
|
use crate::tuice::MouseBoundIntersect;
|
||||||
use crossterm::event::{MouseButton, MouseEventKind};
|
use crossterm::event::{MouseButton, MouseEventKind};
|
||||||
|
|
||||||
@ -194,10 +242,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Mouse(mouse_event) => {
|
Event::Mouse(mouse_event) => {
|
||||||
if mouse_event.does_mouse_intersect_bounds(bounds) {
|
if mouse_event.does_mouse_intersect_bounds(area) {
|
||||||
match mouse_event.kind {
|
match mouse_event.kind {
|
||||||
MouseEventKind::Down(MouseButton::Left) => {
|
MouseEventKind::Down(MouseButton::Left) => {
|
||||||
let y = mouse_event.row - bounds.top();
|
let y = mouse_event.row - area.top();
|
||||||
|
|
||||||
if self.sortable && y == 0 {
|
if self.sortable && y == 0 {
|
||||||
todo!()
|
todo!()
|
||||||
@ -230,55 +278,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&mut self, bounds: Rect, frame: &mut Frame<'_, B>) {
|
|
||||||
self.table_gap = if !self.show_gap
|
|
||||||
|| (self.rows.len() + 2 > bounds.height.into()
|
|
||||||
&& bounds.height < TABLE_GAP_HEIGHT_LIMIT)
|
|
||||||
{
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
};
|
|
||||||
|
|
||||||
let table_extras = 1 + self.table_gap;
|
|
||||||
let scrollable_height = bounds.height.saturating_sub(table_extras);
|
|
||||||
self.update_column_widths(bounds);
|
|
||||||
|
|
||||||
// Calculate widths first, since we need them later.
|
|
||||||
let widths = self
|
|
||||||
.column_widths
|
|
||||||
.iter()
|
|
||||||
.map(|column| Constraint::Length(*column))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// Then calculate rows. We truncate the amount of data read based on height,
|
|
||||||
// as well as truncating some entries based on available width.
|
|
||||||
let data_slice = {
|
|
||||||
// Note: `get_list_start` already ensures `start` is within the bounds of the number of items, so no need to check!
|
|
||||||
let start = self
|
|
||||||
.state
|
|
||||||
.display_start_index(bounds, scrollable_height as usize);
|
|
||||||
let end = min(self.state.num_items(), start + scrollable_height as usize);
|
|
||||||
|
|
||||||
self.rows[start..end].to_vec()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Now build up our headers...
|
|
||||||
let header = Row::new(self.columns.iter().map(|column| column.name.clone()))
|
|
||||||
.style(self.style_sheet.table_header)
|
|
||||||
.bottom_margin(self.table_gap);
|
|
||||||
|
|
||||||
let mut table = Table::new(data_slice)
|
|
||||||
.header(header)
|
|
||||||
.style(self.style_sheet.text);
|
|
||||||
|
|
||||||
if self.show_selected_entry {
|
|
||||||
table = table.highlight_style(self.style_sheet.selected_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.render_stateful_widget(table.widths(&widths), bounds, self.state.tui_state());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
0
src/tuice/component/widget/mod.rs
Normal file
0
src/tuice/component/widget/mod.rs
Normal file
6
src/tuice/context.rs
Normal file
6
src/tuice/context.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use crate::app::layout_manager::LayoutNode;
|
||||||
|
|
||||||
|
/// Internal management for drawing and the like.
|
||||||
|
pub struct Context {
|
||||||
|
layout_root: LayoutNode,
|
||||||
|
}
|
17
src/tuice/layout/bounds.rs
Normal file
17
src/tuice/layout/bounds.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/// [`Bounds`] represent minimal and maximal widths/height constraints while laying things out.
|
||||||
|
///
|
||||||
|
/// These are sent from a parent component to a child to determine the [`Size`](super::Size)
|
||||||
|
/// of a child, which is passed back up to the parent.
|
||||||
|
pub struct Bounds {
|
||||||
|
/// The minimal width available.
|
||||||
|
pub min_width: u16,
|
||||||
|
|
||||||
|
/// The minimal height available.
|
||||||
|
pub min_height: u16,
|
||||||
|
|
||||||
|
/// The maximal width available.
|
||||||
|
pub max_width: u16,
|
||||||
|
|
||||||
|
/// The maximal height available.
|
||||||
|
pub max_height: u16,
|
||||||
|
}
|
12
src/tuice/layout/layout_node.rs
Normal file
12
src/tuice/layout/layout_node.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use tui::layout::Rect;
|
||||||
|
|
||||||
|
/// A node for the layout tree.
|
||||||
|
pub enum LayoutNode {
|
||||||
|
Leaf {
|
||||||
|
area: Rect,
|
||||||
|
},
|
||||||
|
Branch {
|
||||||
|
area: Rect,
|
||||||
|
children: Vec<LayoutNode>,
|
||||||
|
},
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/// Which strategy to use while laying out widgets.
|
/// Which strategy to use while laying out things.
|
||||||
pub enum Length {
|
pub enum Length {
|
||||||
/// Fill in remaining space. Equivalent to `Length::FlexRatio(1)`.
|
/// Fill in remaining space. Equivalent to `Length::FlexRatio(1)`.
|
||||||
Flex,
|
Flex,
|
||||||
@ -8,4 +8,7 @@ pub enum Length {
|
|||||||
|
|
||||||
/// Fill in a fixed amount of space.
|
/// Fill in a fixed amount of space.
|
||||||
Fixed(u16),
|
Fixed(u16),
|
||||||
|
|
||||||
|
/// Let the child determine how large to make the component.
|
||||||
|
Child,
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,15 @@
|
|||||||
pub mod length;
|
pub mod length;
|
||||||
pub use length::Length;
|
pub use length::Length;
|
||||||
|
|
||||||
|
pub mod bounds;
|
||||||
|
pub use bounds::Bounds;
|
||||||
|
|
||||||
|
pub mod size;
|
||||||
|
pub use size::Size;
|
||||||
|
|
||||||
|
pub mod layout_node;
|
||||||
|
pub use layout_node::LayoutNode;
|
||||||
|
|
||||||
|
pub fn build_layout() -> LayoutNode {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
11
src/tuice/layout/size.rs
Normal file
11
src/tuice/layout/size.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/// A [`Size`] represents calculated widths and heights for a component.
|
||||||
|
///
|
||||||
|
/// A [`Size`] is sent from a child component back up to its parents after
|
||||||
|
/// first being given a [`Bounds`](super::Bounds) from the parent.
|
||||||
|
pub struct Size {
|
||||||
|
/// The given width.
|
||||||
|
pub width: u16,
|
||||||
|
|
||||||
|
/// The given height.
|
||||||
|
pub height: u16,
|
||||||
|
}
|
@ -14,3 +14,6 @@ pub use runtime::RuntimeEvent;
|
|||||||
|
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
|
|
||||||
|
pub mod context;
|
||||||
|
pub use context::*;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user