feat(tui): forge widgets only use required lines
All checks were successful
Rust / build (push) Successful in 10m32s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
Release Please / Release-plz (push) Successful in 1m30s
ci/woodpecker/cron/cron-docker-builder Pipeline was successful
ci/woodpecker/cron/push-next Pipeline was successful
ci/woodpecker/cron/tag-created Pipeline was successful

Rather than filling all the space available, the ForgeWidget now only
uses as many lines as it needs to show its contents.
This commit is contained in:
Paul Campbell 2024-08-28 22:25:31 +01:00
parent 2959bdfad4
commit 52bd9cc30b
4 changed files with 69 additions and 17 deletions

View file

@ -3,17 +3,26 @@ use std::collections::BTreeMap;
use git_next_core::ForgeAlias; use git_next_core::ForgeAlias;
use ratatui::{ use ratatui::{
buffer::Buffer, buffer::Buffer,
layout::{Constraint, Direction, Layout, Rect}, layout::{Direction, Layout, Rect},
widgets::Widget, widgets::Widget,
}; };
use crate::tui::actor::{ForgeState, ViewState}; use crate::tui::actor::ForgeState;
use super::forge::ForgeWidget; use super::{forge::ForgeWidget, HeightContraintLength};
pub struct ConfiguredAppWidget<'a> { pub struct ConfiguredAppWidget<'a> {
pub forges: &'a BTreeMap<ForgeAlias, ForgeState>, pub forges: &'a BTreeMap<ForgeAlias, ForgeState>,
} }
impl<'a> HeightContraintLength for ConfiguredAppWidget<'a> {
fn height_constraint_length(&self) -> u16 {
self.children()
.iter()
.map(HeightContraintLength::height_constraint_length)
.sum::<u16>()
+ 2 // top + bottom borders
}
}
impl<'a> Widget for ConfiguredAppWidget<'a> { impl<'a> Widget for ConfiguredAppWidget<'a> {
fn render(self, area: Rect, buf: &mut Buffer) fn render(self, area: Rect, buf: &mut Buffer)
where where
@ -22,15 +31,20 @@ impl<'a> Widget for ConfiguredAppWidget<'a> {
let layout_forge_list = Layout::default() let layout_forge_list = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints( .constraints(
self.forges self.children()
.iter() .iter()
.map(|(_alias, state)| match state.view_state { .map(HeightContraintLength::height_constraint_length),
ViewState::Collapsed => Constraint::Length(1),
ViewState::Expanded => Constraint::Fill(1),
}),
) )
.split(area); .split(area);
self.children()
.into_iter()
.enumerate()
.for_each(|(i, w)| w.render(layout_forge_list[i], buf));
}
}
impl<'a> ConfiguredAppWidget<'a> {
fn children(&self) -> Vec<ForgeWidget<'a>> {
self.forges self.forges
.iter() .iter()
.map(|(forge_alias, state)| ForgeWidget { .map(|(forge_alias, state)| ForgeWidget {
@ -38,7 +52,6 @@ impl<'a> Widget for ConfiguredAppWidget<'a> {
repos: &state.repos, repos: &state.repos,
view_state: state.view_state, view_state: state.view_state,
}) })
.enumerate() .collect::<Vec<_>>()
.for_each(|(i, w)| w.render(layout_forge_list[i], buf));
} }
} }

View file

