[grid] Ensure the contents of each grid cell is aligned left+center

This commit is contained in:
Emil Ernerfeldt 2021-01-15 19:36:35 +01:00
parent db591bc56c
commit 03c9cda89b
5 changed files with 87 additions and 23 deletions

View file

@ -100,6 +100,15 @@ impl GridLayout {
Rect::from_min_size(cursor, size)
}
pub(crate) fn align_size_within_rect(&self, size: Vec2, frame: Rect) -> Rect {
// TODO: allow this alignment to be customized
Align2::LEFT_CENTER.align_size_within_rect(size, frame)
}
pub(crate) fn justify_or_align(&self, frame: Rect, size: Vec2) -> Rect {
self.align_size_within_rect(size, frame)
}
pub(crate) fn advance(&mut self, cursor: &mut Pos2, frame_rect: Rect, widget_rect: Rect) {
self.curr_state
.set_min_col_width(self.col, widget_rect.width());
@ -145,6 +154,10 @@ impl GridLayout {
/// A simple `Grid` layout.
///
/// The contents of each cell be aligned to the left and center.
/// If you want to add multiple widgets to a cell you need to group them with
/// [`Ui::horizontal`], [`Ui::vertical`] etc.
///
/// ```
/// # let ui = &mut egui::Ui::__test();
/// egui::Grid::new("some_unique_id").show(ui, |ui| {
@ -196,7 +209,11 @@ impl Grid {
min_row_height,
} = self;
ui.wrap(|ui| {
// Each grid cell is aligned LEFT_CENTER.
// If somebody wants to wrap more things inside a cell,
// then we should pick a default layout that matches that alignment,
// which we do here:
ui.horizontal(|ui| {
let id = ui.make_persistent_id(id_source);
let grid = GridLayout {
striped,

View file

@ -432,16 +432,27 @@ impl Layout {
/// Apply justify or alignment after calling `next_space`.
pub(crate) fn justify_or_align(&self, rect: Rect, mut child_size: Vec2) -> Rect {
if self.main_dir.is_horizontal() {
if self.cross_justify {
if self.cross_justify {
if self.main_dir.is_horizontal() {
child_size.y = rect.height(); // fill full height
}
Align2([Align::Center, self.cross_align]).align_size_within_rect(child_size, rect)
} else {
if self.cross_justify {
} else {
child_size.x = rect.width(); // fill full width
}
Align2([self.cross_align, Align::Center]).align_size_within_rect(child_size, rect)
}
match self.main_dir {
Direction::LeftToRight => {
Align2([Align::Min, self.cross_align]).align_size_within_rect(child_size, rect)
}
Direction::RightToLeft => {
Align2([Align::Max, self.cross_align]).align_size_within_rect(child_size, rect)
}
Direction::TopDown => {
Align2([self.cross_align, Align::Min]).align_size_within_rect(child_size, rect)
}
Direction::BottomUp => {
Align2([self.cross_align, Align::Max]).align_size_within_rect(child_size, rect)
}
}
}

View file

@ -58,7 +58,11 @@ impl Placer {
impl Placer {
pub(crate) fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
self.layout.align_size_within_rect(size, outer)
if let Some(grid) = &self.grid {
grid.align_size_within_rect(size, outer)
} else {
self.layout.align_size_within_rect(size, outer)
}
}
pub(crate) fn available_rect_before_wrap(&self) -> Rect {
@ -102,7 +106,11 @@ impl Placer {
/// Apply justify or alignment after calling `next_space`.
pub(crate) fn justify_or_align(&self, rect: Rect, child_size: Vec2) -> Rect {
self.layout.justify_or_align(rect, child_size)
if let Some(grid) = &self.grid {
grid.justify_or_align(rect, child_size)
} else {
self.layout.justify_or_align(rect, child_size)
}
}
/// Advance the cursor by this many points.
@ -115,7 +123,7 @@ impl Placer {
}
/// Advance cursor after a widget was added to a specific rectangle
/// and expand the region min_rect.
/// and expand the region `min_rect`.
///
/// * `frame_rect`: the frame inside which a widget was e.g. centered
/// * `widget_rect`: the actual rect used by the widget

View file

@ -4,11 +4,15 @@ use crate::*;
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
pub struct Separator {
spacing: f32,
is_horizontal_line: Option<bool>,
}
impl Separator {
pub fn new() -> Self {
Self { spacing: 6.0 }
Self {
spacing: 6.0,
is_horizontal_line: None,
}
}
/// How much space we take up. The line is painted in the middle of this.
@ -16,31 +20,53 @@ impl Separator {
self.spacing = spacing;
self
}
/// Explicitly ask for a horizontal line.
/// By default you will get a horizontal line in vertical layouts,
/// and a vertical line in horizontal layouts.
pub fn horizontal(mut self) -> Self {
self.is_horizontal_line = Some(true);
self
}
/// Explicitly ask for a vertical line.
/// By default you will get a horizontal line in vertical layouts,
/// and a vertical line in horizontal layouts.
pub fn vertical(mut self) -> Self {
self.is_horizontal_line = Some(false);
self
}
}
impl Widget for Separator {
fn ui(self, ui: &mut Ui) -> Response {
let Separator { spacing } = self;
let Separator {
spacing,
is_horizontal_line,
} = self;
let is_horizontal_line =
is_horizontal_line.unwrap_or_else(|| !ui.layout().main_dir().is_horizontal());
let available_space = ui.available_size_before_wrap_finite();
let size = if ui.layout().main_dir().is_horizontal() {
vec2(spacing, available_space.y)
} else {
let size = if is_horizontal_line {
vec2(available_space.x, spacing)
} else {
vec2(spacing, available_space.y)
};
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let points = if ui.layout().main_dir().is_horizontal() {
[
pos2(rect.center().x, rect.top()),
pos2(rect.center().x, rect.bottom()),
]
} else {
let points = if is_horizontal_line {
[
pos2(rect.left(), rect.center().y),
pos2(rect.right(), rect.center().y),
]
} else {
[
pos2(rect.center().x, rect.top()),
pos2(rect.center().x, rect.bottom()),
]
};
let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke;
ui.painter().line_segment(points, stroke);

View file

@ -131,7 +131,9 @@ impl super::View for WidgetGallery {
ui.end_row();
ui.label("Separator:");
ui.separator();
// Putting a separator in a grid is kind of meaningless since there is no well-defined direction.
// Normally you'd just do ui.separator(), but here we need to explicitly pick a dimension:
ui.add(egui::Separator::new().horizontal());
ui.end_row();
ui.label("CollapsingHeader:");