Direction enum now one of LeftToRight, RightToLeft, TopDown, BottomUp
This commit is contained in:
parent
ed6739867d
commit
c520f2e9cc
9 changed files with 249 additions and 238 deletions
|
@ -16,6 +16,21 @@ pub enum Align {
|
|||
Max,
|
||||
}
|
||||
|
||||
impl Align {
|
||||
pub fn left() -> Self {
|
||||
Self::Min
|
||||
}
|
||||
pub fn right() -> Self {
|
||||
Self::Max
|
||||
}
|
||||
pub fn top() -> Self {
|
||||
Self::Min
|
||||
}
|
||||
pub fn bottom() -> Self {
|
||||
Self::Max
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Align {
|
||||
fn default() -> Align {
|
||||
Align::Min
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::{
|
||||
layout::Direction,
|
||||
paint::{PaintCmd, TextStyle},
|
||||
widgets::Label,
|
||||
*,
|
||||
|
@ -168,7 +167,7 @@ struct Prepared {
|
|||
impl CollapsingHeader {
|
||||
fn begin(self, ui: &mut Ui) -> Prepared {
|
||||
assert!(
|
||||
ui.layout().dir() == Direction::Vertical,
|
||||
ui.layout().main_dir().is_vertical(),
|
||||
"Horizontal collapsing is unimplemented"
|
||||
);
|
||||
let Self {
|
||||
|
|
|
@ -60,10 +60,13 @@ pub fn combo_box(
|
|||
let frame = Frame::popup(ui.style());
|
||||
let frame_margin = frame.margin;
|
||||
frame.show(ui, |ui| {
|
||||
ui.with_layout(Layout::justified(Direction::Vertical), |ui| {
|
||||
ui.set_min_width(button_response.rect.width() - 2.0 * frame_margin.x);
|
||||
menu_contents(ui);
|
||||
});
|
||||
ui.with_layout(
|
||||
Layout::top_down(Align::left()).with_cross_justify(true),
|
||||
|ui| {
|
||||
ui.set_min_width(button_response.rect.width() - 2.0 * frame_margin.x);
|
||||
menu_contents(ui);
|
||||
},
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ impl DemoWindow {
|
|||
});
|
||||
|
||||
CollapsingHeader::new("Layout")
|
||||
.default_open(false)
|
||||
.default_open(true)
|
||||
.show(ui, |ui| self.layout.ui(ui));
|
||||
|
||||
CollapsingHeader::new("Tree")
|
||||
|
@ -304,29 +304,25 @@ use crate::layout::*;
|
|||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
struct LayoutDemo {
|
||||
dir: Direction,
|
||||
align: Option<Align>, // None == justified
|
||||
reversed: bool,
|
||||
// Identical to contents of `egui::Layout`
|
||||
main_dir: Direction,
|
||||
cross_align: Align,
|
||||
cross_justify: bool,
|
||||
}
|
||||
|
||||
impl Default for LayoutDemo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
dir: Direction::Vertical,
|
||||
align: Some(Align::Center),
|
||||
reversed: false,
|
||||
main_dir: Direction::TopDown,
|
||||
cross_align: Align::Min,
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutDemo {
|
||||
fn layout(&self) -> Layout {
|
||||
let layout = Layout::from_dir_align(self.dir, self.align);
|
||||
if self.reversed {
|
||||
layout.reverse()
|
||||
} else {
|
||||
layout
|
||||
}
|
||||
Layout::from_parts(self.main_dir, self.cross_align, self.cross_justify)
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui) {
|
||||
|
@ -347,39 +343,24 @@ impl LayoutDemo {
|
|||
|
||||
// TODO: enum iter
|
||||
|
||||
for &dir in &[Direction::Horizontal, Direction::Vertical] {
|
||||
if ui
|
||||
.add(RadioButton::new(self.dir == dir, format!("{:?}", dir)))
|
||||
.clicked
|
||||
{
|
||||
self.dir = dir;
|
||||
}
|
||||
for &dir in &[
|
||||
Direction::LeftToRight,
|
||||
Direction::RightToLeft,
|
||||
Direction::TopDown,
|
||||
Direction::BottomUp,
|
||||
] {
|
||||
ui.radio_value(&mut self.main_dir, dir, format!("{:?}", dir));
|
||||
}
|
||||
|
||||
ui.checkbox(&mut self.reversed, "Reversed");
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.label("Align:");
|
||||
|
||||
for &align in &[Align::Min, Align::Center, Align::Max] {
|
||||
if ui
|
||||
.add(RadioButton::new(
|
||||
self.align == Some(align),
|
||||
format!("{:?}", align),
|
||||
))
|
||||
.clicked
|
||||
{
|
||||
self.align = Some(align);
|
||||
}
|
||||
}
|
||||
if ui
|
||||
.add(RadioButton::new(self.align == None, "Justified"))
|
||||
.on_hover_text("Try to fill full width/height (e.g. buttons)")
|
||||
.clicked
|
||||
{
|
||||
self.align = None;
|
||||
ui.radio_value(&mut self.cross_align, align, format!("{:?}", align));
|
||||
}
|
||||
|
||||
ui.checkbox(&mut self.cross_justify, "Justified")
|
||||
.on_hover_text("Try to fill full width/height (e.g. buttons)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -345,7 +345,7 @@ fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight:
|
|||
(time % 1.0 * 100.0).floor()
|
||||
);
|
||||
|
||||
ui.with_layout(Layout::horizontal(Align::Center).reverse(), |ui| {
|
||||
ui.with_layout(Layout::right_to_left(), |ui| {
|
||||
if ui
|
||||
.add(Button::new(time).text_style(TextStyle::Monospace))
|
||||
.clicked
|
||||
|
|
|
@ -64,18 +64,30 @@ impl Region {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// `Layout` direction (horizontal or vertical).
|
||||
/// Main layout direction
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||
pub enum Direction {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
LeftToRight,
|
||||
RightToLeft,
|
||||
TopDown,
|
||||
BottomUp,
|
||||
}
|
||||
|
||||
impl Default for Direction {
|
||||
fn default() -> Direction {
|
||||
Direction::Vertical
|
||||
impl Direction {
|
||||
pub fn is_horizontal(self) -> bool {
|
||||
match self {
|
||||
Direction::LeftToRight | Direction::RightToLeft => true,
|
||||
Direction::TopDown | Direction::BottomUp => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_vertical(self) -> bool {
|
||||
match self {
|
||||
Direction::LeftToRight | Direction::RightToLeft => false,
|
||||
Direction::TopDown | Direction::BottomUp => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,111 +97,133 @@ impl Default for Direction {
|
|||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
// #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Layout {
|
||||
/// Lay out things horizontally or vertically? Main axis.
|
||||
dir: Direction,
|
||||
/// Main axis direction
|
||||
main_dir: Direction,
|
||||
|
||||
/// How to align things on the cross axis.
|
||||
/// For vertical layouts: put things to left, center or right?
|
||||
/// For horizontal layouts: put things to top, center or bottom?
|
||||
/// `None` means justified, which means full width (vertical layout) or height (horizontal layouts).
|
||||
align: Option<Align>,
|
||||
cross_align: Align,
|
||||
|
||||
/// Lay out things in reversed order, i.e. from the right or bottom-up.
|
||||
reversed: bool,
|
||||
/// Justify the cross axis?
|
||||
/// For vertical layouts justify mean all widgets get maximum width.
|
||||
/// For horizontal layouts justify mean all widgets get maximum height.
|
||||
cross_justify: bool,
|
||||
}
|
||||
|
||||
impl Default for Layout {
|
||||
fn default() -> Self {
|
||||
// TODO: Get from `Style` instead.
|
||||
// This is a very euro-centric default.
|
||||
Self {
|
||||
dir: Direction::Vertical,
|
||||
align: Some(Align::Min),
|
||||
reversed: false,
|
||||
main_dir: Direction::TopDown,
|
||||
cross_align: Align::left(),
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
/// None align means justified, e.g. fill full width/height.
|
||||
pub fn from_dir_align(dir: Direction, align: Option<Align>) -> Self {
|
||||
pub(crate) fn from_parts(main_dir: Direction, cross_align: Align, cross_justify: bool) -> Self {
|
||||
Self {
|
||||
dir,
|
||||
align,
|
||||
reversed: false,
|
||||
main_dir,
|
||||
cross_align,
|
||||
cross_justify,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertical(align: Align) -> Self {
|
||||
#[deprecated = "Use `top_down`"]
|
||||
pub fn vertical(cross_align: Align) -> Self {
|
||||
Self::top_down(cross_align)
|
||||
}
|
||||
|
||||
#[deprecated = "Use `left_to_right`"]
|
||||
pub fn horizontal(cross_align: Align) -> Self {
|
||||
Self::left_to_right().with_cross_align(cross_align)
|
||||
}
|
||||
|
||||
pub fn left_to_right() -> Self {
|
||||
Self {
|
||||
dir: Direction::Vertical,
|
||||
align: Some(align),
|
||||
reversed: false,
|
||||
main_dir: Direction::LeftToRight,
|
||||
cross_align: Align::Center,
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn horizontal(align: Align) -> Self {
|
||||
pub fn right_to_left() -> Self {
|
||||
Self {
|
||||
dir: Direction::Horizontal,
|
||||
align: Some(align),
|
||||
reversed: false,
|
||||
main_dir: Direction::RightToLeft,
|
||||
cross_align: Align::Center,
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Full-width layout.
|
||||
/// Nice for menus etc where each button is full width.
|
||||
pub fn justified(dir: Direction) -> Self {
|
||||
pub fn top_down(cross_align: Align) -> Self {
|
||||
Self {
|
||||
dir,
|
||||
align: None,
|
||||
reversed: false,
|
||||
main_dir: Direction::TopDown,
|
||||
cross_align,
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn reverse(self) -> Self {
|
||||
pub fn bottom_up(cross_align: Align) -> Self {
|
||||
Self {
|
||||
dir: self.dir,
|
||||
align: self.align,
|
||||
reversed: !self.reversed,
|
||||
main_dir: Direction::BottomUp,
|
||||
cross_align,
|
||||
cross_justify: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_reversed(self, reversed: bool) -> Self {
|
||||
if reversed {
|
||||
self.reverse()
|
||||
} else {
|
||||
self
|
||||
pub fn with_cross_align(self, cross_align: Align) -> Self {
|
||||
Self {
|
||||
cross_align,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dir(self) -> Direction {
|
||||
self.dir
|
||||
pub fn with_cross_justify(self, cross_justify: bool) -> Self {
|
||||
Self {
|
||||
cross_justify,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align(self) -> Option<Align> {
|
||||
self.align
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
pub fn main_dir(self) -> Direction {
|
||||
self.main_dir
|
||||
}
|
||||
|
||||
pub fn is_reversed(self) -> bool {
|
||||
self.reversed
|
||||
pub fn cross_align(self) -> Align {
|
||||
self.cross_align
|
||||
}
|
||||
|
||||
pub fn cross_justify(self) -> bool {
|
||||
self.cross_justify
|
||||
}
|
||||
|
||||
pub fn is_horizontal(self) -> bool {
|
||||
self.main_dir().is_horizontal()
|
||||
}
|
||||
|
||||
pub fn is_vertical(self) -> bool {
|
||||
self.main_dir().is_vertical()
|
||||
}
|
||||
|
||||
pub fn prefer_right_to_left(self) -> bool {
|
||||
self.main_dir == Direction::RightToLeft
|
||||
|| self.main_dir.is_vertical() && self.cross_align == Align::Max
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
fn initial_cursor(self, max_rect: Rect) -> Pos2 {
|
||||
match self.dir {
|
||||
Direction::Horizontal => {
|
||||
if self.reversed {
|
||||
max_rect.right_top()
|
||||
} else {
|
||||
max_rect.left_top()
|
||||
}
|
||||
}
|
||||
Direction::Vertical => {
|
||||
if self.reversed {
|
||||
max_rect.left_bottom()
|
||||
} else {
|
||||
max_rect.left_top()
|
||||
}
|
||||
}
|
||||
match self.main_dir {
|
||||
Direction::LeftToRight => max_rect.left_top(),
|
||||
Direction::RightToLeft => max_rect.right_top(),
|
||||
Direction::TopDown => max_rect.left_top(),
|
||||
Direction::BottomUp => max_rect.left_bottom(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,52 +249,45 @@ impl Layout {
|
|||
/// for the next widget?
|
||||
fn available_from_cursor_max_rect(self, cursor: Pos2, max_rect: Rect) -> Rect {
|
||||
let mut rect = max_rect;
|
||||
match self.dir {
|
||||
Direction::Horizontal => {
|
||||
rect.min.y = cursor.y;
|
||||
if self.reversed {
|
||||
rect.max.x = cursor.x;
|
||||
} else {
|
||||
rect.min.x = cursor.x;
|
||||
}
|
||||
}
|
||||
Direction::Vertical => {
|
||||
|
||||
match self.main_dir {
|
||||
Direction::LeftToRight => {
|
||||
rect.min.x = cursor.x;
|
||||
if self.reversed {
|
||||
rect.max.y = cursor.y;
|
||||
} else {
|
||||
rect.min.y = cursor.y;
|
||||
}
|
||||
rect.min.y = cursor.y;
|
||||
}
|
||||
Direction::RightToLeft => {
|
||||
rect.max.x = cursor.x;
|
||||
rect.min.y = cursor.y;
|
||||
}
|
||||
Direction::TopDown => {
|
||||
rect.min.x = cursor.x;
|
||||
rect.min.y = cursor.y;
|
||||
}
|
||||
Direction::BottomUp => {
|
||||
rect.min.x = cursor.x;
|
||||
rect.max.y = cursor.y;
|
||||
}
|
||||
}
|
||||
|
||||
rect
|
||||
}
|
||||
|
||||
/// Advance the cursor by this many points.
|
||||
pub fn advance_cursor(self, region: &mut Region, amount: f32) {
|
||||
match self.dir() {
|
||||
Direction::Horizontal => {
|
||||
if self.is_reversed() {
|
||||
region.cursor.x -= amount;
|
||||
} else {
|
||||
region.cursor.x += amount;
|
||||
}
|
||||
}
|
||||
Direction::Vertical => {
|
||||
if self.is_reversed() {
|
||||
region.cursor.y -= amount;
|
||||
} else {
|
||||
region.cursor.y += amount;
|
||||
}
|
||||
}
|
||||
match self.main_dir {
|
||||
Direction::LeftToRight => region.cursor.x += amount,
|
||||
Direction::RightToLeft => region.cursor.x -= amount,
|
||||
Direction::TopDown => region.cursor.y += amount,
|
||||
Direction::BottomUp => region.cursor.y -= amount,
|
||||
}
|
||||
}
|
||||
|
||||
/// Advance the cursor by this spacing
|
||||
pub fn advance_cursor2(self, region: &mut Region, amount: Vec2) {
|
||||
match self.dir() {
|
||||
Direction::Horizontal => self.advance_cursor(region, amount.x),
|
||||
Direction::Vertical => self.advance_cursor(region, amount.y),
|
||||
if self.main_dir.is_horizontal() {
|
||||
self.advance_cursor(region, amount.x)
|
||||
} else {
|
||||
self.advance_cursor(region, amount.y)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,49 +309,39 @@ impl Layout {
|
|||
|
||||
let mut child_size = minimum_child_size;
|
||||
let mut child_move = Vec2::default();
|
||||
let mut cursor_change = Vec2::default();
|
||||
|
||||
match self.dir {
|
||||
Direction::Horizontal => {
|
||||
if let Some(align) = self.align {
|
||||
child_move.y += match align {
|
||||
Align::Min => 0.0,
|
||||
Align::Center => 0.5 * (available_size.y - child_size.y),
|
||||
Align::Max => available_size.y - child_size.y,
|
||||
};
|
||||
} else {
|
||||
// justified: fill full height
|
||||
child_size.y = child_size.y.max(available_size.y);
|
||||
}
|
||||
|
||||
cursor_change.x += child_size.x;
|
||||
}
|
||||
Direction::Vertical => {
|
||||
if let Some(align) = self.align {
|
||||
child_move.x += match align {
|
||||
Align::Min => 0.0,
|
||||
Align::Center => 0.5 * (available_size.x - child_size.x),
|
||||
Align::Max => available_size.x - child_size.x,
|
||||
};
|
||||
} else {
|
||||
// justified: fill full width
|
||||
child_size.x = child_size.x.max(available_size.x);
|
||||
if self.main_dir.is_horizontal() {
|
||||
if self.cross_justify {
|
||||
// fill full height
|
||||
child_size.y = child_size.y.max(available_size.y);
|
||||
} else {
|
||||
child_move.y += match self.cross_align {
|
||||
Align::Min => 0.0,
|
||||
Align::Center => 0.5 * (available_size.y - child_size.y),
|
||||
Align::Max => available_size.y - child_size.y,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if self.cross_justify {
|
||||
// justified: fill full width
|
||||
child_size.x = child_size.x.max(available_size.x);
|
||||
} else {
|
||||
child_move.x += match self.cross_align {
|
||||
Align::Min => 0.0,
|
||||
Align::Center => 0.5 * (available_size.x - child_size.x),
|
||||
Align::Max => available_size.x - child_size.x,
|
||||
};
|
||||
cursor_change.y += child_size.y;
|
||||
}
|
||||
}
|
||||
|
||||
if self.is_reversed() {
|
||||
let child_pos = region.cursor + child_move;
|
||||
let child_pos = match self.dir {
|
||||
Direction::Horizontal => child_pos + vec2(-child_size.x, 0.0),
|
||||
Direction::Vertical => child_pos + vec2(0.0, -child_size.y),
|
||||
};
|
||||
Rect::from_min_size(child_pos, child_size)
|
||||
} else {
|
||||
let child_pos = region.cursor + child_move;
|
||||
Rect::from_min_size(child_pos, child_size)
|
||||
}
|
||||
let child_pos = match self.main_dir {
|
||||
Direction::LeftToRight => region.cursor + child_move,
|
||||
Direction::RightToLeft => region.cursor + child_move + vec2(-child_size.x, 0.0),
|
||||
Direction::TopDown => region.cursor + child_move,
|
||||
Direction::BottomUp => region.cursor + child_move + vec2(0.0, -child_size.y),
|
||||
};
|
||||
|
||||
Rect::from_min_size(child_pos, child_size)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,24 +360,22 @@ impl Layout {
|
|||
|
||||
let align;
|
||||
|
||||
match self.dir {
|
||||
Direction::Horizontal => {
|
||||
if self.reversed {
|
||||
painter.debug_arrow(cursor, vec2(-1.0, 0.0), stroke);
|
||||
align = (Align::Max, Align::Min);
|
||||
} else {
|
||||
painter.debug_arrow(cursor, vec2(1.0, 0.0), stroke);
|
||||
align = (Align::Min, Align::Min);
|
||||
}
|
||||
match self.main_dir {
|
||||
Direction::LeftToRight => {
|
||||
painter.debug_arrow(cursor, vec2(1.0, 0.0), stroke);
|
||||
align = (Align::Min, Align::Min);
|
||||
}
|
||||
Direction::Vertical => {
|
||||
if self.reversed {
|
||||
painter.debug_arrow(cursor, vec2(0.0, -1.0), stroke);
|
||||
align = (Align::Min, Align::Max);
|
||||
} else {
|
||||
painter.debug_arrow(cursor, vec2(0.0, 1.0), stroke);
|
||||
align = (Align::Min, Align::Min);
|
||||
}
|
||||
Direction::RightToLeft => {
|
||||
painter.debug_arrow(cursor, vec2(-1.0, 0.0), stroke);
|
||||
align = (Align::Max, Align::Min);
|
||||
}
|
||||
Direction::TopDown => {
|
||||
painter.debug_arrow(cursor, vec2(0.0, 1.0), stroke);
|
||||
align = (Align::Min, Align::Min);
|
||||
}
|
||||
Direction::BottomUp => {
|
||||
painter.debug_arrow(cursor, vec2(0.0, -1.0), stroke);
|
||||
align = (Align::Min, Align::Max);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,10 @@ fn menu_impl<'c>(
|
|||
style.visuals.widgets.inactive.bg_fill = TRANSPARENT;
|
||||
style.visuals.widgets.inactive.bg_stroke = Stroke::none();
|
||||
ui.set_style(style);
|
||||
ui.with_layout(Layout::justified(Direction::Vertical), add_contents);
|
||||
ui.with_layout(
|
||||
Layout::top_down(Align::left()).with_cross_justify(true),
|
||||
add_contents,
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ impl Ui {
|
|||
/// Set the maximum width of the ui.
|
||||
/// You won't be able to shrink it below the current minimum size.
|
||||
pub fn set_max_width(&mut self, width: f32) {
|
||||
if self.layout.dir() == Direction::Horizontal && self.layout.is_reversed() {
|
||||
if self.layout.main_dir() == Direction::RightToLeft {
|
||||
debug_assert_eq!(self.min_rect().max.x, self.max_rect().max.x);
|
||||
self.region.max_rect.min.x =
|
||||
self.region.max_rect.max.x - width.at_least(self.min_rect().width());
|
||||
|
@ -237,7 +237,7 @@ impl Ui {
|
|||
/// Set the maximum height of the ui.
|
||||
/// You won't be able to shrink it below the current minimum size.
|
||||
pub fn set_max_height(&mut self, height: f32) {
|
||||
if self.layout.dir() == Direction::Vertical && self.layout.is_reversed() {
|
||||
if self.layout.main_dir() == Direction::BottomUp {
|
||||
debug_assert_eq!(self.min_rect().max.y, self.region.max_rect.max.y);
|
||||
self.region.max_rect.min.y =
|
||||
self.region.max_rect.max.y - height.at_least(self.min_rect().height());
|
||||
|
@ -260,7 +260,7 @@ impl Ui {
|
|||
/// Set the minimum width of the ui.
|
||||
/// This can't shrink the ui, only make it larger.
|
||||
pub fn set_min_width(&mut self, width: f32) {
|
||||
if self.layout.dir() == Direction::Horizontal && self.layout.is_reversed() {
|
||||
if self.layout.main_dir() == Direction::RightToLeft {
|
||||
debug_assert_eq!(self.region.min_rect.max.x, self.region.max_rect.max.x);
|
||||
let min_rect = &mut self.region.min_rect;
|
||||
min_rect.min.x = min_rect.min.x.min(min_rect.max.x - width);
|
||||
|
@ -275,7 +275,7 @@ impl Ui {
|
|||
/// Set the minimum height of the ui.
|
||||
/// This can't shrink the ui, only make it larger.
|
||||
pub fn set_min_height(&mut self, height: f32) {
|
||||
if self.layout.dir() == Direction::Vertical && self.layout.is_reversed() {
|
||||
if self.layout.main_dir() == Direction::BottomUp {
|
||||
debug_assert_eq!(self.region.min_rect.max.y, self.region.max_rect.max.y);
|
||||
let min_rect = &mut self.region.min_rect;
|
||||
min_rect.min.y = min_rect.min.y.min(min_rect.max.y - height);
|
||||
|
@ -733,8 +733,9 @@ impl Ui {
|
|||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> (R, Response) {
|
||||
assert!(
|
||||
self.layout().dir() == Direction::Vertical,
|
||||
"You can only indent vertical layouts"
|
||||
self.layout.is_vertical(),
|
||||
"You can only indent vertical layouts, found {:?}",
|
||||
self.layout
|
||||
);
|
||||
let indent = vec2(self.style().spacing.indent, 0.0);
|
||||
let child_rect =
|
||||
|
@ -805,22 +806,19 @@ impl Ui {
|
|||
self.style().spacing.interact_size.y, // Assume there will be something interactive on the horizontal layout
|
||||
);
|
||||
|
||||
let right_to_left =
|
||||
(self.layout.dir(), self.layout.align()) == (Direction::Vertical, Some(Align::Max));
|
||||
let layout = if self.layout.prefer_right_to_left() {
|
||||
Layout::right_to_left()
|
||||
} else {
|
||||
Layout::left_to_right()
|
||||
};
|
||||
|
||||
self.allocate_ui_min(initial_size, |ui| {
|
||||
ui.with_layout(
|
||||
Layout::horizontal(Align::Center).with_reversed(right_to_left),
|
||||
add_contents,
|
||||
)
|
||||
.0
|
||||
})
|
||||
self.allocate_ui_min(initial_size, |ui| ui.with_layout(layout, add_contents).0)
|
||||
}
|
||||
|
||||
/// Start a ui with vertical layout.
|
||||
/// Widgets will be left-justified.
|
||||
pub fn vertical<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
|
||||
self.with_layout(Layout::vertical(Align::Min), add_contents)
|
||||
self.with_layout(Layout::top_down(Align::Min), add_contents)
|
||||
}
|
||||
|
||||
pub fn with_layout<R>(
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#![allow(clippy::new_without_default)]
|
||||
|
||||
use crate::{layout::Direction, *};
|
||||
use crate::*;
|
||||
|
||||
pub mod color_picker;
|
||||
mod drag_value;
|
||||
|
@ -606,27 +606,24 @@ impl Widget for Separator {
|
|||
|
||||
let available_space = ui.available_finite().size();
|
||||
|
||||
let (points, rect) = match ui.layout().dir() {
|
||||
Direction::Horizontal => {
|
||||
let rect = ui.allocate_space(vec2(spacing, available_space.y));
|
||||
(
|
||||
[
|
||||
pos2(rect.center().x, rect.top()),
|
||||
pos2(rect.center().x, rect.bottom()),
|
||||
],
|
||||
rect,
|
||||
)
|
||||
}
|
||||
Direction::Vertical => {
|
||||
let rect = ui.allocate_space(vec2(available_space.x, spacing));
|
||||
(
|
||||
[
|
||||
pos2(rect.left(), rect.center().y),
|
||||
pos2(rect.right(), rect.center().y),
|
||||
],
|
||||
rect,
|
||||
)
|
||||
}
|
||||
let (points, rect) = if ui.layout().main_dir().is_horizontal() {
|
||||
let rect = ui.allocate_space(vec2(spacing, available_space.y));
|
||||
(
|
||||
[
|
||||
pos2(rect.center().x, rect.top()),
|
||||
pos2(rect.center().x, rect.bottom()),
|
||||
],
|
||||
rect,
|
||||
)
|
||||
} else {
|
||||
let rect = ui.allocate_space(vec2(available_space.x, spacing));
|
||||
(
|
||||
[
|
||||
pos2(rect.left(), rect.center().y),
|
||||
pos2(rect.right(), rect.center().y),
|
||||
],
|
||||
rect,
|
||||
)
|
||||
};
|
||||
let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke;
|
||||
ui.painter().line_segment(points, stroke);
|
||||
|
|
Loading…
Reference in a new issue