1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 13:50:04 -04:00

combine vertical/horizontal variant to remove duplicate code

This commit is contained in:
René Rössler
2022-01-09 21:16:14 +01:00
parent a346bcf8a3
commit 7dec7054fb
7 changed files with 477 additions and 725 deletions

View File

@@ -1,26 +1,158 @@
mod horizontal;
mod vertical;
use crate::Padding;
use crate::{
layout::{CellSize, Layout, LineDirection},
sizing::Sizing,
Padding, Size,
};
use egui::Ui;
pub use horizontal::*;
pub use vertical::*;
enum GridDirection {
Horizontal,
Vertical,
}
pub struct GridBuilder<'a> {
ui: &'a mut Ui,
sizing: Sizing,
padding: Padding,
}
impl<'a> GridBuilder<'a> {
/// Create new grid builder
/// After adding size hints with [Self::column]/[Self::columns] the grid can be build with [Self::horizontal]/[Self::vertical]
pub fn new(ui: &'a mut Ui, padding: Padding) -> Self {
Self { ui, padding }
let sizing = Sizing::new();
Self {
ui,
sizing,
padding,
}
}
pub fn horizontal(self, horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder)) {
horizontal_grid_builder(HorizontalGridBuilder::new(self.ui, self.padding));
/// Add size hint for column/row
pub fn size(mut self, size: Size) -> Self {
self.sizing.add_size(size);
self
}
pub fn vertical(self, vertical_grid_builder: impl FnOnce(VerticalGridBuilder)) {
vertical_grid_builder(VerticalGridBuilder::new(self.ui, self.padding));
/// Add size hint for columns/rows [count] times
pub fn sizes(mut self, size: Size, count: usize) -> Self {
for _ in 0..count {
self.sizing.add_size(size.clone());
}
self
}
/// Build horizontal grid
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,
);
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::TopToBottom);
grid(Grid {
layout: &mut layout,
direction: GridDirection::Horizontal,
padding: self.padding.clone(),
widths,
});
}
/// Build vertical grid
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,
);
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::LeftToRight);
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);
}
pub fn _cell(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) {
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);
}
/// Add cell, content is clipped
pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(true, add_contents);
}
/// Add cell, content is not clipped
pub fn cell_noclip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(false, add_contents);
}
pub fn _grid(&mut self, clip: bool, grid_builder: impl FnOnce(GridBuilder)) {
let padding = self.padding.clone();
self._cell(clip, |ui| {
grid_builder(GridBuilder::new(ui, padding));
});
}
/// Add grid as cell, content is clipped
pub fn grid(&mut self, grid_builder: impl FnOnce(GridBuilder)) {
self._grid(true, grid_builder)
}
/// Add grid as cell, content is not clipped
pub fn grid_noclip(&mut self, grid_builder: impl FnOnce(GridBuilder)) {
self._grid(false, grid_builder)
}
}
impl<'a, 'b> Drop for Grid<'a, 'b> {
fn drop(&mut self) {
while !self.widths.is_empty() {
self.empty();
}
}
}

View File

