2022-01-09 20:16:14 +00:00
|
|
|
use crate::{
|
|
|
|
layout::{CellSize, Layout, LineDirection},
|
|
|
|
sizing::Sizing,
|
|
|
|
Padding, Size,
|
|
|
|
};
|
2021-12-17 14:33:29 +00:00
|
|
|
use egui::Ui;
|
2022-01-09 20:16:14 +00:00
|
|
|
|
|
|
|
enum GridDirection {
|
|
|
|
Horizontal,
|
|
|
|
Vertical,
|
|
|
|
}
|
2021-12-17 14:33:29 +00:00
|
|
|
|
|
|
|
pub struct GridBuilder<'a> {
|
|
|
|
ui: &'a mut Ui,
|
2022-01-09 20:16:14 +00:00
|
|
|
sizing: Sizing,
|
2021-12-17 14:33:29 +00:00
|
|
|
padding: Padding,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> GridBuilder<'a> {
|
2022-01-09 20:16:14 +00:00
|
|
|
/// Create new grid builder
|
2022-02-09 11:56:01 +00:00
|
|
|
/// After adding size hints with `[Self::column]`/`[Self::columns]` the grid can be build with `[Self::horizontal]`/`[Self::vertical]`
|
2021-12-17 14:33:29 +00:00
|
|
|
pub fn new(ui: &'a mut Ui, padding: Padding) -> Self {
|
2022-01-09 20:16:14 +00:00
|
|
|
let sizing = Sizing::new();
|
|
|
|
|
|
|
|
Self {
|
|
|
|
ui,
|
|
|
|
sizing,
|
|
|
|
padding,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add size hint for column/row
|
|
|
|
pub fn size(mut self, size: Size) -> Self {
|
|
|
|
self.sizing.add_size(size);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add size hint for columns/rows [count] times
|
|
|
|
pub fn sizes(mut self, size: Size, count: usize) -> Self {
|
|
|
|
for _ in 0..count {
|
2022-02-09 11:56:01 +00:00
|
|
|
self.sizing.add_size(size);
|
2022-01-09 20:16:14 +00:00
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Build horizontal grid
|
2022-02-09 11:02:19 +00:00
|
|
|
/// Takes the available horizontal width, so there can't be anything right of the grid or the container will grow slowly!
|
2022-01-09 20:16:14 +00:00
|
|
|
pub fn horizontal<F>(self, grid: F)
|
|
|
|
where
|
|
|
|
F: for<'b> FnOnce(Grid<'a, 'b>),
|
|
|
|
{
|
|
|
|
let widths = self.sizing.into_lengths(
|
|
|
|
self.ui.available_rect_before_wrap().width() - 2.0 * self.padding.outer,
|
|
|
|
self.padding.inner,
|
|
|
|
);
|
2022-02-09 12:09:10 +00:00
|
|
|
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::Vertical);
|
2022-01-09 20:16:14 +00:00
|
|
|
grid(Grid {
|
|
|
|
layout: &mut layout,
|
|
|
|
direction: GridDirection::Horizontal,
|
|
|
|
padding: self.padding.clone(),
|
|
|
|
widths,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Build vertical grid
|
2022-02-09 11:02:19 +00:00
|
|
|
/// Takes the full available vertical height, so there can't be anything below of the grid or the container will grow slowly!
|
2022-01-09 20:16:14 +00:00
|
|
|
pub fn vertical<F>(self, grid: F)
|
|
|
|
where
|
|
|
|
F: for<'b> FnOnce(Grid<'a, 'b>),
|
|
|
|
{
|
|
|
|
let widths = self.sizing.into_lengths(
|
|
|
|
self.ui.available_rect_before_wrap().height() - 2.0 * self.padding.outer,
|
|
|
|
self.padding.inner,
|
|
|
|
);
|
2022-02-09 12:09:10 +00:00
|
|
|
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::Horizontal);
|
2022-01-09 20:16:14 +00:00
|
|
|
grid(Grid {
|
|
|
|
layout: &mut layout,
|
|
|
|
direction: GridDirection::Vertical,
|
|
|
|
padding: self.padding.clone(),
|
|
|
|
widths,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Grid<'a, 'b> {
|
|
|
|
layout: &'b mut Layout<'a>,
|
|
|
|
direction: GridDirection,
|
|
|
|
padding: Padding,
|
|
|
|
widths: Vec<f32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> Grid<'a, 'b> {
|
|
|
|
fn size(&mut self) -> (CellSize, CellSize) {
|
|
|
|
match self.direction {
|
|
|
|
GridDirection::Horizontal => (
|
|
|
|
CellSize::Absolute(self.widths.remove(0)),
|
|
|
|
CellSize::Remainder,
|
|
|
|
),
|
|
|
|
GridDirection::Vertical => (
|
|
|
|
CellSize::Remainder,
|
|
|
|
CellSize::Absolute(self.widths.remove(0)),
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add empty cell
|
|
|
|
pub fn empty(&mut self) {
|
|
|
|
assert!(
|
|
|
|
!self.widths.is_empty(),
|
|
|
|
"Tried using more grid cells then available."
|
|
|
|
);
|
|
|
|
|
|
|
|
let (width, height) = self.size();
|
|
|
|
self.layout.empty(width, height);
|
|
|
|
}
|
|
|
|
|
2022-02-09 12:00:09 +00:00
|
|
|
fn _cell(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) {
|
2022-01-09 20:16:14 +00:00
|
|
|
assert!(
|
|
|
|
!self.widths.is_empty(),
|
|
|
|
"Tried using more grid cells then available."
|
|
|
|
);
|
|
|
|
|
|
|
|
let (width, height) = self.size();
|
|
|
|
self.layout.add(width, height, clip, add_contents);
|
2021-12-17 14:33:29 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 12:03:02 +00:00
|
|
|
/// Add cell, content is wrapped
|
2022-01-09 20:16:14 +00:00
|
|
|
pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) {
|
2022-02-09 12:01:43 +00:00
|
|
|
self._cell(false, add_contents);
|
2021-12-17 14:33:29 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 12:01:43 +00:00
|
|
|
/// Add cell, content is clipped
|
2022-01-09 20:16:14 +00:00
|
|
|
pub fn cell_noclip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
|
2022-02-09 12:01:43 +00:00
|
|
|
self._cell(true, add_contents);
|
2022-01-09 20:16:14 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 12:00:09 +00:00
|
|
|
fn _grid(&mut self, clip: bool, grid_builder: impl FnOnce(GridBuilder<'_>)) {
|
2022-01-09 20:16:14 +00:00
|
|
|
let padding = self.padding.clone();
|
|
|
|
self._cell(clip, |ui| {
|
|
|
|
grid_builder(GridBuilder::new(ui, padding));
|
|
|
|
});
|
|
|
|
}
|
2022-02-09 12:01:43 +00:00
|
|
|
/// Add grid as cell
|
2022-02-09 11:56:01 +00:00
|
|
|
pub fn grid(&mut self, grid_builder: impl FnOnce(GridBuilder<'_>)) {
|
2022-02-09 12:01:43 +00:00
|
|
|
self._grid(false, grid_builder);
|
2022-01-09 20:16:14 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 12:01:43 +00:00
|
|
|
/// Add grid as cell, content is clipped
|
2022-02-09 11:56:01 +00:00
|
|
|
pub fn grid_noclip(&mut self, grid_builder: impl FnOnce(GridBuilder<'_>)) {
|
2022-02-09 12:01:43 +00:00
|
|
|
self._grid(true, grid_builder);
|
2022-01-09 20:16:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> Drop for Grid<'a, 'b> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
while !self.widths.is_empty() {
|
|
|
|
self.empty();
|
|
|
|
}
|
2021-12-17 14:33:29 +00:00
|
|
|
}
|
|
|
|
}
|