remove padding, use egui item spacing

This commit is contained in:
René Rössler 2022-02-09 16:00:25 +01:00
parent 6261380180
commit 63a70ab00d
9 changed files with 81 additions and 118 deletions

View file

@ -1,5 +1,5 @@
use egui::Color32;
use egui_extras::{GridBuilder, Padding, Size};
use egui_extras::{GridBuilder, Size};
/// Shows off a table with dynamic layout
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
@ -25,14 +25,14 @@ impl super::Demo for GridDemo {
impl super::View for GridDemo {
fn ui(&mut self, ui: &mut egui::Ui) {
GridBuilder::new(ui, Padding::new(0.0, 0.0))
GridBuilder::new(ui)
.size(Size::Absolute(50.0))
.size(Size::Remainder)
.size(Size::RelativeMinimum {
relative: 0.5,
minimum: 60.0,
})
.size(Size::Absolute(14.0))
.size(Size::Absolute(10.0))
.vertical(|mut grid| {
grid.cell(|ui| {
ui.painter()

View file

@ -1,5 +1,5 @@
use egui::Label;
use egui_extras::{GridBuilder, Padding, Size, TableBuilder};
use egui::{Label, Vec2};
use egui_extras::{GridBuilder, Size, TableBuilder};
/// Shows off a table with dynamic layout
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
@ -30,13 +30,15 @@ impl super::View for TableDemo {
ui.checkbox(&mut self.virtual_scrool, "Virtual scroll demo");
// The table is inside a grid as its container would otherwise grow slowly as it takes all available height
GridBuilder::new(ui, Padding::new(0.0, 0.0))
ui.spacing_mut().item_spacing = Vec2::splat(4.0);
GridBuilder::new(ui)
.size(Size::Remainder)
.size(Size::Absolute(14.0))
.size(Size::Absolute(10.0))
.vertical(|mut grid| {
grid.cell(|ui| {
// TODO: Fix table as a padding smaller than 16 grows the window
TableBuilder::new(ui, Padding::new(3.0, 16.0))
grid.cell_clip(|ui| {
ui.spacing_mut().item_spacing = Vec2::splat(3.0);
TableBuilder::new(ui)
.striped(true)
.column(Size::Absolute(120.0))
.column(Size::RemainderMinimum(180.0))
@ -58,7 +60,7 @@ impl super::View for TableDemo {
row.col(|ui| {
ui.label(index.to_string());
});
row.col(|ui| {
row.col_clip(|ui| {
ui.add(
Label::new("virtual scroll, easily with thousands of rows!")
.wrap(false),
@ -79,7 +81,7 @@ impl super::View for TableDemo {
row.col(|ui| {
ui.label(i.to_string());
});
row.col(|ui| {
row.col_clip(|ui| {
ui.add(
Label::new(
format!("Normal scroll, each row can have a different height. Height: {}", height),

View file

@ -1,7 +1,7 @@
use super::{button::DatePickerButtonState, month_data};
use crate::{GridBuilder, Padding, Size, TableBuilder};
use crate::{GridBuilder, Size, TableBuilder};
use chrono::{Date, Datelike, NaiveDate, Utc, Weekday};
use egui::{Align, Button, Color32, ComboBox, Direction, Id, Label, Layout, RichText, Ui};
use egui::{Align, Button, Color32, ComboBox, Direction, Id, Label, Layout, RichText, Ui, Vec2};
#[derive(Default, Clone)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
@ -52,7 +52,9 @@ impl<'a> DatePickerPopup<'a> {
let weeks = month_data(popup_state.year, popup_state.month);
let mut close = false;
let height = 20.0;
GridBuilder::new(ui, Padding::new(2.0, 0.0))
let spacing = 2.0;
ui.spacing_mut().item_spacing = Vec2::splat(spacing);
GridBuilder::new(ui)
.sizes(
Size::Absolute(height),
match (self.combo_boxes, self.arrows) {
@ -62,7 +64,7 @@ impl<'a> DatePickerPopup<'a> {
},
)
.sizes(
Size::Absolute(2.0 + (height + 2.0) * weeks.len() as f32),
Size::Absolute((spacing + height) * (weeks.len() + 1) as f32),
if self.calendar { 1 } else { 0 },
)
.size(Size::Absolute(height))
@ -70,7 +72,7 @@ impl<'a> DatePickerPopup<'a> {
if self.combo_boxes {
grid.grid_noclip(|builder| {
builder.sizes(Size::Remainder, 3).horizontal(|mut grid| {
grid.cell_noclip(|ui| {
grid.cell(|ui| {
ComboBox::from_id_source("date_picker_year")
.selected_text(popup_state.year.to_string())
.show_ui(ui, |ui| {
@ -90,7 +92,7 @@ impl<'a> DatePickerPopup<'a> {
}
});
});
grid.cell_noclip(|ui| {
grid.cell(|ui| {
ComboBox::from_id_source("date_picker_month")
.selected_text(popup_state.month.to_string())
.show_ui(ui, |ui| {
@ -110,7 +112,7 @@ impl<'a> DatePickerPopup<'a> {
}
});
});
grid.cell_noclip(|ui| {
grid.cell(|ui| {
ComboBox::from_id_source("date_picker_day")
.selected_text(popup_state.day.to_string())
.show_ui(ui, |ui| {
@ -231,7 +233,8 @@ impl<'a> DatePickerPopup<'a> {
if self.calendar {
grid.cell(|ui| {
TableBuilder::new(ui, Padding::new(2.0, 0.0))
ui.spacing_mut().item_spacing = Vec2::new(1.0, 2.0);
TableBuilder::new(ui)
.scroll(false)
.columns(Size::Remainder, if self.calendar_week { 8 } else { 7 })
.header(height, |mut header| {

View file

@ -1,7 +1,7 @@
use crate::{
layout::{CellSize, Layout, LineDirection},
sizing::Sizing,
Padding, Size,
Size,
};
use egui::Ui;
@ -13,20 +13,15 @@ enum GridDirection {
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 {
pub fn new(ui: &'a mut Ui) -> Self {
let sizing = Sizing::new();
Self {
ui,
sizing,
padding,
}
Self { ui, sizing }
}
/// Add size hint for column/row
@ -50,15 +45,14 @@ impl<'a> GridBuilder<'a> {
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,
self.ui.available_rect_before_wrap().width() - self.ui.spacing().item_spacing.x,
self.ui.spacing().item_spacing.x,
);
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::Vertical);
let mut layout = Layout::new(self.ui, LineDirection::Vertical);
grid(Grid {
layout: &mut layout,
direction: GridDirection::Horizontal,
padding: self.padding.clone(),
widths,
sizes: widths,
});
}
@ -68,16 +62,15 @@ impl<'a> GridBuilder<'a> {
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 heights = self.sizing.into_lengths(
self.ui.available_rect_before_wrap().height() - self.ui.spacing().item_spacing.y,
self.ui.spacing().item_spacing.y,
);
let mut layout = Layout::new(self.ui, self.padding.clone(), LineDirection::Horizontal);
let mut layout = Layout::new(self.ui, LineDirection::Horizontal);
grid(Grid {
layout: &mut layout,
direction: GridDirection::Vertical,
padding: self.padding.clone(),
widths,
sizes: heights,
});
}
}
@ -85,20 +78,19 @@ impl<'a> GridBuilder<'a> {
pub struct Grid<'a, 'b> {
layout: &'b mut Layout<'a>,
direction: GridDirection,
padding: Padding,
widths: Vec<f32>,
sizes: 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::Absolute(self.sizes.remove(0)),
CellSize::Remainder,
),
GridDirection::Vertical => (
CellSize::Remainder,
CellSize::Absolute(self.widths.remove(0)),
CellSize::Absolute(self.sizes.remove(0)),
),
}
}
@ -106,7 +98,7 @@ impl<'a, 'b> Grid<'a, 'b> {
/// Add empty cell
pub fn empty(&mut self) {
assert!(
!self.widths.is_empty(),
!self.sizes.is_empty(),
"Tried using more grid cells then available."
);
@ -116,7 +108,7 @@ impl<'a, 'b> Grid<'a, 'b> {
fn _cell(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) {
assert!(
!self.widths.is_empty(),
!self.sizes.is_empty(),
"Tried using more grid cells then available."
);
@ -130,14 +122,13 @@ impl<'a, 'b> Grid<'a, 'b> {
}
/// Add cell, content is clipped
pub fn cell_noclip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
pub fn cell_clip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self._cell(true, add_contents);
}
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));
grid_builder(GridBuilder::new(ui));
});
}
/// Add grid as cell
@ -153,7 +144,7 @@ impl<'a, 'b> Grid<'a, 'b> {
impl<'a, 'b> Drop for Grid<'a, 'b> {
fn drop(&mut self) {
while !self.widths.is_empty() {
while !self.sizes.is_empty() {
self.empty();
}
}

View file

@ -1,5 +1,4 @@
use crate::Padding;
use egui::{Pos2, Rect, Response, Rgba, Sense, Ui, Vec2};
use egui::{Pos2, Rect, Response, Rgba, Sense, Ui};
#[derive(Clone, Copy)]
pub(crate) enum CellSize {
@ -30,7 +29,6 @@ pub(crate) enum LineDirection {
/// Positions cells in `[LineDirection]` and starts a new line on `[Layout::end_line]`
pub struct Layout<'l> {
ui: &'l mut Ui,
padding: Padding,
direction: LineDirection,
rect: Rect,
pos: Pos2,
@ -38,15 +36,12 @@ pub struct Layout<'l> {
}
impl<'l> Layout<'l> {
pub(crate) fn new(ui: &'l mut Ui, padding: Padding, direction: LineDirection) -> Self {
let rect = ui
.available_rect_before_wrap()
.shrink(padding.inner + padding.outer);
pub(crate) fn new(ui: &'l mut Ui, direction: LineDirection) -> Self {
let rect = ui.available_rect_before_wrap();
let pos = rect.left_top();
Self {
ui,
padding,
rect,
pos,
max: pos,
@ -64,11 +59,11 @@ impl<'l> Layout<'l> {
max: Pos2 {
x: match width {
CellSize::Absolute(width) => self.pos.x + width,
CellSize::Remainder => self.rect.right(),
CellSize::Remainder => self.rect.right() - self.ui.spacing().item_spacing.x,
},
y: match height {
CellSize::Absolute(height) => self.pos.y + height,
CellSize::Remainder => self.rect.bottom(),
CellSize::Remainder => self.rect.bottom() - self.ui.spacing().item_spacing.y,
},
},
}
@ -77,15 +72,21 @@ impl<'l> Layout<'l> {
fn set_pos(&mut self, rect: Rect) {
match self.direction {
LineDirection::Horizontal => {
self.pos.y = rect.bottom() + self.padding.inner;
self.pos.y = rect.bottom() + self.ui.spacing().item_spacing.y;
}
LineDirection::Vertical => {
self.pos.x = rect.right() + self.padding.inner;
self.pos.x = rect.right() + self.ui.spacing().item_spacing.x;
}
}
self.max.x = self.max.x.max(rect.right() + self.padding.inner);
self.max.y = self.max.y.max(rect.bottom() + self.padding.inner);
self.max.x = self
.max
.x
.max(rect.right() + self.ui.spacing().item_spacing.x);
self.max.y = self
.max
.y
.max(rect.bottom() + self.ui.spacing().item_spacing.y);
}
pub(crate) fn empty(&mut self, width: CellSize, height: CellSize) {
@ -114,8 +115,9 @@ impl<'l> Layout<'l> {
add_contents: impl FnOnce(&mut Ui),
) -> Response {
let mut rect = self.cell_rect(&width, &height);
*rect.top_mut() -= self.padding.inner;
*rect.left_mut() -= self.padding.inner;
// Make sure we don't have a gap in the stripe background
*rect.top_mut() -= self.ui.spacing().item_spacing.y;
*rect.left_mut() -= self.ui.spacing().item_spacing.x;
let text_color: Rgba = self.ui.visuals().text_color().into();
self.ui
@ -154,12 +156,8 @@ impl<'l> Layout<'l> {
if clip {
let mut clip_rect = child_ui.clip_rect();
clip_rect.min = clip_rect
.min
.max(rect.min - Vec2::new(self.padding.inner, self.padding.inner));
clip_rect.max = clip_rect
.max
.min(rect.max + Vec2::new(self.padding.inner, self.padding.inner));
clip_rect.min = clip_rect.min.max(rect.min);
clip_rect.max = clip_rect.max.min(rect.max);
child_ui.set_clip_rect(clip_rect);
}

View file

@ -85,7 +85,6 @@ mod datepicker;
mod grid;
mod layout;
mod padding;
mod sizing;
mod table;
@ -94,6 +93,5 @@ pub use datepicker::DatePickerButton;
pub use grid::*;
pub(crate) use layout::Layout;
pub use padding::Padding;
pub use sizing::Size;
pub use table::*;

View file

@ -1,29 +0,0 @@
/// Configure padding of grid or table
/// TODO: Use padding settings of egui/should we extend egui padding settings for table?
#[derive(Clone, Debug)]
pub struct Padding {
pub(crate) inner: f32,
pub(crate) outer: f32,
}
impl Padding {
pub fn new(inner: f32, outer: f32) -> Self {
Self { inner, outer }
}
pub fn inner(mut self, inner: f32) -> Self {
self.inner = inner;
self
}
pub fn outer(mut self, outer: f32) -> Self {
self.outer = outer;
self
}
}
impl Default for Padding {
fn default() -> Self {
Self::new(5.0, 10.0)
}
}

View file

@ -32,7 +32,7 @@ impl Sizing {
self.sizes.push(size);
}
pub fn into_lengths(self, length: f32, inner_padding: f32) -> Vec<f32> {
pub fn into_lengths(self, length: f32, spacing: f32) -> Vec<f32> {
let mut remainders = 0;
let sum_non_remainder = self
.sizes
@ -55,7 +55,7 @@ impl Sizing {
}
})
.sum::<f32>()
+ inner_padding * (self.sizes.len() + 1) as f32;
+ spacing * (self.sizes.len() - 1) as f32;
let avg_remainder_length = if remainders == 0 {
0.0

View file

@ -5,7 +5,7 @@
use crate::{
layout::{CellSize, LineDirection},
sizing::Sizing,
Layout, Padding, Size,
Layout, Size,
};
use egui::{Response, Ui};
@ -13,19 +13,17 @@ use std::cmp;
pub struct TableBuilder<'a> {
ui: &'a mut Ui,
padding: Padding,
sizing: Sizing,
scroll: bool,
striped: bool,
}
impl<'a> TableBuilder<'a> {
pub fn new(ui: &'a mut Ui, padding: Padding) -> Self {
pub fn new(ui: &'a mut Ui) -> Self {
let sizing = Sizing::new();
Self {
ui,
padding,
sizing,
scroll: true,
striped: false,
@ -61,12 +59,18 @@ 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(
self.ui.available_rect_before_wrap().width() - 2.0 * self.padding.outer,
self.padding.inner,
self.ui.available_rect_before_wrap().width()
- self.ui.spacing().item_spacing.x
- if self.scroll {
self.ui.spacing().scroll_bar_width
} else {
0.0
},
self.ui.spacing().item_spacing.x,
);
let ui = self.ui;
{
let mut layout = Layout::new(ui, self.padding.clone(), LineDirection::Vertical);
let mut layout = Layout::new(ui, LineDirection::Vertical);
{
let row = TableRow {
layout: &mut layout,
@ -81,7 +85,6 @@ impl<'a> TableBuilder<'a> {
Table {
ui,
padding: self.padding,
widths,
scroll: self.scroll,
striped: self.striped,
@ -94,13 +97,12 @@ impl<'a> TableBuilder<'a> {
F: for<'b> FnOnce(TableBody<'b>),
{
let widths = self.sizing.into_lengths(
self.ui.available_rect_before_wrap().width() - 2.0 * self.padding.outer,
self.padding.inner,
self.ui.available_rect_before_wrap().width(),
self.ui.spacing().item_spacing.x,
);
Table {
ui: self.ui,
padding: self.padding,
widths,
scroll: self.scroll,
striped: self.striped,
@ -111,7 +113,6 @@ impl<'a> TableBuilder<'a> {
pub struct Table<'a> {
ui: &'a mut Ui,
padding: Padding,
widths: Vec<f32>,
scroll: bool,
striped: bool,
@ -123,7 +124,6 @@ impl<'a> Table<'a> {
where
F: for<'b> FnOnce(TableBody<'b>),
{
let padding = self.padding;
let ui = self.ui;
let widths = self.widths;
let striped = self.striped;
@ -131,7 +131,7 @@ impl<'a> Table<'a> {
let end_y = ui.available_rect_before_wrap().bottom();
egui::ScrollArea::new([false, self.scroll]).show(ui, move |ui| {
let layout = Layout::new(ui, padding, LineDirection::Vertical);
let layout = Layout::new(ui, LineDirection::Vertical);
body(TableBody {
layout,