Correctly align buttons and labels in justified layouts

This commit is contained in:
Emil Ernerfeldt 2020-12-06 13:12:34 +01:00
parent c520f2e9cc
commit a97141fe06
3 changed files with 44 additions and 12 deletions

View file

@ -335,14 +335,13 @@ impl LayoutDemo {
pub fn content_ui(&mut self, ui: &mut Ui) {
// ui.label(format!("Available space: {:?}", ui.available().size()));
if ui.button("Reset").clicked {
if ui.button("Default").clicked {
*self = Default::default();
}
ui.separator();
ui.label("Direction:");
// TODO: enum iter
ui.label("Main Direction:");
for &dir in &[
Direction::LeftToRight,
Direction::RightToLeft,
@ -354,12 +353,14 @@ impl LayoutDemo {
ui.separator();
ui.label("Align:");
ui.label("Cross Align:");
for &align in &[Align::Min, Align::Center, Align::Max] {
ui.radio_value(&mut self.cross_align, align, format!("{:?}", align));
}
ui.checkbox(&mut self.cross_justify, "Justified")
ui.separator();
ui.checkbox(&mut self.cross_justify, "Cross Justified")
.on_hover_text("Try to fill full width/height (e.g. buttons)");
}
}

View file

@ -216,6 +216,37 @@ impl Layout {
|| self.main_dir.is_vertical() && self.cross_align == Align::Max
}
pub fn horizontal_align(self) -> Align {
match self.main_dir {
Direction::LeftToRight => Align::left(),
Direction::RightToLeft => Align::right(),
Direction::TopDown | Direction::BottomUp => self.cross_align,
}
}
pub fn vertical_align(self) -> Align {
match self.main_dir {
Direction::TopDown => Align::top(),
Direction::BottomUp => Align::bottom(),
Direction::LeftToRight | Direction::RightToLeft => self.cross_align,
}
}
pub fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
let x = match self.horizontal_align() {
Align::Min => outer.left(),
Align::Center => outer.center().x - size.x / 2.0,
Align::Max => outer.right() - size.x,
};
let y = match self.vertical_align() {
Align::Min => outer.top(),
Align::Center => outer.center().y - size.y / 2.0,
Align::Max => outer.bottom() - size.y,
};
Rect::from_min_size(Pos2::new(x, y), size)
}
// ------------------------------------------------------------------------
fn initial_cursor(self, max_rect: Rect) -> Pos2 {
@ -303,6 +334,7 @@ impl Layout {
/// for justified layouts, like in menus.
///
/// You may get LESS space than you asked for if the current layout won't fit what you asked for.
#[allow(clippy::collapsible_if)]
pub fn next_space(self, region: &Region, minimum_child_size: Vec2) -> Rect {
let available_size = self.available_finite(region).size();
let available_size = available_size.at_least(minimum_child_size);

View file

@ -127,6 +127,7 @@ impl Widget for Label {
fn ui(self, ui: &mut Ui) -> Response {
let galley = self.layout(ui);
let rect = ui.allocate_space(galley.size);
let rect = ui.layout().align_size_within_rect(galley.size, rect);
self.paint_galley(ui, rect.min, galley);
ui.interact_hover(rect)
}
@ -314,11 +315,10 @@ impl Widget for Button {
let id = ui.make_position_id();
let response = ui.interact(rect, id, sense);
let visuals = ui.style().interact(&response);
// let text_cursor = response.rect.center() - 0.5 * galley.size; // centered-centered (looks bad for justified drop-down menus
let text_cursor = pos2(
response.rect.left() + button_padding.x,
response.rect.center().y - 0.5 * galley.size.y,
); // left-centered
let text_cursor = ui
.layout()
.align_size_within_rect(galley.size, response.rect.shrink2(button_padding))
.min;
let fill = fill.unwrap_or(visuals.bg_fill);
ui.painter().rect(
response.rect,
@ -473,7 +473,6 @@ impl Widget for RadioButton {
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
desired_size.y = desired_size.y.max(icon_width);
let rect = ui.allocate_space(desired_size);
let id = ui.make_position_id();
let response = ui.interact(rect, id, Sense::click());