Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Grid::with_row_color #2519

Merged
merged 6 commits into from
Mar 30, 2023
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 49 additions & 22 deletions crates/egui/src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ impl State {

// ----------------------------------------------------------------------------

// type alias for boxed function to determine row color during grid generation
type ColorPickerFn = Box<dyn Fn(usize, &Style) -> Option<Rgba>>;
imgurbot12 marked this conversation as resolved.
Show resolved Hide resolved

pub(crate) struct GridLayout {
ctx: Context,
style: std::sync::Arc<Style>,
Expand All @@ -66,7 +69,7 @@ pub(crate) struct GridLayout {
spacing: Vec2,
min_cell_size: Vec2,
max_cell_size: Vec2,
striped: bool,
color_picker: Option<ColorPickerFn>,

// Cursor:
col: usize,
Expand Down Expand Up @@ -101,7 +104,7 @@ impl GridLayout {
spacing: ui.spacing().item_spacing,
min_cell_size: ui.spacing().interact_size,
max_cell_size: Vec2::INFINITY,
striped: false,
color_picker: None,

col: 0,
row: 0,
Expand Down Expand Up @@ -214,6 +217,20 @@ impl GridLayout {
self.col += 1;
}

pub(crate) fn paint_row(&mut self, cursor: &mut Rect, painter: &Painter) {
emilk marked this conversation as resolved.
Show resolved Hide resolved
// handle row color painting based on color-picker function
let Some(color_picker) = self.color_picker.as_ref() else { return };
let Some(row_color) = color_picker(self.row, &self.style) else { return };
let Some(height) = self.prev_state.row_height(self.row) else {return };
// Paint background for coming row:
let size = Vec2::new(self.prev_state.full_width(self.spacing.x), height);
let rect = Rect::from_min_size(cursor.min, size);
let rect = rect.expand2(0.5 * self.spacing.y * Vec2::Y);
let rect = rect.expand2(2.0 * Vec2::X); // HACK: just looks better with some spacing on the sides

painter.rect_filled(rect, 2.0, row_color);
}

pub(crate) fn end_row(&mut self, cursor: &mut Rect, painter: &Painter) {
cursor.min.x = self.initial_available.min.x;
cursor.min.y += self.spacing.y;
Expand All @@ -225,17 +242,7 @@ impl GridLayout {
self.col = 0;
self.row += 1;

if self.striped && self.row % 2 == 1 {
if let Some(height) = self.prev_state.row_height(self.row) {
// Paint background for coming row:
let size = Vec2::new(self.prev_state.full_width(self.spacing.x), height);
let rect = Rect::from_min_size(cursor.min, size);
let rect = rect.expand2(0.5 * self.spacing.y * Vec2::Y);
let rect = rect.expand2(2.0 * Vec2::X); // HACK: just looks better with some spacing on the sides

painter.rect_filled(rect, 2.0, self.style.visuals.faint_bg_color);
}
}
self.paint_row(cursor, painter);
}

pub(crate) fn save(&self) {
Expand Down Expand Up @@ -278,12 +285,12 @@ impl GridLayout {
pub struct Grid {
id_source: Id,
num_columns: Option<usize>,
striped: Option<bool>,
min_col_width: Option<f32>,
min_row_height: Option<f32>,
max_cell_size: Vec2,
spacing: Option<Vec2>,
start_row: usize,
color_picker: Option<ColorPickerFn>,
}

impl Grid {
Expand All @@ -292,15 +299,24 @@ impl Grid {
Self {
id_source: Id::new(id_source),
num_columns: None,
striped: None,
min_col_width: None,
min_row_height: None,
max_cell_size: Vec2::INFINITY,
spacing: None,
start_row: 0,
color_picker: None,
}
}

/// Setting this will allow for dynamic coloring of rows of the grid object
pub fn with_row_color<F>(mut self, color_picker: F) -> Self
where
F: Fn(usize, &Style) -> Option<Rgba> + 'static,
{
self.color_picker = Some(Box::new(color_picker));
self
}

/// Setting this will allow the last column to expand to take up the rest of the space of the parent [`Ui`].
pub fn num_columns(mut self, num_columns: usize) -> Self {
self.num_columns = Some(num_columns);
Expand All @@ -311,9 +327,13 @@ impl Grid {
///
/// This can make a table easier to read.
/// Default is whatever is in [`crate::Visuals::striped`].
pub fn striped(mut self, striped: bool) -> Self {
self.striped = Some(striped);
self
pub fn striped(self, striped: bool) -> Self {
self.with_row_color(move |row, style| {
if striped && row % 2 == 1 {
return Some(Rgba::from(style.visuals.faint_bg_color));
}
None
})
imgurbot12 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Set minimum width of each column.
Expand Down Expand Up @@ -364,14 +384,13 @@ impl Grid {
let Self {
id_source,
num_columns,
striped,
min_col_width,
min_row_height,
max_cell_size,
spacing,
start_row,
color_picker,
} = self;
let striped = striped.unwrap_or(ui.visuals().striped);
let min_col_width = min_col_width.unwrap_or_else(|| ui.spacing().interact_size.x);
let min_row_height = min_row_height.unwrap_or_else(|| ui.spacing().interact_size.y);
let spacing = spacing.unwrap_or_else(|| ui.spacing().item_spacing);
Expand All @@ -387,16 +406,24 @@ impl Grid {
ui.allocate_ui_at_rect(max_rect, |ui| {
ui.set_visible(prev_state.is_some()); // Avoid visible first-frame jitter
ui.horizontal(|ui| {
let grid = GridLayout {
let is_color = color_picker.is_some();
let mut grid = GridLayout {
num_columns,
striped,
color_picker,
min_cell_size: vec2(min_col_width, min_row_height),
max_cell_size,
spacing,
row: start_row,
..GridLayout::new(ui, id, prev_state)
};

// paint first incoming row
if is_color {
let mut cursor = ui.cursor();
let painter = ui.painter();
grid.paint_row(&mut cursor, &painter);
emilk marked this conversation as resolved.
Show resolved Hide resolved
}

ui.set_grid(grid);
let r = add_contents(ui);
ui.save_grid();
Expand Down