More table improvements (#1440)

* Clip by default
* Fix some spacing bugs
* datepicker: look nicer in light mode
* datepicker: show month names
* Table: don't allow resize of last column if it is Size::Remainder
This commit is contained in:
Emil Ernerfeldt 2022-04-01 15:27:42 +02:00 committed by GitHub
parent c029f25c13
commit 5dff1e42c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 173 additions and 128 deletions

View file

@ -31,14 +31,14 @@ impl super::View for StripDemo {
.size(Size::relative(0.5).at_least(60.0)) .size(Size::relative(0.5).at_least(60.0))
.size(Size::exact(10.0)) .size(Size::exact(10.0))
.vertical(|mut strip| { .vertical(|mut strip| {
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.painter() ui.painter()
.rect_filled(ui.available_rect_before_wrap(), 0.0, Color32::BLUE); .rect_filled(ui.available_rect_before_wrap(), 0.0, Color32::BLUE);
ui.label("Full width and 50px height"); ui.label("Full width and 50px height");
}); });
strip.strip(|builder| { strip.strip(|builder| {
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| { builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.painter().rect_filled( ui.painter().rect_filled(
ui.available_rect_before_wrap(), ui.available_rect_before_wrap(),
0.0, 0.0,
@ -49,7 +49,7 @@ impl super::View for StripDemo {
strip.strip(|builder| { strip.strip(|builder| {
builder.sizes(Size::remainder(), 3).vertical(|mut strip| { builder.sizes(Size::remainder(), 3).vertical(|mut strip| {
strip.empty(); strip.empty();
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.painter().rect_filled( ui.painter().rect_filled(
ui.available_rect_before_wrap(), ui.available_rect_before_wrap(),
0.0, 0.0,
@ -76,7 +76,7 @@ impl super::View for StripDemo {
.size(Size::remainder()) .size(Size::remainder())
.vertical(|mut strip| { .vertical(|mut strip| {
strip.empty(); strip.empty();
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.painter().rect_filled( ui.painter().rect_filled(
ui.available_rect_before_wrap(), ui.available_rect_before_wrap(),
0.0, 0.0,
@ -87,7 +87,7 @@ impl super::View for StripDemo {
}); });
}); });
strip.empty(); strip.empty();
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.painter().rect_filled( ui.painter().rect_filled(
ui.available_rect_before_wrap(), ui.available_rect_before_wrap(),
0.0, 0.0,
@ -97,7 +97,7 @@ impl super::View for StripDemo {
}); });
}); });
}); });
strip.cell_clip(|ui| { strip.cell(|ui| {
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.add(crate::__egui_github_link_file!()); ui.add(crate::__egui_github_link_file!());
}); });

View file

@ -1,3 +1,4 @@
use egui::TextStyle;
use egui_extras::{Size, StripBuilder, TableBuilder}; use egui_extras::{Size, StripBuilder, TableBuilder};
/// Shows off a table with dynamic layout /// Shows off a table with dynamic layout
@ -35,7 +36,7 @@ impl super::View for TableDemo {
.size(Size::remainder()) // for the table .size(Size::remainder()) // for the table
.size(Size::exact(10.0)) // for the source code link .size(Size::exact(10.0)) // for the source code link
.vertical(|mut strip| { .vertical(|mut strip| {
strip.cell_clip(|ui| { strip.cell(|ui| {
self.table_ui(ui); self.table_ui(ui);
}); });
strip.cell(|ui| { strip.cell(|ui| {
@ -49,48 +50,63 @@ impl super::View for TableDemo {
impl TableDemo { impl TableDemo {
fn table_ui(&mut self, ui: &mut egui::Ui) { fn table_ui(&mut self, ui: &mut egui::Ui) {
let text_height = TextStyle::Body.resolve(ui.style()).size;
TableBuilder::new(ui) TableBuilder::new(ui)
.striped(true) .striped(true)
.column(Size::initial(60.0).at_least(40.0)) .column(Size::initial(60.0).at_least(40.0))
.column(Size::remainder().at_least(60.0))
.column(Size::initial(60.0).at_least(40.0)) .column(Size::initial(60.0).at_least(40.0))
.column(Size::remainder().at_least(60.0))
.resizable(self.resizable) .resizable(self.resizable)
.header(20.0, |mut header| { .header(20.0, |mut header| {
header.col_clip(|ui| { header.col(|ui| {
ui.heading("Left"); ui.centered_and_justified(|ui| {
ui.heading("Row");
}); });
header.col_clip(|ui| {
ui.heading("Middle");
}); });
header.col_clip(|ui| { header.col(|ui| {
ui.heading("Right"); ui.centered_and_justified(|ui| {
ui.heading("Clock");
});
});
header.col(|ui| {
ui.centered_and_justified(|ui| {
ui.heading("Content");
});
}); });
}) })
.body(|mut body| { .body(|mut body| {
if self.virtual_scroll { if self.virtual_scroll {
body.rows(20.0, 100_000, |index, mut row| { body.rows(text_height, 100_000, |row_index, mut row| {
row.col_clip(|ui| { row.col(|ui| {
ui.label(index.to_string()); ui.label(row_index.to_string());
}); });
row.col_clip(|ui| { row.col(|ui| {
ui.label(clock_emoji(row_index));
});
row.col(|ui| {
ui.add( ui.add(
egui::Label::new("virtual scroll, easily with thousands of rows!") egui::Label::new("Thousands of rows of even height").wrap(false),
.wrap(false),
); );
}); });
row.col_clip(|ui| {
ui.label(index.to_string());
});
}); });
} else { } else {
for i in 0..20 { for row_index in 0..20 {
let thick = i % 4 == 0; let thick = row_index % 6 == 0;
let height = if thick { 25.0 } else { 15.0 }; let row_height = if thick { 30.0 } else { 18.0 };
body.row(height, |mut row| { body.row(row_height, |mut row| {
row.col_clip(|ui| { row.col(|ui| {
ui.label(i.to_string()); ui.centered_and_justified(|ui| {
ui.label(row_index.to_string());
}); });
row.col_clip(|ui| { });
row.col(|ui| {
ui.centered_and_justified(|ui| {
ui.label(clock_emoji(row_index));
});
});
row.col(|ui| {
ui.centered_and_justified(|ui| {
ui.style_mut().wrap = Some(false); ui.style_mut().wrap = Some(false);
if thick { if thick {
ui.heading("Extra thick row"); ui.heading("Extra thick row");
@ -98,8 +114,6 @@ impl TableDemo {
ui.label("Normal row"); ui.label("Normal row");
} }
}); });
row.col_clip(|ui| {
ui.label(i.to_string());
}); });
}); });
} }
@ -107,3 +121,9 @@ impl TableDemo {
}); });
} }
} }
fn clock_emoji(row_index: usize) -> String {
char::from_u32(0x1f550 + row_index as u32 % 24)
.unwrap()
.to_string()
}

View file

@ -1,7 +1,7 @@
use super::{button::DatePickerButtonState, month_data}; use super::{button::DatePickerButtonState, month_data};
use crate::{Size, StripBuilder, TableBuilder}; use crate::{Size, StripBuilder, TableBuilder};
use chrono::{Date, Datelike, NaiveDate, Utc, Weekday}; use chrono::{Date, Datelike, NaiveDate, Utc, Weekday};
use egui::{Align, Button, Color32, ComboBox, Direction, Id, Label, Layout, RichText, Ui, Vec2}; use egui::{Align, Button, Color32, ComboBox, Direction, Id, Layout, RichText, Ui, Vec2};
#[derive(Default, Clone)] #[derive(Default, Clone)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
@ -55,6 +55,7 @@ impl<'a> DatePickerPopup<'a> {
let spacing = 2.0; let spacing = 2.0;
ui.spacing_mut().item_spacing = Vec2::splat(spacing); ui.spacing_mut().item_spacing = Vec2::splat(spacing);
StripBuilder::new(ui) StripBuilder::new(ui)
.clip(false)
.sizes( .sizes(
Size::exact(height), Size::exact(height),
match (self.combo_boxes, self.arrows) { match (self.combo_boxes, self.arrows) {
@ -70,7 +71,7 @@ impl<'a> DatePickerPopup<'a> {
.size(Size::exact(height)) .size(Size::exact(height))
.vertical(|mut strip| { .vertical(|mut strip| {
if self.combo_boxes { if self.combo_boxes {
strip.strip_clip(|builder| { strip.strip(|builder| {
builder.sizes(Size::remainder(), 3).horizontal(|mut strip| { builder.sizes(Size::remainder(), 3).horizontal(|mut strip| {
strip.cell(|ui| { strip.cell(|ui| {
ComboBox::from_id_source("date_picker_year") ComboBox::from_id_source("date_picker_year")
@ -94,14 +95,14 @@ impl<'a> DatePickerPopup<'a> {
}); });
strip.cell(|ui| { strip.cell(|ui| {
ComboBox::from_id_source("date_picker_month") ComboBox::from_id_source("date_picker_month")
.selected_text(popup_state.month.to_string()) .selected_text(month_name(popup_state.month))
.show_ui(ui, |ui| { .show_ui(ui, |ui| {
for month in 1..=12 { for month in 1..=12 {
if ui if ui
.selectable_value( .selectable_value(
&mut popup_state.month, &mut popup_state.month,
month, month,
month.to_string(), month_name(month),
) )
.changed() .changed()
{ {
@ -236,6 +237,7 @@ impl<'a> DatePickerPopup<'a> {
ui.spacing_mut().item_spacing = Vec2::new(1.0, 2.0); ui.spacing_mut().item_spacing = Vec2::new(1.0, 2.0);
TableBuilder::new(ui) TableBuilder::new(ui)
.scroll(false) .scroll(false)
.clip(false)
.columns(Size::remainder(), if self.calendar_week { 8 } else { 7 }) .columns(Size::remainder(), if self.calendar_week { 8 } else { 7 })
.header(height, |mut header| { .header(height, |mut header| {
if self.calendar_week { if self.calendar_week {
@ -243,7 +245,7 @@ impl<'a> DatePickerPopup<'a> {
ui.with_layout( ui.with_layout(
Layout::centered_and_justified(Direction::TopDown), Layout::centered_and_justified(Direction::TopDown),
|ui| { |ui| {
ui.add(Label::new("Week")); ui.label("Week");
}, },
); );
}); });
@ -255,7 +257,7 @@ impl<'a> DatePickerPopup<'a> {
ui.with_layout( ui.with_layout(
Layout::centered_and_justified(Direction::TopDown), Layout::centered_and_justified(Direction::TopDown),
|ui| { |ui| {
ui.add(Label::new(name)); ui.label(name);
}, },
); );
}); });
@ -266,7 +268,7 @@ impl<'a> DatePickerPopup<'a> {
body.row(height, |mut row| { body.row(height, |mut row| {
if self.calendar_week { if self.calendar_week {
row.col(|ui| { row.col(|ui| {
ui.add(Label::new(week.number.to_string())); ui.label(week.number.to_string());
}); });
} }
for day in week.days { for day in week.days {
@ -274,7 +276,6 @@ impl<'a> DatePickerPopup<'a> {
ui.with_layout( ui.with_layout(
Layout::top_down_justified(Align::Center), Layout::top_down_justified(Align::Center),
|ui| { |ui| {
//TODO: Colors from egui style
let fill_color = if popup_state.year let fill_color = if popup_state.year
== day.year() == day.year()
&& popup_state.month == day.month() && popup_state.month == day.month()
@ -284,25 +285,51 @@ impl<'a> DatePickerPopup<'a> {
} else if day.weekday() == Weekday::Sat } else if day.weekday() == Weekday::Sat
|| day.weekday() == Weekday::Sun || day.weekday() == Weekday::Sun
{ {
if ui.visuals().dark_mode {
Color32::DARK_RED Color32::DARK_RED
} else { } else {
Color32::BLACK Color32::LIGHT_RED
}; }
let text_color = if day == today {
Color32::RED
} else if day.month() == popup_state.month {
Color32::WHITE
} else { } else {
Color32::from_gray(80) ui.visuals().extreme_bg_color
}; };
let button = Button::new( let mut text_color = ui
RichText::new(day.day().to_string()) .visuals()
.widgets
.inactive
.text_color();
if day.month() != popup_state.month {
text_color =
text_color.linear_multiply(0.5);
};
let button_response = ui.add(
Button::new(
RichText::new(
day.day().to_string(),
)
.color(text_color), .color(text_color),
) )
.fill(fill_color); .fill(fill_color),
);
if ui.add(button).clicked() { if day == today {
// Encircle today's date
let stroke = ui
.visuals()
.widgets
.inactive
.fg_stroke;
ui.painter().circle_stroke(
button_response.rect.center(),
8.0,
stroke,
);
}
if button_response.clicked() {
popup_state.year = day.year(); popup_state.year = day.year();
popup_state.month = day.month(); popup_state.month = day.month();
popup_state.day = day.day(); popup_state.day = day.day();
@ -361,3 +388,21 @@ impl<'a> DatePickerPopup<'a> {
} }
} }
} }
fn month_name(i: u32) -> &'static str {
match i {
1 => "January",
2 => "February",
3 => "March",
4 => "April",
5 => "May",
6 => "June",
7 => "July",
8 => "August",
9 => "September",
10 => "October",
11 => "November",
12 => "December",
_ => panic!("Unknown month: {}", i),
}
}

View file

@ -31,10 +31,11 @@ pub struct StripLayout<'l> {
rect: Rect, rect: Rect,
cursor: Pos2, cursor: Pos2,
max: Pos2, max: Pos2,
pub(crate) clip: bool,
} }
impl<'l> StripLayout<'l> { impl<'l> StripLayout<'l> {
pub(crate) fn new(ui: &'l mut Ui, direction: CellDirection) -> Self { pub(crate) fn new(ui: &'l mut Ui, direction: CellDirection, clip: bool) -> Self {
let rect = ui.available_rect_before_wrap(); let rect = ui.available_rect_before_wrap();
let pos = rect.left_top(); let pos = rect.left_top();
@ -44,6 +45,7 @@ impl<'l> StripLayout<'l> {
cursor: pos, cursor: pos,
max: pos, max: pos,
direction, direction,
clip,
} }
} }
@ -89,11 +91,10 @@ impl<'l> StripLayout<'l> {
&mut self, &mut self,
width: CellSize, width: CellSize,
height: CellSize, height: CellSize,
clip: bool,
add_contents: impl FnOnce(&mut Ui), add_contents: impl FnOnce(&mut Ui),
) -> Response { ) -> Response {
let rect = self.cell_rect(&width, &height); let rect = self.cell_rect(&width, &height);
let used_rect = self.cell(rect, clip, add_contents); let used_rect = self.cell(rect, add_contents);
self.set_pos(rect); self.set_pos(rect);
self.ui.allocate_rect(rect.union(used_rect), Sense::hover()) self.ui.allocate_rect(rect.union(used_rect), Sense::hover())
} }
@ -102,7 +103,6 @@ impl<'l> StripLayout<'l> {
&mut self, &mut self,
width: CellSize, width: CellSize,
height: CellSize, height: CellSize,
clip: bool,
add_contents: impl FnOnce(&mut Ui), add_contents: impl FnOnce(&mut Ui),
) -> Response { ) -> Response {
let rect = self.cell_rect(&width, &height); let rect = self.cell_rect(&width, &height);
@ -114,7 +114,7 @@ impl<'l> StripLayout<'l> {
.painter() .painter()
.rect_filled(rect, 0.0, self.ui.visuals().faint_bg_color); .rect_filled(rect, 0.0, self.ui.visuals().faint_bg_color);
self.add(width, height, clip, add_contents) self.add(width, height, add_contents)
} }
/// only needed for layouts with multiple lines, like [`Table`]. /// only needed for layouts with multiple lines, like [`Table`].
@ -131,10 +131,10 @@ impl<'l> StripLayout<'l> {
} }
} }
fn cell(&mut self, rect: Rect, clip: bool, add_contents: impl FnOnce(&mut Ui)) -> Rect { fn cell(&mut self, rect: Rect, add_contents: impl FnOnce(&mut Ui)) -> Rect {
let mut child_ui = self.ui.child_ui(rect, *self.ui.layout()); let mut child_ui = self.ui.child_ui(rect, *self.ui.layout());
if clip { if self.clip {
let mut clip_rect = child_ui.clip_rect(); let mut clip_rect = child_ui.clip_rect();
clip_rect.min = clip_rect.min.max(rect.min); clip_rect.min = clip_rect.min.max(rect.min);
clip_rect.max = clip_rect.max.min(rect.max); clip_rect.max = clip_rect.max.min(rect.max);

View file

@ -40,6 +40,7 @@ use egui::{Response, Ui};
pub struct StripBuilder<'a> { pub struct StripBuilder<'a> {
ui: &'a mut Ui, ui: &'a mut Ui,
sizing: Sizing, sizing: Sizing,
clip: bool,
} }
impl<'a> StripBuilder<'a> { impl<'a> StripBuilder<'a> {
@ -47,7 +48,17 @@ impl<'a> StripBuilder<'a> {
pub fn new(ui: &'a mut Ui) -> Self { pub fn new(ui: &'a mut Ui) -> Self {
let sizing = Sizing::new(); let sizing = Sizing::new();
Self { ui, sizing } Self {
ui,
sizing,
clip: true,
}
}
/// Should we clip the contents of each cell? Default: `true`.
pub fn clip(mut self, clip: bool) -> Self {
self.clip = clip;
self
} }
/// Add size hint for one column/row. /// Add size hint for one column/row.
@ -76,7 +87,7 @@ impl<'a> StripBuilder<'a> {
self.ui.available_rect_before_wrap().width() - self.ui.spacing().item_spacing.x, self.ui.available_rect_before_wrap().width() - self.ui.spacing().item_spacing.x,
self.ui.spacing().item_spacing.x, self.ui.spacing().item_spacing.x,
); );
let mut layout = StripLayout::new(self.ui, CellDirection::Horizontal); let mut layout = StripLayout::new(self.ui, CellDirection::Horizontal, self.clip);
strip(Strip { strip(Strip {
layout: &mut layout, layout: &mut layout,
direction: CellDirection::Horizontal, direction: CellDirection::Horizontal,
@ -97,7 +108,7 @@ impl<'a> StripBuilder<'a> {
self.ui.available_rect_before_wrap().height() - self.ui.spacing().item_spacing.y, self.ui.available_rect_before_wrap().height() - self.ui.spacing().item_spacing.y,
self.ui.spacing().item_spacing.y, self.ui.spacing().item_spacing.y,
); );
let mut layout = StripLayout::new(self.ui, CellDirection::Vertical); let mut layout = StripLayout::new(self.ui, CellDirection::Vertical, self.clip);
strip(Strip { strip(Strip {
layout: &mut layout, layout: &mut layout,
direction: CellDirection::Vertical, direction: CellDirection::Vertical,
@ -136,35 +147,18 @@ impl<'a, 'b> Strip<'a, 'b> {
self.layout.empty(width, height); self.layout.empty(width, height);
} }
fn cell_impl(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) { /// Add cell contents.
let (width, height) = self.next_cell_size();
self.layout.add(width, height, clip, add_contents);
}
/// Add cell, content is wrapped
pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) { pub fn cell(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self.cell_impl(false, add_contents); let (width, height) = self.next_cell_size();
} self.layout.add(width, height, add_contents);
/// Add cell, content is clipped
pub fn cell_clip(&mut self, add_contents: impl FnOnce(&mut Ui)) {
self.cell_impl(true, add_contents);
}
fn strip_impl(&mut self, clip: bool, strip_builder: impl FnOnce(StripBuilder<'_>)) {
self.cell_impl(clip, |ui| {
strip_builder(StripBuilder::new(ui));
});
} }
/// Add strip as cell /// Add strip as cell
pub fn strip(&mut self, strip_builder: impl FnOnce(StripBuilder<'_>)) { pub fn strip(&mut self, strip_builder: impl FnOnce(StripBuilder<'_>)) {
self.strip_impl(false, strip_builder); let clip = self.layout.clip;
} self.cell(|ui| {
strip_builder(StripBuilder::new(ui).clip(clip));
/// Add strip as cell, content is clipped });
pub fn strip_clip(&mut self, strip_builder: impl FnOnce(StripBuilder<'_>)) {
self.strip_impl(true, strip_builder);
} }
} }

View file

@ -40,7 +40,7 @@ use egui::{Response, Ui};
/// row.col(|ui| { /// row.col(|ui| {
/// ui.label("first row growing cell"); /// ui.label("first row growing cell");
/// }); /// });
/// row.col_clip(|ui| { /// row.col(|ui| {
/// ui.button("action"); /// ui.button("action");
/// }); /// });
/// }); /// });
@ -53,6 +53,7 @@ pub struct TableBuilder<'a> {
scroll: bool, scroll: bool,
striped: bool, striped: bool,
resizable: bool, resizable: bool,
clip: bool,
} }
impl<'a> TableBuilder<'a> { impl<'a> TableBuilder<'a> {
@ -65,6 +66,7 @@ impl<'a> TableBuilder<'a> {
scroll: true, scroll: true,
striped: false, striped: false,
resizable: false, resizable: false,
clip: true,
} }
} }
@ -94,6 +96,12 @@ impl<'a> TableBuilder<'a> {
self self
} }
/// Should we clip the contents of each cell? Default: `true`.
pub fn clip(mut self, clip: bool) -> Self {
self.clip = clip;
self
}
/// Add size hint for column /// Add size hint for column
pub fn column(mut self, width: Size) -> Self { pub fn column(mut self, width: Size) -> Self {
self.sizing.add(width); self.sizing.add(width);
@ -127,6 +135,7 @@ impl<'a> TableBuilder<'a> {
scroll, scroll,
striped, striped,
resizable, resizable,
clip,
} = self; } = self;
let resize_id = resizable.then(|| ui.id().with("__table_resize")); let resize_id = resizable.then(|| ui.id().with("__table_resize"));
@ -141,13 +150,12 @@ impl<'a> TableBuilder<'a> {
let table_top = ui.cursor().top(); let table_top = ui.cursor().top();
{ {
let mut layout = StripLayout::new(ui, CellDirection::Horizontal); let mut layout = StripLayout::new(ui, CellDirection::Horizontal, clip);
header(TableRow { header(TableRow {
layout: &mut layout, layout: &mut layout,
widths: &widths, widths: &widths,
striped: false, striped: false,
height, height,
clicked: false,
}); });
layout.allocate_rect(); layout.allocate_rect();
} }
@ -161,6 +169,7 @@ impl<'a> TableBuilder<'a> {
widths, widths,
scroll, scroll,
striped, striped,
clip,
} }
} }
@ -177,6 +186,7 @@ impl<'a> TableBuilder<'a> {
scroll, scroll,
striped, striped,
resizable, resizable,
clip,
} = self; } = self;
let resize_id = resizable.then(|| ui.id().with("__table_resize")); let resize_id = resizable.then(|| ui.id().with("__table_resize"));
@ -199,6 +209,7 @@ impl<'a> TableBuilder<'a> {
widths, widths,
scroll, scroll,
striped, striped,
clip,
} }
.body(body); .body(body);
} }
@ -216,6 +227,7 @@ pub struct Table<'a> {
widths: Vec<f32>, widths: Vec<f32>,
scroll: bool, scroll: bool,
striped: bool, striped: bool,
clip: bool,
} }
impl<'a> Table<'a> { impl<'a> Table<'a> {
@ -233,6 +245,7 @@ impl<'a> Table<'a> {
widths, widths,
scroll, scroll,
striped, striped,
clip,
} = self; } = self;
let avail_rect = ui.available_rect_before_wrap(); let avail_rect = ui.available_rect_before_wrap();
@ -242,7 +255,7 @@ impl<'a> Table<'a> {
egui::ScrollArea::new([false, scroll]) egui::ScrollArea::new([false, scroll])
.auto_shrink([true; 2]) .auto_shrink([true; 2])
.show(ui, move |ui| { .show(ui, move |ui| {
let layout = StripLayout::new(ui, CellDirection::Horizontal); let layout = StripLayout::new(ui, CellDirection::Horizontal, clip);
body(TableBody { body(TableBody {
layout, layout,
@ -355,7 +368,6 @@ impl<'a> TableBody<'a> {
widths: &self.widths, widths: &self.widths,
striped: false, striped: false,
height: skip_height, height: skip_height,
clicked: false,
} }
.col(|_| ()); // advances the cursor .col(|_| ()); // advances the cursor
} }
@ -372,7 +384,6 @@ impl<'a> TableBody<'a> {
widths: &self.widths, widths: &self.widths,
striped: self.striped && idx % 2 == 0, striped: self.striped && idx % 2 == 0,
height, height,
clicked: false,
}, },
); );
} }
@ -385,7 +396,6 @@ impl<'a> TableBody<'a> {
widths: &self.widths, widths: &self.widths,
striped: false, striped: false,
height: skip_height, height: skip_height,
clicked: false,
} }
.col(|_| ()); // advances the cursor .col(|_| ()); // advances the cursor
} }
@ -398,7 +408,6 @@ impl<'a> TableBody<'a> {
widths: &self.widths, widths: &self.widths,
striped: self.striped && self.row_nr % 2 == 0, striped: self.striped && self.row_nr % 2 == 0,
height, height,
clicked: false,
}); });
self.row_nr += 1; self.row_nr += 1;
@ -418,26 +427,11 @@ pub struct TableRow<'a, 'b> {
widths: &'b [f32], widths: &'b [f32],
striped: bool, striped: bool,
height: f32, height: f32,
clicked: bool,
} }
impl<'a, 'b> TableRow<'a, 'b> { impl<'a, 'b> TableRow<'a, 'b> {
/// Check if row was clicked /// Add the contents of a column.
pub fn clicked(&self) -> bool {
self.clicked
}
/// Add column, content is wrapped
pub fn col(&mut self, add_contents: impl FnOnce(&mut Ui)) -> Response { pub fn col(&mut self, add_contents: impl FnOnce(&mut Ui)) -> Response {
self.column(false, add_contents)
}
/// Add column, content is clipped
pub fn col_clip(&mut self, add_contents: impl FnOnce(&mut Ui)) -> Response {
self.column(true, add_contents)
}
fn column(&mut self, clip: bool, add_contents: impl FnOnce(&mut Ui)) -> Response {
assert!( assert!(
!self.widths.is_empty(), !self.widths.is_empty(),
"Tried using more table columns than available." "Tried using more table columns than available."
@ -448,19 +442,11 @@ impl<'a, 'b> TableRow<'a, 'b> {
let width = CellSize::Absolute(width); let width = CellSize::Absolute(width);
let height = CellSize::Absolute(self.height); let height = CellSize::Absolute(self.height);
let response;
if self.striped { if self.striped {
response = self.layout.add_striped(width, height, clip, add_contents); self.layout.add_striped(width, height, add_contents)
} else { } else {
response = self.layout.add(width, height, clip, add_contents); self.layout.add(width, height, add_contents)
} }
if response.clicked() {
self.clicked = true;
}
response
} }
} }