@@ -1,157 +0,0 @@
use crate::{
layout::{CellSize, LineDirection},
sizing::Sizing,
Layout, Padding, Size,
};
use egui::Ui;
use super::VerticalGridBuilder;
pub struct HorizontalGridBuilder<'a> {
ui: &'a mut Ui,
padding: Padding,
sizing: Sizing,
}
impl<'a> HorizontalGridBuilder<'a> {
/// Create new grid builder for horizontal grid
/// After adding size hints with [Self::column]/[Self::columns] the grid can be build with [Self::build]
pub(crate) fn new(ui: &'a mut Ui, padding: Padding) -> Self {
let layouter = Sizing::new(
ui.available_rect_before_wrap().width() - 2.0 * padding.outer,
padding.inner,
);
Self {
ui,
padding,
sizing: layouter,
}
}
/// Add size hint for column
pub fn column(mut self, size: Size) -> Self {
self.sizing.add_size(size);
self
}
/// Add size hint for columns [count] times
pub fn columns(mut self, size: Size, count: usize) -> Self {
for _ in 0..count {
self.sizing.add_size(size.clone());
}
self
}
/// Build grid
pub fn build<F>(self, horizontal_grid: F)
where
F: for<'b> FnOnce(HorizontalGrid<'a, 'b>),
{
let widths = self.sizing.into_lengths();
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::TopToBottom);
let grid = HorizontalGrid {
layout: &mut layout,
padding: self.padding.clone(),
widths,
};
horizontal_grid(grid);
}
}
pub struct HorizontalGrid<'a, 'b> {
layout: &'b mut Layout<'a>,
padding: Padding,
widths: Vec<f32>,
}
impl<'a, 'b> HorizontalGrid<'a, 'b> {
/// Add empty cell
pub fn empty(&mut self) {
assert!(
!self.widths.is_empty(),
"Tried using more grid cells then available."
);
self.layout.empty(
CellSize::Absolute(self.widths.remove(0)),
CellSize::Remainder,
);
}
pub fn _cell(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) {
assert!(
!self.widths.is_empty(),
"Tried using more grid cells then available."
);
self.layout.add(
CellSize::Absolute(self.widths.remove(0)),
CellSize::Remainder,
clip,
add_contents,
);
}
/// Add cell, content is clipped
pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(true, add_contents);
}
/// Add cell, content is not clipped
pub fn cell_noclip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(false, add_contents);
}
pub fn _horizontal(
&mut self,
clip: bool,
horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder),
) {
let padding = self.padding.clone();
self._cell(clip, |ui| {
horizontal_grid_builder(HorizontalGridBuilder::new(ui, padding));
});
}
/// Add horizontal grid as cell, content is clipped
pub fn horizontal(&mut self, horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder)) {
self._horizontal(true, horizontal_grid_builder)
}
/// Add horizontal grid as cell, content is not clipped
pub fn horizontal_noclip(
&mut self,
horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder),
) {
self._horizontal(false, horizontal_grid_builder)
}
pub fn _vertical(
&mut self,
clip: bool,
vertical_grid_builder: impl FnOnce(VerticalGridBuilder),
) {
let padding = self.padding.clone();
self._cell(clip, |ui| {
vertical_grid_builder(VerticalGridBuilder::new(ui, padding));
});
}
/// Add vertical grid as cell, content is clipped
pub fn vertical(&mut self, vertical_grid_builder: impl FnOnce(VerticalGridBuilder)) {
self._vertical(true, vertical_grid_builder);
}
/// Add vertical grid as cell, content is not clipped
pub fn vertical_noclip(&mut self, vertical_grid_builder: impl FnOnce(VerticalGridBuilder)) {
self._vertical(false, vertical_grid_builder);
}
}
impl<'a, 'b> Drop for HorizontalGrid<'a, 'b> {
fn drop(&mut self) {
while !self.widths.is_empty() {
self.empty();
}
}
}

View File

