Fix layout bugs

This commit is contained in:
ClementTsang 2021-12-30 22:40:00 -05:00
parent 3411d320c9
commit 93f936f369
24 changed files with 229 additions and 145 deletions

View File

@ -2,7 +2,7 @@ use crate::{
app::SelectableType,
data_conversion::ConvertedData,
error::{BottomError, Result},
options::layout_options::{FinalWidget, LayoutRow, LayoutRowChild, LayoutRule},
options::layout_options::{FinalWidget, LayoutRow, LayoutRowChild, WidgetLayoutRule},
tuine::*,
};
use anyhow::anyhow;
@ -101,7 +101,7 @@ Supported widget names:
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RowLayout {
last_selected: Option<NodeId>,
pub parent_rule: LayoutRule,
pub parent_rule: WidgetLayoutRule,
pub bound: Rect,
}
@ -109,7 +109,7 @@ pub struct RowLayout {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ColLayout {
last_selected: Option<NodeId>,
pub parent_rule: LayoutRule,
pub parent_rule: WidgetLayoutRule,
pub bound: Rect,
}
@ -180,7 +180,7 @@ pub enum WidgetLayoutNode {
Widget {
widget_type: BottomWidgetType,
selected: bool,
rule: LayoutRule,
rule: WidgetLayoutRule,
},
}
@ -254,10 +254,10 @@ impl WidgetLayoutNode {
}
}
fn wrap_element<Message>(element: Element<Message>, rule: &LayoutRule) -> FlexElement<Message> {
fn wrap_element<Message>(element: Element<Message>, rule: &WidgetLayoutRule) -> FlexElement<Message> {
match rule {
LayoutRule::Expand { ratio } => FlexElement::with_flex(element, *ratio),
LayoutRule::Length { width, height } => {
WidgetLayoutRule::Expand { ratio } => FlexElement::with_flex(element, *ratio),
WidgetLayoutRule::Length { width, height } => {
if width.is_some() || height.is_some() {
FlexElement::with_no_flex(
Container::with_child(element).width(*width).height(*height),

View File

@ -7,7 +7,7 @@ use tui::{backend::Backend, layout::Rect, Frame};
use crate::{
app::event::{ComponentEventResult, SelectionAction},
canvas::Painter,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
mod tui_stuff;
@ -133,10 +133,10 @@ pub trait Widget {
fn update_data(&mut self, data_collection: &DataCollection) {}
/// Returns the desired width from the [`Widget`].
fn width(&self) -> LayoutRule;
fn width(&self) -> WidgetLayoutRule;
/// Returns the desired height from the [`Widget`].
fn height(&self) -> LayoutRule;
fn height(&self) -> WidgetLayoutRule;
/// Returns whether this [`Widget`] can be selected. The default implementation returns [`SelectableType::Selectable`].
fn selectable_type(&self) -> SelectableType {

View File

@ -11,7 +11,7 @@ use crate::{
app::{widgets::tui_stuff::PipeGauge, AppConfig, Component, DataCollection, Widget},
canvas::Painter,
constants::SIDE_BORDERS,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
const REQUIRED_COLUMNS: usize = 4;
@ -20,7 +20,7 @@ const REQUIRED_COLUMNS: usize = 4;
pub struct BasicCpu {
bounds: Rect,
display_data: Vec<(f64, String, String)>,
width: LayoutRule,
width: WidgetLayoutRule,
showing_avg: bool,
}
@ -36,7 +36,7 @@ impl BasicCpu {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
@ -184,11 +184,11 @@ impl Widget for BasicCpu {
.collect::<Vec<_>>();
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
let display_data_len = self.display_data.len();
let length = max(
1,

View File

@ -14,13 +14,13 @@ use crate::{
canvas::Painter,
constants::SIDE_BORDERS,
data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points},
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
#[derive(Debug)]
pub struct BasicMem {
bounds: Rect,
width: LayoutRule,
width: WidgetLayoutRule,
mem_data: (f64, String, String),
swap_data: Option<(f64, String, String)>,
use_percent: bool,
@ -40,7 +40,7 @@ impl Default for BasicMem {
impl BasicMem {
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
@ -155,11 +155,11 @@ impl Widget for BasicMem {
};
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
todo!()
}
}

View File

@ -11,14 +11,14 @@ use crate::{
canvas::Painter,
constants::SIDE_BORDERS,
data_conversion::convert_network_data_points,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
units::data_units::DataUnit,
};
#[derive(Debug)]
pub struct BasicNet {
bounds: Rect,
width: LayoutRule,
width: WidgetLayoutRule,
rx_display: String,
tx_display: String,
@ -45,7 +45,7 @@ impl BasicNet {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
@ -124,11 +124,11 @@ impl Widget for BasicNet {
}
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
todo!()
}
}

View File

@ -17,7 +17,7 @@ use crate::{
canvas::Painter,
constants::TABLE_GAP_HEIGHT_LIMIT,
data_conversion::{convert_battery_harvest, ConvertedBatteryData},
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// A table displaying battery information on a per-battery basis.
@ -25,8 +25,8 @@ pub struct BatteryTable {
bounds: Rect,
selected_index: usize,
battery_data: Vec<ConvertedBatteryData>,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
block_border: Borders,
tab_bounds: Vec<Rect>,
}
@ -37,8 +37,8 @@ impl Default for BatteryTable {
bounds: Default::default(),
selected_index: 0,
battery_data: Default::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
block_border: Borders::ALL,
tab_bounds: Default::default(),
}
@ -47,13 +47,13 @@ impl Default for BatteryTable {
impl BatteryTable {
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -147,11 +147,11 @@ impl Widget for BatteryTable {
}
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}

View File

@ -17,7 +17,7 @@ use crate::{
Component, Widget,
},
canvas::Painter,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// A container that "holds" multiple [`BottomWidget`]s through their [`NodeId`]s.
@ -26,8 +26,8 @@ pub struct Carousel {
index: usize,
children: Vec<(NodeId, Cow<'static, str>)>,
bounds: Rect,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
left_button_bounds: Rect,
right_button_bounds: Rect,
}
@ -47,13 +47,13 @@ impl Carousel {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -191,11 +191,11 @@ impl Widget for Carousel {
"Carousel"
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}

View File

@ -17,7 +17,7 @@ use crate::{
},
canvas::Painter,
data_conversion::{convert_cpu_data_points, ConvertedCpuData},
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// Which part of the [`CpuGraph`] is currently selected.
@ -45,8 +45,8 @@ pub struct CpuGraph {
display_data: Vec<ConvertedCpuData>,
load_avg_data: [f32; 3],
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
}
impl CpuGraph {
@ -75,19 +75,19 @@ impl CpuGraph {
selected: CpuGraphSelection::Graph,
display_data: Default::default(),
load_avg_data: [0.0; 3],
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
}
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -281,11 +281,11 @@ impl Widget for CpuGraph {
self.load_avg_data = data_collection.load_avg_harvest;
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}

View File

@ -9,7 +9,7 @@ use crate::{
},
canvas::Painter,
data_conversion::convert_disk_row,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// A table displaying disk data.
@ -19,8 +19,8 @@ pub struct DiskTable {
display_data: TextTableData,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
block_border: Borders,
show_scroll_index: bool,
}
@ -43,21 +43,21 @@ impl DiskTable {
table,
bounds: Rect::default(),
display_data: Default::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
block_border: Borders::ALL,
show_scroll_index: false,
}
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -126,11 +126,11 @@ impl Widget for DiskTable {
self.display_data = convert_disk_row(data_collection);
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}
}

View File

@ -2,32 +2,32 @@ use tui::layout::Rect;
use crate::{
app::{Component, SelectableType, Widget},
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
pub struct Empty {
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
}
impl Default for Empty {
fn default() -> Self {
Self {
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
}
}
}
impl Empty {
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -46,11 +46,11 @@ impl Widget for Empty {
""
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}

View File

@ -7,7 +7,7 @@ use crate::{
app::{event::ComponentEventResult, time_graph::TimeGraphData, DataCollection},
app::{Component, TimeGraph, Widget},
data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points},
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// A widget that deals with displaying memory usage on a [`TimeGraph`]. Basically just a wrapper
@ -19,8 +19,8 @@ pub struct MemGraph {
mem_data: Vec<(f64, f64)>,
swap_data: Vec<(f64, f64)>,
bounds: Rect,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
}
impl MemGraph {
@ -33,19 +33,19 @@ impl MemGraph {
mem_data: Default::default(),
swap_data: Default::default(),
bounds: Rect::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
}
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -126,11 +126,11 @@ impl Widget for MemGraph {
self.swap_labels = swap_labels;
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}
}

View File

@ -15,7 +15,7 @@ use crate::{
},
canvas::Painter,
data_conversion::convert_network_data_points,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
units::data_units::DataUnit,
utils::gen_util::*,
};
@ -381,8 +381,8 @@ pub struct NetGraph {
hide_legend: bool,
bounds: Rect,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
}
impl NetGraph {
@ -404,8 +404,8 @@ impl NetGraph {
use_binary_prefix: app_config_fields.network_use_binary_prefix,
hide_legend: false,
bounds: Rect::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
}
}
@ -416,13 +416,13 @@ impl NetGraph {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -569,11 +569,11 @@ impl Widget for NetGraph {
}
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}
}
@ -584,8 +584,8 @@ pub struct OldNetGraph {
net_graph: NetGraph,
table: TextTable,
bounds: Rect,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
}
impl OldNetGraph {
@ -602,19 +602,19 @@ impl OldNetGraph {
.try_show_gap(config.table_gap)
.unselectable(),
bounds: Rect::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
}
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -709,11 +709,11 @@ impl Widget for OldNetGraph {
}
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}
}

View File

@ -26,7 +26,7 @@ use crate::{
},
canvas::Painter,
data_conversion::{get_string_with_bytes, get_string_with_bytes_per_second},
options::{layout_options::LayoutRule, ProcessDefaults},
options::{layout_options::WidgetLayoutRule, ProcessDefaults},
utils::error::BottomError,
Pid,
};
@ -271,8 +271,8 @@ pub struct ProcessManager {
display_data: TextTableData,
process_filter: Option<Result<Query, BottomError>>,
block_border: Borders,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
show_scroll_index: bool,
}
@ -311,8 +311,8 @@ impl ProcessManager {
display_data: Default::default(),
process_filter: None,
block_border: Borders::ALL,
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
show_scroll_index: false,
};
@ -330,13 +330,13 @@ impl ProcessManager {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -1362,11 +1362,11 @@ impl Widget for ProcessManager {
};
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}

View File

@ -9,7 +9,7 @@ use crate::{
},
canvas::Painter,
data_conversion::convert_temp_row,
options::layout_options::LayoutRule,
options::layout_options::WidgetLayoutRule,
};
/// A table displaying temperature data.
@ -18,8 +18,8 @@ pub struct TempTable {
bounds: Rect,
display_data: TextTableData,
temp_type: TemperatureType,
width: LayoutRule,
height: LayoutRule,
width: WidgetLayoutRule,
height: WidgetLayoutRule,
block_border: Borders,
show_scroll_index: bool,
}
@ -39,8 +39,8 @@ impl TempTable {
bounds: Rect::default(),
display_data: Default::default(),
temp_type: TemperatureType::default(),
width: LayoutRule::default(),
height: LayoutRule::default(),
width: WidgetLayoutRule::default(),
height: WidgetLayoutRule::default(),
block_border: Borders::ALL,
show_scroll_index: false,
}
@ -53,13 +53,13 @@ impl TempTable {
}
/// Sets the width.
pub fn width(mut self, width: LayoutRule) -> Self {
pub fn width(mut self, width: WidgetLayoutRule) -> Self {
self.width = width;
self
}
/// Sets the height.
pub fn height(mut self, height: LayoutRule) -> Self {
pub fn height(mut self, height: WidgetLayoutRule) -> Self {
self.height = height;
self
}
@ -128,11 +128,11 @@ impl Widget for TempTable {
self.display_data = convert_temp_row(data_collection, &self.temp_type);
}
fn width(&self) -> LayoutRule {
fn width(&self) -> WidgetLayoutRule {
self.width
}
fn height(&self) -> LayoutRule {
fn height(&self) -> WidgetLayoutRule {
self.height
}
}

View File

@ -462,19 +462,23 @@ pub const DEFAULT_BATTERY_LAYOUT: &str = r##"
pub const DEFAULT_BASIC_LAYOUT: &str = r##"
[[row]]
ratio = 0
[[row.child]]
type = "bcpu"
[[row]]
ratio = 0
[[row.child]]
type = "bmem"
[[row.child]]
type = "bnet"
[[row]]
ratio = 0
[[row.child]]
[[row.child.child]]
length = 1
type = "empty"
[[row]]
ratio = 0
[[row.child]]
default = true
carousel_children = ["proc", "temp", "disk"]

View File

@ -33,18 +33,19 @@ pub enum LayoutRowChild {
#[derive(Clone, Deserialize, Debug, Serialize)]
pub struct FinalWidget {
#[serde(flatten)]
pub rule: Option<LayoutRule>,
pub rule: Option<WidgetLayoutRule>,
#[serde(rename = "type")]
pub widget_type: String,
pub default: Option<bool>,
}
/// A "rule" denoting how this component is to be laid out.
/// A "rule" denoting how a widget is to be laid out.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(untagged)]
pub enum LayoutRule {
/// Expand to whatever space is left; the `ratio` determines how much
/// space to take if there is more than one [`LayoutRule::Expand`] component.
pub enum WidgetLayoutRule {
/// Expand to whatever space is left. The `ratio` field determines
/// how much space to allocate if there are other [`WidgetLayoutRule::Expand`]
/// items.
Expand { ratio: u16 },
/// Take up an exact amount of space, if possible.
@ -54,8 +55,8 @@ pub enum LayoutRule {
},
}
impl Default for LayoutRule {
impl Default for WidgetLayoutRule {
fn default() -> Self {
LayoutRule::Expand { ratio: 1 }
WidgetLayoutRule::Expand { ratio: 1 }
}
}

View File

@ -73,6 +73,28 @@ where
}
inner
}
fn outer_size(&self, original: Size) -> Size {
let mut outer = original;
if self.borders.intersects(Borders::LEFT) {
outer.width = outer.width.saturating_add(1);
}
if self.borders.intersects(Borders::TOP)
|| self.left_text.is_some()
|| self.right_text.is_some()
{
outer.height = outer.height.saturating_add(1);
}
if self.borders.intersects(Borders::RIGHT) {
outer.width = outer.width.saturating_add(1);
}
if self.borders.intersects(Borders::BOTTOM) {
outer.height = outer.height.saturating_add(1);
}
outer
}
}
impl<Message, Child> TmpComponent<Message> for Block<Message, Child>
@ -136,7 +158,7 @@ where
);
node.children = vec![child_node];
child_size
self.outer_size(child_size)
} else {
Size {
width: 0,

View File

@ -62,28 +62,34 @@ impl<Message> FlexElement<Message> {
}
/// Assumes the flex is NOT 0. Will call layout on its children, but will ignore
/// its sizing.
/// its sizing on the given axis.
///
/// **Note it does NOT check for div by zero!** Please check this yourself.
pub(crate) fn ratio_layout(
&self, bounds: Bounds, total_flex: u16, node: &mut LayoutNode, parent_alignment: Axis,
) -> Size {
let (width, height) = match parent_alignment {
Axis::Horizontal => (bounds.max_width * self.flex / total_flex, bounds.max_height),
Axis::Vertical => (bounds.max_width, bounds.max_height * self.flex / total_flex),
let (min_width, min_height, max_width, max_height) = match parent_alignment {
Axis::Horizontal => {
let w = bounds.max_width * self.flex / total_flex;
(w, 0, w, bounds.max_height)
}
Axis::Vertical => {
let h = bounds.max_height * self.flex / total_flex;
(0, h, bounds.max_width, h)
}
};
self.element.layout(
let ratio_res = self.element.layout(
Bounds {
min_width: width,
min_height: height,
max_width: width,
max_height: height,
min_width,
min_height,
max_width,
max_height,
},
node,
);
Size { width, height }
ratio_res
}
}

View File

@ -1,3 +1,5 @@
use std::cmp::max;
use tui::{backend::Backend, layout::Rect, Frame};
pub mod flex_element;
@ -119,11 +121,14 @@ impl<Message> TmpComponent<Message> for Flex<Message> {
}
fn layout(&self, bounds: Bounds, node: &mut LayoutNode) -> Size {
let mut remaining_bounds = bounds;
let mut remaining_bounds = Bounds {
min_width: 0,
min_height: 0,
max_width: bounds.max_width,
max_height: bounds.max_height,
};
let mut children = vec![LayoutNode::default(); self.children.len()];
let mut flexible_children_indexes = vec![];
let mut current_x_offset = 0;
let mut current_y_offset = 0;
let mut sizes = Vec::with_capacity(self.children.len());
let mut current_size = Size::default();
let mut total_flex = 0;
@ -139,7 +144,10 @@ impl<Message> TmpComponent<Message> for Flex<Message> {
let size = if remaining_bounds.has_space() {
let size = child.child_layout(remaining_bounds, child_node);
current_size += size;
remaining_bounds.shrink_size(size);
match &self.alignment {
Axis::Horizontal => remaining_bounds.shrink_width_size(size),
Axis::Vertical => remaining_bounds.shrink_height_size(size),
}
size
} else {
@ -160,13 +168,23 @@ impl<Message> TmpComponent<Message> for Flex<Message> {
//
// NB: If you **EVER** make changes in this function, ensure these assumptions
// still hold!
// FIXME: [Remove Unsafe] Can potentially just use zips... and maybe partition to combine above and here
let child = unsafe { self.children.get_unchecked(index) };
let child_node = unsafe { children.get_unchecked_mut(index) };
let size = unsafe { sizes.get_unchecked_mut(index) };
let new_size =
child.ratio_layout(remaining_bounds, total_flex, child_node, self.alignment);
current_size += new_size;
match &self.alignment {
Axis::Horizontal => {
current_size.width += new_size.width;
current_size.height = max(current_size.height, new_size.height);
}
Axis::Vertical => {
current_size.width = max(current_size.width, new_size.width);
current_size.height += new_size.height;
}
}
*size = new_size;
});
@ -184,6 +202,9 @@ impl<Message> TmpComponent<Message> for Flex<Message> {
// Now that we're done determining sizes, convert all children into the appropriate
// layout nodes. Remember - parents determine children, and so, we determine
// children here!
let mut current_x_offset = 0;
let mut current_y_offset = 0;
sizes
.iter()
.zip(children.iter_mut())
@ -200,7 +221,6 @@ impl<Message> TmpComponent<Message> for Flex<Message> {
}
});
node.children = children;
current_size
}
}

View File

@ -1,6 +1,8 @@
use std::cmp::{max, min};
use tui::{text::Text, widgets::Paragraph, Frame};
use crate::tuine::{DrawContext, StateContext, TmpComponent};
use crate::tuine::{Bounds, DrawContext, LayoutNode, Size, StateContext, TmpComponent};
/// A [`CpuSimple`] is a widget displaying simple CPU stats.
pub struct CpuSimple {}
@ -27,4 +29,11 @@ impl<Message> TmpComponent<Message> for CpuSimple {
rect,
);
}
fn layout(&self, bounds: Bounds, _node: &mut LayoutNode) -> Size {
Size {
width: bounds.max_width,
height: max(bounds.min_height, min(4, bounds.max_height)), // FIXME: Temp value - this is not correct; should be based on data.
}
}
}

View File

@ -1,6 +1,8 @@
use std::cmp::{max, min};
use tui::{text::Text, widgets::Paragraph, Frame};
use crate::tuine::{DrawContext, StateContext, TmpComponent};
use crate::tuine::{Bounds, DrawContext, LayoutNode, Size, StateContext, TmpComponent};
/// A [`MemSimple`] is a widget displaying simple CPU stats.
pub struct MemSimple {}
@ -27,4 +29,11 @@ impl<Message> TmpComponent<Message> for MemSimple {
rect,
);
}
fn layout(&self, bounds: Bounds, _node: &mut LayoutNode) -> Size {
Size {
width: bounds.max_width,
height: max(bounds.min_height, min(2, bounds.max_height)),
}
}
}

View File

@ -1,6 +1,8 @@
use std::cmp::{max, min};
use tui::{text::Text, widgets::Paragraph, Frame};
use crate::tuine::{DrawContext, StateContext, TmpComponent};
use crate::tuine::{Bounds, DrawContext, LayoutNode, Size, StateContext, TmpComponent};
/// A [`NetSimple`] is a widget displaying simple CPU stats.
pub struct NetSimple {}
@ -27,4 +29,11 @@ impl<Message> TmpComponent<Message> for NetSimple {
rect,
);
}
fn layout(&self, bounds: Bounds, _node: &mut LayoutNode) -> Size {
Size {
width: bounds.max_width,
height: max(bounds.min_height, min(2, bounds.max_height)),
}
}
}

View File

@ -26,17 +26,21 @@ impl Bounds {
self.max_height = self.max_height.saturating_sub(height);
}
/// Shrinks by a given [`Size`].
pub fn shrink_size(&mut self, size: Size) {
/// Shrinks the width by a given [`Size`].
pub fn shrink_width_size(&mut self, size: Size) {
self.max_width = self.max_width.saturating_sub(size.width);
}
/// Shrinks the height by a given [`Size`].
pub fn shrink_height_size(&mut self, size: Size) {
self.max_height = self.max_height.saturating_sub(size.height);
}
/// Returns whether there is any space left in this bound for laying out things.
pub fn has_space(&self) -> bool {
self.min_width >= self.max_width
|| self.min_height >= self.max_height
!(self.min_width > self.max_width
|| self.min_height > self.max_height
|| self.max_width == 0
|| self.max_height == 0
|| self.max_height == 0)
}
}

View File

@ -105,7 +105,7 @@ where
};
for msg in messages {
debug!("Message: {:?}", msg); // FIXME: Remove this debug line!
// debug!("Message: {:?}", msg);
let msg_result = application.update(msg);
should_redraw = should_redraw || msg_result;
}