[grid] Ensure the contents of each grid cell is aligned left+center
This commit is contained in:
parent
db591bc56c
commit
03c9cda89b
5 changed files with 87 additions and 23 deletions
|
@ -100,6 +100,15 @@ impl GridLayout {
|
||||||
Rect::from_min_size(cursor, size)
|
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) {
|
pub(crate) fn advance(&mut self, cursor: &mut Pos2, frame_rect: Rect, widget_rect: Rect) {
|
||||||
self.curr_state
|
self.curr_state
|
||||||
.set_min_col_width(self.col, widget_rect.width());
|
.set_min_col_width(self.col, widget_rect.width());
|
||||||
|
@ -145,6 +154,10 @@ impl GridLayout {
|
||||||
|
|
||||||
/// A simple `Grid` layout.
|
/// 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();
|
/// # let ui = &mut egui::Ui::__test();
|
||||||
/// egui::Grid::new("some_unique_id").show(ui, |ui| {
|
/// egui::Grid::new("some_unique_id").show(ui, |ui| {
|
||||||
|
@ -196,7 +209,11 @@ impl Grid {
|
||||||
min_row_height,
|
min_row_height,
|
||||||
} = self;
|
} = 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 id = ui.make_persistent_id(id_source);
|
||||||
let grid = GridLayout {
|
let grid = GridLayout {
|
||||||
striped,
|
striped,
|
||||||
|
|
|
@ -432,16 +432,27 @@ impl Layout {
|
||||||
|
|
||||||
/// Apply justify or alignment after calling `next_space`.
|
/// Apply justify or alignment after calling `next_space`.
|
||||||
pub(crate) fn justify_or_align(&self, rect: Rect, mut child_size: Vec2) -> Rect {
|
pub(crate) fn justify_or_align(&self, rect: Rect, mut child_size: Vec2) -> Rect {
|
||||||
|
if self.cross_justify {
|
||||||
if self.main_dir.is_horizontal() {
|
if self.main_dir.is_horizontal() {
|
||||||
if self.cross_justify {
|
|
||||||
child_size.y = rect.height(); // fill full height
|
child_size.y = rect.height(); // fill full height
|
||||||
}
|
|
||||||
Align2([Align::Center, self.cross_align]).align_size_within_rect(child_size, rect)
|
|
||||||
} else {
|
} else {
|
||||||
if self.cross_justify {
|
|
||||||
child_size.x = rect.width(); // fill full width
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,12 @@ impl Placer {
|
||||||
|
|
||||||
impl Placer {
|
impl Placer {
|
||||||
pub(crate) fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
|
pub(crate) fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
|
||||||
|
if let Some(grid) = &self.grid {
|
||||||
|
grid.align_size_within_rect(size, outer)
|
||||||
|
} else {
|
||||||
self.layout.align_size_within_rect(size, outer)
|
self.layout.align_size_within_rect(size, outer)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn available_rect_before_wrap(&self) -> Rect {
|
pub(crate) fn available_rect_before_wrap(&self) -> Rect {
|
||||||
if let Some(grid) = &self.grid {
|
if let Some(grid) = &self.grid {
|
||||||
|
@ -102,8 +106,12 @@ impl Placer {
|
||||||
|
|
||||||
/// Apply justify or alignment after calling `next_space`.
|
/// Apply justify or alignment after calling `next_space`.
|
||||||
pub(crate) fn justify_or_align(&self, rect: Rect, child_size: Vec2) -> Rect {
|
pub(crate) fn justify_or_align(&self, rect: Rect, child_size: Vec2) -> Rect {
|
||||||
|
if let Some(grid) = &self.grid {
|
||||||
|
grid.justify_or_align(rect, child_size)
|
||||||
|
} else {
|
||||||
self.layout.justify_or_align(rect, child_size)
|
self.layout.justify_or_align(rect, child_size)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Advance the cursor by this many points.
|
/// Advance the cursor by this many points.
|
||||||
pub(crate) fn advance_cursor(&mut self, amount: f32) {
|
pub(crate) fn advance_cursor(&mut self, amount: f32) {
|
||||||
|
@ -115,7 +123,7 @@ impl Placer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance cursor after a widget was added to a specific rectangle
|
/// 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
|
/// * `frame_rect`: the frame inside which a widget was e.g. centered
|
||||||
/// * `widget_rect`: the actual rect used by the widget
|
/// * `widget_rect`: the actual rect used by the widget
|
||||||
|
|
|
@ -4,11 +4,15 @@ use crate::*;
|
||||||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||||
pub struct Separator {
|
pub struct Separator {
|
||||||
spacing: f32,
|
spacing: f32,
|
||||||
|
is_horizontal_line: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Separator {
|
impl Separator {
|
||||||
pub fn new() -> Self {
|
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.
|
/// 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.spacing = spacing;
|
||||||
self
|
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 {
|
impl Widget for Separator {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
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 available_space = ui.available_size_before_wrap_finite();
|
||||||
|
|
||||||
let size = if ui.layout().main_dir().is_horizontal() {
|
let size = if is_horizontal_line {
|
||||||
vec2(spacing, available_space.y)
|
|
||||||
} else {
|
|
||||||
vec2(available_space.x, spacing)
|
vec2(available_space.x, spacing)
|
||||||
|
} else {
|
||||||
|
vec2(spacing, available_space.y)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
||||||
let points = if ui.layout().main_dir().is_horizontal() {
|
let points = if is_horizontal_line {
|
||||||
[
|
|
||||||
pos2(rect.center().x, rect.top()),
|
|
||||||
pos2(rect.center().x, rect.bottom()),
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
[
|
[
|
||||||
pos2(rect.left(), rect.center().y),
|
pos2(rect.left(), rect.center().y),
|
||||||
pos2(rect.right(), 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;
|
let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke;
|
||||||
ui.painter().line_segment(points, stroke);
|
ui.painter().line_segment(points, stroke);
|
||||||
|
|
|
@ -131,7 +131,9 @@ impl super::View for WidgetGallery {
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
|
|
||||||
ui.label("Separator:");
|
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.end_row();
|
||||||
|
|
||||||
ui.label("CollapsingHeader:");
|
ui.label("CollapsingHeader:");
|
||||||
|
|
Loading…
Reference in a new issue