Skip to content

Commit

Permalink
Calculate the column widths using cassowary
Browse files Browse the repository at this point in the history
  • Loading branch information
medwards committed Aug 7, 2021
1 parent 0d6a990 commit e4e4bc6
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 24 deletions.
60 changes: 42 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Expand Up @@ -9,6 +9,7 @@ edition = "2018"
[dependencies]
git2 = "0.13"
crossterm = { version = "0.19" }
tui = { version = "0.14", default-features = false, features = ['crossterm'] }
tui = { version = "0.16", default-features = false, features = ['crossterm'] }
cassowary = "0.3" # keep this in sync /w tui?
clap = { version = "3.0.0-beta.2" }
chrono = "0.4.19"
15 changes: 10 additions & 5 deletions src/main.rs
Expand Up @@ -30,6 +30,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let tick_rate = std::time::Duration::from_millis(200);
let mut handler = controller::EventHandler::new(tick_rate);

let bounds: Vec<_> = (0..6).map(|_| cassowary::Variable::new()).collect();
let window_width = cassowary::Variable::new();
let mut column_solver = widgets::commit_list_column_width_solver(&bounds, &window_width);

// TODO: use RAII for this somehow
crossterm::execute!(std::io::stdout(), crossterm::terminal::EnterAlternateScreen)?;
crossterm::terminal::enable_raw_mode().expect("can run in raw mode");
Expand Down Expand Up @@ -85,17 +89,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
drop(commits);
app_model.resize_revision_window(length);

column_solver
.suggest_value(window_width, chunk_commit.width as f64)
.expect("constraints solver failed");
let column_widths = widgets::solver_changes_to_lengths(&column_solver, &bounds);

let list = tui::widgets::Table::new(commit_items)
.block(commits_block)
.highlight_style(
tui::style::Style::default().add_modifier(tui::style::Modifier::BOLD),
)
// TODO: https://github.com/fdehau/tui-rs/issues/499
.widths(&[
tui::layout::Constraint::Length(84),
tui::layout::Constraint::Length(40),
tui::layout::Constraint::Length(10), // Commit date (truncates time by default)
]);
.widths(column_widths.as_slice());

let (details_index, details_window, details_length) = app_model.diff_line_scroll();
let details_scroll = widgets::VerticalBar {
Expand Down
57 changes: 57 additions & 0 deletions src/widgets.rs
@@ -1,3 +1,6 @@
use cassowary::strength::{REQUIRED, STRONG, WEAK};
use cassowary::WeightedRelation::*;
use cassowary::{Solver, Variable};
use tui::buffer::Buffer;
use tui::layout::Rect;
use tui::style::Style;
Expand Down Expand Up @@ -46,3 +49,57 @@ impl Widget for VerticalBar {
buf.set_style(window_area, self.style);
}
}

// bounds consists of pairs of variables representing left and right position of the column
pub fn commit_list_column_width_solver(bounds: &[Variable], window_width: &Variable) -> Solver {
let mut solver = Solver::new();
solver
.add_constraints(&[
*window_width | GE(REQUIRED) | 0.0, // positive window width
bounds[0] | EQ(REQUIRED) | 0.0, // left align
bounds[3] | EQ(REQUIRED) | bounds[4] - 1.0, // right align
bounds[5] | EQ(REQUIRED) | *window_width, // right align
bounds[2] | GE(REQUIRED) | bounds[1], // no overlap
bounds[4] | GE(REQUIRED) | bounds[3], // no overlap
// positive widths
bounds[0] | LE(REQUIRED) | bounds[1],
bounds[2] | LE(REQUIRED) | bounds[3],
bounds[4] | LE(REQUIRED) | bounds[5],
// preferred widths:
bounds[1] - bounds[0] | EQ(WEAK) | *window_width * (72.0 / 100.0),
bounds[3] - bounds[2] | EQ(WEAK) | *window_width * (18.0 / 100.0),
bounds[5] - bounds[4] | EQ(WEAK) | *window_width * (9.0 / 100.0),
// constrain some columns to a range:
bounds[3] - bounds[2] | LE(REQUIRED) | 40.0,
bounds[3] - bounds[2] | GE(STRONG) | 20.0,
bounds[5] - bounds[4] | LE(REQUIRED) | 15.0,
bounds[5] - bounds[4] | GE(STRONG) | 10.0,
// require one column to have a minimum size
bounds[1] - bounds[0] | GE(STRONG) | 50.0,
// fixed length
//box1.right - box1.left | EQ(WEAK) | 79.0,
//box2.right - box2.left | EQ(WEAK) | 20.0,
//box3.right - box3.left | EQ(WEAK) | 10.0,
])
.unwrap();
solver
.add_edit_variable(*window_width, STRONG)
.expect("Unable to add edit variable");

solver
}

pub fn solver_changes_to_lengths(
solver: &Solver,
bounds: &[Variable],
) -> Vec<tui::layout::Constraint> {
let widths: Vec<_> = bounds
.windows(2)
.map(|bounds| solver.get_value(bounds[1]) - solver.get_value(bounds[0]))
.collect();
vec![
tui::layout::Constraint::Length((widths[0] + widths[1]) as u16),
tui::layout::Constraint::Length((widths[2] + widths[3]) as u16),
tui::layout::Constraint::Length((widths[4]) as u16),
]
}

0 comments on commit e4e4bc6

Please sign in to comment.