@@ -1,158 +0,0 @@
use crate::{layout::CellSize, sizing::Sizing, Layout, Padding, Size};
use egui::Ui;
use super::HorizontalGridBuilder;
pub struct VerticalGridBuilder<'a> {
ui: &'a mut Ui,
padding: Padding,
sizing: Sizing,
}
impl<'a> VerticalGridBuilder<'a> {
/// Create new grid builder for vertical grid
/// After adding size hints with [Self::row]/[Self::rows] the grid can be build with [Self::build]
pub(crate) fn new(ui: &'a mut Ui, padding: Padding) -> Self {
let layouter = Sizing::new(
ui.available_rect_before_wrap().height() - 2.0 * padding.outer,
padding.inner,
);
Self {
ui,
padding,
sizing: layouter,
}
}
/// Add size hint for row
pub fn row(mut self, size: Size) -> Self {
self.sizing.add_size(size);
self
}
/// Add size hint for rows [count] times
pub fn rows(mut self, size: Size, count: usize) -> Self {
for _ in 0..count {
self.sizing.add_size(size.clone());
}
self
}
/// Build grid
pub fn build<F>(self, vertical_grid: F)
where
F: for<'b> FnOnce(VerticalGrid<'a, 'b>),
{
let heights = self.sizing.into_lengths();
let mut layout = Layout::new(
self.ui,
self.padding.clone(),
crate::layout::LineDirection::LeftToRight,
);
let grid = VerticalGrid {
layout: &mut layout,
padding: self.padding.clone(),
heights,
};
vertical_grid(grid);
}
}
pub struct VerticalGrid<'a, 'b> {
layout: &'b mut Layout<'a>,
padding: Padding,
heights: Vec<f32>,
}
impl<'a, 'b> VerticalGrid<'a, 'b> {
/// Add empty cell
pub fn empty(&mut self) {
assert!(
!self.heights.is_empty(),
"Tried using more grid cells then available."
);
self.layout.empty(
CellSize::Remainder,
CellSize::Absolute(self.heights.remove(0)),
);
}
pub fn _cell(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) {
assert!(
!self.heights.is_empty(),
"Tried using more grid cells then available."
);
self.layout.add(
CellSize::Remainder,
CellSize::Absolute(self.heights.remove(0)),
clip,
add_contents,
);
}
/// Add cell, content is clipped
pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(true, add_contents);
}
/// Add cell, content is not clipped
pub fn cell_noclip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(false, add_contents);
}
pub fn _horizontal(
&mut self,
clip: bool,
horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder),
) {
let padding = self.padding.clone();
self._cell(clip, |ui| {
horizontal_grid_builder(HorizontalGridBuilder::new(ui, padding));
});
}
/// Add horizontal grid as cell, content is clipped
pub fn horizontal(&mut self, horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder)) {
self._horizontal(true, horizontal_grid_builder)
}
/// Add horizontal grid as cell, content is not clipped
pub fn horizontal_noclip(
&mut self,
horizontal_grid_builder: impl FnOnce(HorizontalGridBuilder),
) {
self._horizontal(false, horizontal_grid_builder)
}
pub fn _vertical(
&mut self,
clip: bool,
vertical_grid_builder: impl FnOnce(VerticalGridBuilder),
) {
let padding = self.padding.clone();
self._cell(clip, |ui| {
vertical_grid_builder(VerticalGridBuilder::new(ui, padding));
});
}
/// Add vertical grid as cell, content is clipped
pub fn vertical(&mut self, vertical_grid_builder: impl FnOnce(VerticalGridBuilder)) {
self._vertical(true, vertical_grid_builder);
}
/// Add vertical grid as cell, content is not clipped
pub fn vertical_noclip(&mut self, vertical_grid_builder: impl FnOnce(VerticalGridBuilder)) {
self._vertical(false, vertical_grid_builder);
}
}
impl<'a, 'b> Drop for VerticalGrid<'a, 'b> {
fn drop(&mut self) {
while !self.heights.is_empty() {
self.empty();
}
}
}

View File

@@ -19,27 +19,20 @@ pub enum Size {
}
pub struct Sizing {
length: f32,
inner_padding: f32,
sizes: Vec<Size>,
}
impl Sizing {
pub fn new(length: f32, inner_padding: f32) -> Self {
Self {
length,
inner_padding,
sizes: vec![],
}
pub fn new() -> Self {
Self { sizes: vec![] }
}
pub fn add_size(&mut self, size: Size) {
self.sizes.push(size);
}
pub fn into_lengths(self) -> Vec<f32> {
pub fn into_lengths(self, length: f32, inner_padding: f32) -> Vec<f32> {
let mut remainders = 0;
let length = self.length;
let sum_non_remainder = self
.sizes
.iter()
@@ -61,7 +54,7 @@ impl Sizing {
}
})
.sum::<f32>()
+ self.inner_padding * (self.sizes.len() + 1) as f32;
+ inner_padding * (self.sizes.len() + 1) as f32;
let avg_remainder_length = if remainders == 0 {
0.0

View File

@@ -20,10 +20,7 @@ pub struct TableBuilder<'a> {
impl<'a> TableBuilder<'a> {
pub fn new(ui: &'a mut Ui, padding: Padding) -> Self {
let sizing = Sizing::new(
ui.available_rect_before_wrap().width() - 2.0 * padding.outer,
padding.inner,
);
let sizing = Sizing::new();
Self {
ui,
@@ -62,7 +59,10 @@ impl<'a> TableBuilder<'a> {
/// Create a header row which always stays visible and at the top
pub fn header(self, height: f32, header: impl FnOnce(TableRow<'_, '_>)) -> Table<'a> {
let widths = self.sizing.into_lengths();
let widths = self.sizing.into_lengths(
self.ui.available_rect_before_wrap().width() - 2.0 * self.padding.outer,
self.padding.inner,
);
let ui = self.ui;
{
let mut layout = Layout::new(ui, self.padding.clone(), LineDirection::TopToBottom);
@@ -92,7 +92,10 @@ impl<'a> TableBuilder<'a> {
where
F: for<'b> FnOnce(TableBody<'b>),
{
let widths = self.sizing.into_lengths();
let widths = self.sizing.into_lengths(
self.ui.available_rect_before_wrap().width() - 2.0 * self.padding.outer,
self.padding.inner,
);
Table {
ui: self.ui,