@ -2,9 +2,16 @@
use git_next_core::ForgeAlias; use git_next_core::ForgeAlias;
use ratatui::{buffer::Buffer, layout::Rect, text::Text, widgets::Widget}; use ratatui::{buffer::Buffer, layout::Rect, text::Text, widgets::Widget};
use crate::tui::components::HeightContraintLength;
pub struct CollapsedForgeWidget<'a> { pub struct CollapsedForgeWidget<'a> {
pub forge_alias: &'a ForgeAlias, pub forge_alias: &'a ForgeAlias,
} }
impl<'a> HeightContraintLength for CollapsedForgeWidget<'a> {
fn height_constraint_length(&self) -> u16 {
1
}
}
impl<'a> Widget for CollapsedForgeWidget<'a> { impl<'a> Widget for CollapsedForgeWidget<'a> {
fn render(self, area: Rect, buf: &mut Buffer) fn render(self, area: Rect, buf: &mut Buffer)
where where

View file

@ -17,6 +17,15 @@ pub struct ExpandedForgeWidget<'a> {
pub forge_alias: &'a ForgeAlias, pub forge_alias: &'a ForgeAlias,
pub repos: &'a BTreeMap<RepoAlias, RepoState>, pub repos: &'a BTreeMap<RepoAlias, RepoState>,
} }
impl<'a> HeightContraintLength for ExpandedForgeWidget<'a> {
fn height_constraint_length(&self) -> u16 {
self.children()
.iter()
.map(HeightContraintLength::height_constraint_length)
.sum::<u16>()
+ 2 // top + bottom borders
}
}
impl<'a> Widget for ExpandedForgeWidget<'a> { impl<'a> Widget for ExpandedForgeWidget<'a> {
fn render(self, area: Rect, buf: &mut Buffer) fn render(self, area: Rect, buf: &mut Buffer)
where where
@ -25,11 +34,7 @@ impl<'a> Widget for ExpandedForgeWidget<'a> {
let block = Block::default() let block = Block::default()
.title(Title::from(format!(" forge: {} ", self.forge_alias)).alignment(Alignment::Left)) .title(Title::from(format!(" forge: {} ", self.forge_alias)).alignment(Alignment::Left))
.borders(Borders::ALL); .borders(Borders::ALL);
let children = self let children = self.children();
.repos
.values()
.map(|repo_state| RepoWidget { repo_state })
.collect::<Vec<_>>();
let layout = Layout::default() let layout = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints( .constraints(
@ -45,3 +50,11 @@ impl<'a> Widget for ExpandedForgeWidget<'a> {
.for_each(|(i, w)| w.render(layout[i], buf)); .for_each(|(i, w)| w.render(layout[i], buf));
} }
} }
impl<'a> ExpandedForgeWidget<'a> {
fn children(&self) -> Vec<RepoWidget<'a>> {
self.repos
.values()
.map(|repo_state| RepoWidget { repo_state })
.collect::<Vec<_>>()
}
}

View file

@ -4,27 +4,46 @@ mod expanded;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use collapsed::CollapsedForgeWidget;
use expanded::ExpandedForgeWidget;
use git_next_core::{ForgeAlias, RepoAlias}; use git_next_core::{ForgeAlias, RepoAlias};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use crate::tui::actor::{RepoState, ViewState}; use crate::tui::actor::{RepoState, ViewState};
use super::HeightContraintLength;
pub struct ForgeWidget<'a> { pub struct ForgeWidget<'a> {
pub forge_alias: &'a ForgeAlias, pub forge_alias: &'a ForgeAlias,
pub repos: &'a BTreeMap<RepoAlias, RepoState>, pub repos: &'a BTreeMap<RepoAlias, RepoState>,
pub view_state: ViewState, pub view_state: ViewState,
} }
impl<'a> HeightContraintLength for ForgeWidget<'a> {
fn height_constraint_length(&self) -> u16 {
match self.view_state {
ViewState::Collapsed => CollapsedForgeWidget {
forge_alias: self.forge_alias,
}
.height_constraint_length(),
ViewState::Expanded => ExpandedForgeWidget {
forge_alias: self.forge_alias,
repos: self.repos,
}
.height_constraint_length(),
}
}
}
impl<'a> Widget for ForgeWidget<'a> { impl<'a> Widget for ForgeWidget<'a> {
fn render(self, area: Rect, buf: &mut Buffer) fn render(self, area: Rect, buf: &mut Buffer)
where where
Self: Sized, Self: Sized,
{ {
match self.view_state { match self.view_state {
ViewState::Collapsed => collapsed::CollapsedForgeWidget { ViewState::Collapsed => CollapsedForgeWidget {
forge_alias: self.forge_alias, forge_alias: self.forge_alias,
} }
.render(area, buf), .render(area, buf),
ViewState::Expanded => expanded::ExpandedForgeWidget { ViewState::Expanded => ExpandedForgeWidget {
forge_alias: self.forge_alias, forge_alias: self.forge_alias,
repos: self.repos, repos: self.repos,
} }