[refactor] Ui: rename child_bounds to min_rect, desired_rect to max_rect
This commit is contained in:
parent
43bb670c0c
commit
908d1d0c08
10 changed files with 153 additions and 121 deletions
|
@ -173,7 +173,7 @@ impl Prepared {
|
||||||
movable,
|
movable,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
state.size = (content_ui.child_bounds().max - state.pos).ceil();
|
state.size = (content_ui.min_rect().max - state.pos).ceil();
|
||||||
|
|
||||||
let rect = Rect::from_min_size(state.pos, state.size);
|
let rect = Rect::from_min_size(state.pos, state.size);
|
||||||
let clip_rect = Rect::everything(); // TODO: get from context
|
let clip_rect = Rect::everything(); // TODO: get from context
|
||||||
|
@ -214,11 +214,6 @@ impl Prepared {
|
||||||
));
|
));
|
||||||
state.pos = ctx.round_pos_to_pixels(state.pos);
|
state.pos = ctx.round_pos_to_pixels(state.pos);
|
||||||
|
|
||||||
// ctx.debug_rect(
|
|
||||||
// Rect::from_min_size(state.pos, state.size),
|
|
||||||
// &format!("Area size: {:?}", state.size),
|
|
||||||
// );
|
|
||||||
|
|
||||||
if move_response.active
|
if move_response.active
|
||||||
|| mouse_pressed_on_area(ctx, layer)
|
|| mouse_pressed_on_area(ctx, layer)
|
||||||
|| !ctx.memory().areas.visible_last_frame(&layer)
|
|| !ctx.memory().areas.visible_last_frame(&layer)
|
||||||
|
|
|
@ -78,18 +78,18 @@ impl State {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut clip_rect = child_ui.clip_rect();
|
let mut clip_rect = child_ui.clip_rect();
|
||||||
clip_rect.max.y = clip_rect.max.y.min(child_ui.rect().top() + max_height);
|
clip_rect.max.y = clip_rect.max.y.min(child_ui.max_rect().top() + max_height);
|
||||||
child_ui.set_clip_rect(clip_rect);
|
child_ui.set_clip_rect(clip_rect);
|
||||||
|
|
||||||
let top_left = child_ui.top_left();
|
let left_top = child_ui.left_top();
|
||||||
let r = add_contents(child_ui);
|
let r = add_contents(child_ui);
|
||||||
|
|
||||||
self.open_height = Some(child_ui.bounding_size().y);
|
self.open_height = Some(child_ui.min_size().y);
|
||||||
|
|
||||||
// Pretend children took up less space:
|
// Pretend children took up less space:
|
||||||
let mut child_bounds = child_ui.child_bounds();
|
let mut min_rect = child_ui.min_rect();
|
||||||
child_bounds.max.y = child_bounds.max.y.min(top_left.y + max_height);
|
min_rect.max.y = min_rect.max.y.min(left_top.y + max_height);
|
||||||
child_ui.force_set_child_bounds(child_bounds);
|
child_ui.force_set_min_rect(min_rect);
|
||||||
r
|
r
|
||||||
}))
|
}))
|
||||||
} else if self.open {
|
} else if self.open {
|
||||||
|
|
|
@ -35,11 +35,11 @@ pub fn combo_box(
|
||||||
|
|
||||||
selected.ui(ui);
|
selected.ui(ui);
|
||||||
|
|
||||||
let advance = full_minimum_width - icon_width - ui.child_bounds().width();
|
let advance = full_minimum_width - icon_width - ui.min_rect().width();
|
||||||
ui.advance_cursor(advance.at_least(0.0));
|
ui.advance_cursor(advance.at_least(0.0));
|
||||||
|
|
||||||
let icon_rect = ui.allocate_space(Vec2::splat(icon_width));
|
let icon_rect = ui.allocate_space(Vec2::splat(icon_width));
|
||||||
let button_rect = ui.rect().expand2(ui.style().spacing.button_padding);
|
let button_rect = ui.min_rect().expand2(ui.style().spacing.button_padding);
|
||||||
let mut response = ui.interact(button_rect, button_id, Sense::click());
|
let mut response = ui.interact(button_rect, button_id, Sense::click());
|
||||||
response.active |= button_active;
|
response.active |= button_active;
|
||||||
paint_icon(ui.painter(), icon_rect, ui.style().interact(&response));
|
paint_icon(ui.painter(), icon_rect, ui.style().interact(&response));
|
||||||
|
@ -57,8 +57,10 @@ pub fn combo_box(
|
||||||
let frame = Frame::popup(ui.style());
|
let frame = Frame::popup(ui.style());
|
||||||
let frame_margin = frame.margin;
|
let frame_margin = frame.margin;
|
||||||
frame.show(ui, |ui| {
|
frame.show(ui, |ui| {
|
||||||
ui.set_min_width(button_response.rect.width() - 2.0 * frame_margin.x);
|
ui.with_layout(Layout::justified(Direction::Vertical), |ui| {
|
||||||
ui.with_layout(Layout::justified(Direction::Vertical), menu_contents);
|
ui.set_min_width(button_response.rect.width() - 2.0 * frame_margin.x);
|
||||||
|
menu_contents(ui);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -85,10 +87,7 @@ fn button_frame(
|
||||||
let mut content_ui = ui.child_ui(inner_rect, *ui.layout());
|
let mut content_ui = ui.child_ui(inner_rect, *ui.layout());
|
||||||
add_contents(&mut content_ui);
|
add_contents(&mut content_ui);
|
||||||
|
|
||||||
let outer_rect = Rect::from_min_max(
|
let outer_rect = Rect::from_min_max(outer_rect_bounds.min, content_ui.min_rect().max + margin);
|
||||||
outer_rect_bounds.min,
|
|
||||||
content_ui.child_bounds().max + margin,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut response = ui.interact(outer_rect, id, sense);
|
let mut response = ui.interact(outer_rect, id, sense);
|
||||||
response.active |= button_active;
|
response.active |= button_active;
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl Prepared {
|
||||||
pub fn outer_rect(&self) -> Rect {
|
pub fn outer_rect(&self) -> Rect {
|
||||||
Rect::from_min_max(
|
Rect::from_min_max(
|
||||||
self.outer_rect_bounds.min,
|
self.outer_rect_bounds.min,
|
||||||
self.content_ui.child_bounds().max + self.frame.margin,
|
self.content_ui.min_rect().max + self.frame.margin,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ impl Resize {
|
||||||
content_ui,
|
content_ui,
|
||||||
} = prepared;
|
} = prepared;
|
||||||
|
|
||||||
state.last_content_size = content_ui.bounding_size();
|
state.last_content_size = content_ui.min_size();
|
||||||
state.last_content_size = state.last_content_size.ceil(); // Avoid rounding errors in math
|
state.last_content_size = state.last_content_size.ceil(); // Avoid rounding errors in math
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
@ -251,7 +251,7 @@ impl Resize {
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
if self.with_stroke && corner_response.is_some() {
|
if self.with_stroke && corner_response.is_some() {
|
||||||
let rect = Rect::from_min_size(content_ui.top_left(), state.desired_size);
|
let rect = Rect::from_min_size(content_ui.left_top(), state.desired_size);
|
||||||
let rect = rect.expand(2.0); // breathing room for content
|
let rect = rect.expand(2.0); // breathing room for content
|
||||||
ui.painter().add(paint::PaintCmd::Rect {
|
ui.painter().add(paint::PaintCmd::Rect {
|
||||||
rect,
|
rect,
|
||||||
|
@ -273,12 +273,12 @@ impl Resize {
|
||||||
|
|
||||||
if ui.ctx().style().visuals.debug_resize {
|
if ui.ctx().style().visuals.debug_resize {
|
||||||
ui.ctx().debug_painter().debug_rect(
|
ui.ctx().debug_painter().debug_rect(
|
||||||
Rect::from_min_size(content_ui.top_left(), state.desired_size),
|
Rect::from_min_size(content_ui.left_top(), state.desired_size),
|
||||||
color::GREEN,
|
color::GREEN,
|
||||||
"desired_size",
|
"desired_size",
|
||||||
);
|
);
|
||||||
ui.ctx().debug_painter().debug_rect(
|
ui.ctx().debug_painter().debug_rect(
|
||||||
Rect::from_min_size(content_ui.top_left(), state.last_content_size),
|
Rect::from_min_size(content_ui.left_top(), state.last_content_size),
|
||||||
color::LIGHT_BLUE,
|
color::LIGHT_BLUE,
|
||||||
"last_content_size",
|
"last_content_size",
|
||||||
);
|
);
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl Prepared {
|
||||||
content_ui,
|
content_ui,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let content_size = content_ui.bounding_size();
|
let content_size = content_ui.min_size();
|
||||||
|
|
||||||
let inner_rect = Rect::from_min_size(
|
let inner_rect = Rect::from_min_size(
|
||||||
inner_rect.min,
|
inner_rect.min,
|
||||||
|
|
|
@ -602,7 +602,7 @@ fn show_title_bar(
|
||||||
collapsible: bool,
|
collapsible: bool,
|
||||||
) -> TitleBar {
|
) -> TitleBar {
|
||||||
let title_bar_and_rect = ui.horizontal(|ui| {
|
let title_bar_and_rect = ui.horizontal(|ui| {
|
||||||
ui.set_desired_height(title_label.font_height(ui.fonts(), ui.style()));
|
ui.set_min_height(title_label.font_height(ui.fonts(), ui.style()));
|
||||||
|
|
||||||
let item_spacing = ui.style().spacing.item_spacing;
|
let item_spacing = ui.style().spacing.item_spacing;
|
||||||
let button_size = ui.style().spacing.icon_width;
|
let button_size = ui.style().spacing.icon_width;
|
||||||
|
@ -625,7 +625,7 @@ fn show_title_bar(
|
||||||
if show_close_button {
|
if show_close_button {
|
||||||
// Reserve space for close button which will be added later (once we know our full width):
|
// Reserve space for close button which will be added later (once we know our full width):
|
||||||
let close_max_x = title_rect.right() + item_spacing.x + button_size + item_spacing.x;
|
let close_max_x = title_rect.right() + item_spacing.x + button_size + item_spacing.x;
|
||||||
let close_max_x = close_max_x.max(ui.rect_finite().right());
|
let close_max_x = close_max_x.max(ui.max_rect_finite().right());
|
||||||
let close_rect = Rect::from_min_size(
|
let close_rect = Rect::from_min_size(
|
||||||
pos2(
|
pos2(
|
||||||
close_max_x - button_size,
|
close_max_x - button_size,
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl Texture {
|
||||||
|
|
||||||
if ui.hovered(rect) {
|
if ui.hovered(rect) {
|
||||||
show_tooltip(ui.ctx(), |ui| {
|
show_tooltip(ui.ctx(), |ui| {
|
||||||
let pos = ui.input().mouse.pos.unwrap_or_else(|| ui.top_left());
|
let pos = ui.input().mouse.pos.unwrap_or_else(|| ui.left_top());
|
||||||
let zoom_rect = ui.allocate_space(vec2(128.0, 128.0));
|
let zoom_rect = ui.allocate_space(vec2(128.0, 128.0));
|
||||||
let u = remap_clamp(pos.x, rect.range_x(), 0.0..=tex_w);
|
let u = remap_clamp(pos.x, rect.range_x(), 0.0..=tex_w);
|
||||||
let v = remap_clamp(pos.y, rect.range_y(), 0.0..=tex_h);
|
let v = remap_clamp(pos.y, rect.range_y(), 0.0..=tex_h);
|
||||||
|
|
|
@ -52,8 +52,7 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect)
|
||||||
|
|
||||||
// Take full width and fixed height:
|
// Take full width and fixed height:
|
||||||
let height = ui.style().spacing.interact_size.y;
|
let height = ui.style().spacing.interact_size.y;
|
||||||
ui.set_desired_height(height);
|
ui.set_min_size(vec2(ui.available().width(), height));
|
||||||
ui.expand_to_size(vec2(ui.available().width(), height));
|
|
||||||
|
|
||||||
add_contents(ui)
|
add_contents(ui)
|
||||||
})
|
})
|
||||||
|
|
219
egui/src/ui.rs
219
egui/src/ui.rs
|
@ -14,21 +14,27 @@ pub struct Ui {
|
||||||
|
|
||||||
painter: Painter,
|
painter: Painter,
|
||||||
|
|
||||||
/// The `rect` represents where in screen-space the ui is
|
/// This is the minimal size of the `Ui`.
|
||||||
/// and its max size (original available_space).
|
/// When adding new widgets, this will generally expand.
|
||||||
/// Note that the size may be infinite in one or both dimensions.
|
///
|
||||||
/// The widgets will TRY to fit within the rect,
|
/// Always finite.
|
||||||
/// but may overflow (which you will see in child_bounds).
|
///
|
||||||
/// Some widgets (like separator lines) will try to fill the full desired width of the ui.
|
/// The bounding box of all child widgets, but not necessarily a tight bounding box
|
||||||
/// If the desired size is zero, it is a signal that child widgets should be as small as possible.
|
/// since `Ui` can start with a non-zero min_rect size.
|
||||||
/// If the desired size is infinite, it is a signal that child widgets should take up as much room as they want.
|
min_rect: Rect,
|
||||||
desired_rect: Rect, // TODO: rename as max_rect ?
|
|
||||||
|
|
||||||
/// Bounding box of all children.
|
/// The maximum size of this `Ui`. This is a *soft max*
|
||||||
/// This is used to see how large a ui actually
|
/// meaning new widgets will *try* not to expand beyond it,
|
||||||
/// needs to be after all children has been added.
|
/// but if they have to, they will.
|
||||||
/// You can think of this as the minimum size.
|
///
|
||||||
child_bounds: Rect, // TODO: rename as min_rect ?
|
/// Text will wrap at `max_rect.right()`.
|
||||||
|
/// Some widgets (like separator lines) will try to fill the full `max_rect` width of the ui.
|
||||||
|
///
|
||||||
|
/// `max_rect` will always be at least the size of `min_rect`.
|
||||||
|
///
|
||||||
|
/// If the `max_rect` size is zero, it is a signal that child widgets should be as small as possible.
|
||||||
|
/// If the `max_rect` size is infinite, it is a signal that child widgets should take up as much room as they want.
|
||||||
|
max_rect: Rect,
|
||||||
|
|
||||||
/// Override default style in this ui
|
/// Override default style in this ui
|
||||||
style: Style,
|
style: Style,
|
||||||
|
@ -39,7 +45,7 @@ pub struct Ui {
|
||||||
/// Progresses along self.dir.
|
/// Progresses along self.dir.
|
||||||
/// Initially set to rect.min
|
/// Initially set to rect.min
|
||||||
/// If something has already been added, this will point ot style.spacing.item_spacing beyond the latest child.
|
/// If something has already been added, this will point ot style.spacing.item_spacing beyond the latest child.
|
||||||
/// The cursor can thus be style.spacing.item_spacing pixels outside of the child_bounds.
|
/// The cursor can thus be style.spacing.item_spacing pixels outside of the min_rect.
|
||||||
cursor: Pos2, // TODO: move into Layout?
|
cursor: Pos2, // TODO: move into Layout?
|
||||||
|
|
||||||
/// How many children has been added to us?
|
/// How many children has been added to us?
|
||||||
|
@ -52,32 +58,38 @@ impl Ui {
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Creation:
|
// Creation:
|
||||||
|
|
||||||
pub fn new(ctx: Arc<Context>, layer: Layer, id: Id, rect: Rect) -> Self {
|
pub fn new(ctx: Arc<Context>, layer: Layer, id: Id, max_rect: Rect) -> Self {
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let clip_rect = rect.expand(style.visuals.clip_rect_margin);
|
let clip_rect = max_rect.expand(style.visuals.clip_rect_margin);
|
||||||
|
let layout = Layout::default();
|
||||||
|
let cursor = layout.initial_cursor(max_rect);
|
||||||
|
let min_size = Vec2::zero(); // TODO: From Style
|
||||||
|
let min_rect = layout.rect_from_cursor_size(cursor, min_size);
|
||||||
Ui {
|
Ui {
|
||||||
id,
|
id,
|
||||||
painter: Painter::new(ctx, layer, clip_rect),
|
painter: Painter::new(ctx, layer, clip_rect),
|
||||||
desired_rect: rect,
|
min_rect,
|
||||||
child_bounds: Rect::from_min_size(rect.min, Vec2::zero()), // TODO: Rect::nothing() ?
|
max_rect,
|
||||||
style,
|
style,
|
||||||
layout: Default::default(),
|
layout,
|
||||||
cursor: rect.min,
|
cursor,
|
||||||
child_count: 0,
|
child_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child_ui(&mut self, child_rect: Rect, layout: Layout) -> Self {
|
pub fn child_ui(&mut self, max_rect: Rect, layout: Layout) -> Self {
|
||||||
let id = self.make_position_id(); // TODO: is this a good idea?
|
let id = self.make_position_id(); // TODO: is this a good idea?
|
||||||
self.child_count += 1;
|
self.child_count += 1;
|
||||||
|
|
||||||
let cursor = layout.initial_cursor(child_rect);
|
let cursor = layout.initial_cursor(max_rect);
|
||||||
|
let min_size = Vec2::zero(); // TODO: From Style
|
||||||
|
let min_rect = layout.rect_from_cursor_size(cursor, min_size);
|
||||||
|
|
||||||
Ui {
|
Ui {
|
||||||
id,
|
id,
|
||||||
painter: self.painter.clone(),
|
painter: self.painter.clone(),
|
||||||
desired_rect: child_rect,
|
min_rect,
|
||||||
child_bounds: Rect::from_min_size(child_rect.min, Vec2::zero()), // TODO: Rect::nothing() ?
|
max_rect,
|
||||||
style: self.style().clone(),
|
style: self.style().clone(),
|
||||||
layout,
|
layout,
|
||||||
cursor,
|
cursor,
|
||||||
|
@ -115,6 +127,10 @@ impl Ui {
|
||||||
&self.painter
|
&self.painter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layout(&self) -> &Layout {
|
||||||
|
&self.layout
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a painter for a sub-region of this Ui.
|
/// Create a painter for a sub-region of this Ui.
|
||||||
///
|
///
|
||||||
/// The clip-rect of the returned `Painter` will be the intersection
|
/// The clip-rect of the returned `Painter` will be the intersection
|
||||||
|
@ -155,103 +171,129 @@ impl Ui {
|
||||||
pub fn set_clip_rect(&mut self, clip_rect: Rect) {
|
pub fn set_clip_rect(&mut self, clip_rect: Rect) {
|
||||||
self.painter.set_clip_rect(clip_rect);
|
self.painter.set_clip_rect(clip_rect);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// ## Sizes etc
|
||||||
|
impl Ui {
|
||||||
/// Screen-space position of this Ui.
|
/// Screen-space position of this Ui.
|
||||||
/// This may have moved from its original if a child overflowed to the left or up (rare).
|
/// This may have moved from its original if a child overflowed to the left or up (rare).
|
||||||
pub fn top_left(&self) -> Pos2 {
|
pub fn left_top(&self) -> Pos2 {
|
||||||
// If a child doesn't fit in desired_rect, we have effectively expanded:
|
// If a child doesn't fit in max_rect, we have effectively expanded:
|
||||||
self.desired_rect.min.min(self.child_bounds.min)
|
self.max_rect.min
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Screen-space position of the current bottom right corner of this Ui.
|
/// Screen-space position of the current bottom right corner of this Ui.
|
||||||
/// This may move when we add children that overflow our desired rectangle bounds.
|
/// This may move when we add children that overflow our desired rectangle bounds.
|
||||||
/// This position may be at infinity if the desired rect is infinite,
|
/// This position may be at infinity if the desired rect is infinite,
|
||||||
/// which happens when a parent widget says "be as big as you want to be".
|
/// which happens when a parent widget says "be as big as you want to be".
|
||||||
pub fn bottom_right(&self) -> Pos2 {
|
pub fn right_bottom(&self) -> Pos2 {
|
||||||
// If a child doesn't fit in desired_rect, we have effectively expanded:
|
// If a child doesn't fit in max_rect, we have effectively expanded:
|
||||||
self.desired_rect.max.max(self.child_bounds.max)
|
self.max_rect.max
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Position and current size of the ui.
|
/// Bounding box of all contained children
|
||||||
/// The size is the maximum of the original (minimum/desired) size and
|
pub fn min_rect(&self) -> Rect {
|
||||||
/// the size of the contained children.
|
self.min_rect
|
||||||
pub fn rect(&self) -> Rect {
|
|
||||||
Rect::from_min_max(self.top_left(), self.bottom_right())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is like `rect()`, but will never be infinite.
|
/// This is the soft max size of the Ui.
|
||||||
|
pub fn max_rect(&self) -> Rect {
|
||||||
|
self.max_rect
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used for animation, kind of hacky
|
||||||
|
pub(crate) fn force_set_min_rect(&mut self, min_rect: Rect) {
|
||||||
|
self.min_rect = min_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is like `max_rect()`, but will never be infinite.
|
||||||
/// If the desired rect is infinite ("be as big as you want")
|
/// If the desired rect is infinite ("be as big as you want")
|
||||||
/// this will be bounded by child bounds.
|
/// this will be bounded by min_rect instead.
|
||||||
pub fn rect_finite(&self) -> Rect {
|
pub fn max_rect_finite(&self) -> Rect {
|
||||||
let mut bottom_right = self.child_bounds.max;
|
let mut right_bottom = self.min_rect.max;
|
||||||
if self.desired_rect.max.x.is_finite() {
|
if self.max_rect.max.x.is_finite() {
|
||||||
bottom_right.x = bottom_right.x.max(self.desired_rect.max.x);
|
right_bottom.x = right_bottom.x.max(self.max_rect.max.x);
|
||||||
}
|
}
|
||||||
if self.desired_rect.max.y.is_finite() {
|
if self.max_rect.max.y.is_finite() {
|
||||||
bottom_right.y = bottom_right.y.max(self.desired_rect.max.y);
|
right_bottom.y = right_bottom.y.max(self.max_rect.max.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect::from_min_max(self.top_left(), bottom_right)
|
Rect::from_min_max(self.left_top(), right_bottom)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_min_width(&mut self, width: f32) {
|
|
||||||
self.child_bounds.max.x = self.child_bounds.max.x.max(self.child_bounds.min.x + width);
|
|
||||||
self.desired_rect.max.x = self.desired_rect.max.x.max(self.desired_rect.min.x + width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the width of the ui.
|
/// Set the width of the ui.
|
||||||
/// You won't be able to shrink it beyond its current child bounds.
|
/// You won't be able to shrink it beyond its current child bounds.
|
||||||
pub fn set_desired_width(&mut self, width: f32) {
|
pub fn set_max_width(&mut self, width: f32) {
|
||||||
let min_width = self.child_bounds.max.x - self.top_left().x;
|
let min_width = self.min_rect.max.x - self.left_top().x;
|
||||||
let width = width.at_least(min_width);
|
let width = width.at_least(min_width);
|
||||||
self.desired_rect.max.x = self.top_left().x + width;
|
self.max_rect.max.x = self.left_top().x + width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the height of the ui.
|
/// Set the height of the ui.
|
||||||
/// You won't be able to shrink it beyond its current child bounds.
|
/// You won't be able to shrink it beyond its current child bounds.
|
||||||
pub fn set_desired_height(&mut self, height: f32) {
|
pub fn set_max_height(&mut self, height: f32) {
|
||||||
let min_height = self.child_bounds.max.y - self.top_left().y;
|
let min_height = self.min_rect.max.y - self.left_top().y;
|
||||||
let height = height.at_least(min_height);
|
let height = height.at_least(min_height);
|
||||||
self.desired_rect.max.y = self.top_left().y + height;
|
self.max_rect.max.y = self.left_top().y + height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_min_size(&mut self, size: Vec2) {
|
||||||
|
self.set_min_width(size.x);
|
||||||
|
self.set_min_height(size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_min_width(&mut self, width: f32) {
|
||||||
|
if self.layout.dir() == Direction::Horizontal && self.layout.is_reversed() {
|
||||||
|
debug_assert_eq!(self.min_rect.max.x, self.max_rect.max.x);
|
||||||
|
self.min_rect.min.x = self.min_rect.min.x.min(self.min_rect.max.x - width);
|
||||||
|
self.max_rect.min.x = self.max_rect.min.x.min(self.max_rect.max.x - width);
|
||||||
|
} else {
|
||||||
|
debug_assert_eq!(self.min_rect.min.x, self.max_rect.min.x);
|
||||||
|
self.min_rect.max.x = self.min_rect.max.x.max(self.min_rect.min.x + width);
|
||||||
|
self.max_rect.max.x = self.max_rect.max.x.max(self.max_rect.min.x + width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_min_height(&mut self, height: f32) {
|
||||||
|
if self.layout.dir() == Direction::Vertical && self.layout.is_reversed() {
|
||||||
|
debug_assert_eq!(self.min_rect.max.y, self.max_rect.max.y);
|
||||||
|
self.min_rect.min.y = self.min_rect.min.y.min(self.min_rect.max.y - height);
|
||||||
|
self.max_rect.min.y = self.max_rect.min.y.min(self.max_rect.max.y - height);
|
||||||
|
} else {
|
||||||
|
debug_assert_eq!(self.min_rect.min.y, self.max_rect.min.y);
|
||||||
|
self.min_rect.max.y = self.min_rect.max.y.max(self.min_rect.min.y + height);
|
||||||
|
self.max_rect.max.y = self.max_rect.max.y.max(self.max_rect.min.y + height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper: shrinks the max/desired width to the current width,
|
/// Helper: shrinks the max/desired width to the current width,
|
||||||
/// so further widgets will try not to be wider than previous widgets.
|
/// so further widgets will try not to be wider than previous widgets.
|
||||||
/// Useful for normal vertical layouts.
|
/// Useful for normal vertical layouts.
|
||||||
pub fn shrink_width_to_current(&mut self) {
|
pub fn shrink_width_to_current(&mut self) {
|
||||||
self.set_desired_width(self.child_bounds().width())
|
self.set_max_width(self.min_rect().width())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper: shrinks the max/desired height to the current height,
|
/// Helper: shrinks the max/desired height to the current height,
|
||||||
/// so further widgets will try not to be wider than previous widgets.
|
/// so further widgets will try not to be wider than previous widgets.
|
||||||
pub fn shrink_height_to_current(&mut self) {
|
pub fn shrink_height_to_current(&mut self) {
|
||||||
self.set_desired_height(self.child_bounds().height())
|
self.set_min_height(self.min_rect().height())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Size of content
|
/// Size of content
|
||||||
pub fn bounding_size(&self) -> Vec2 {
|
pub fn min_size(&self) -> Vec2 {
|
||||||
self.child_bounds.size()
|
self.min_rect.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand the bounding rect of this ui to include a child at the given rect.
|
/// Expand the bounding rect of this ui to include a child at the given rect.
|
||||||
pub fn expand_to_include_child(&mut self, rect: Rect) {
|
pub fn expand_to_include_child(&mut self, rect: Rect) {
|
||||||
self.child_bounds.extend_with(rect.min);
|
self.min_rect.extend_with(rect.min);
|
||||||
self.child_bounds.extend_with(rect.max);
|
self.min_rect.extend_with(rect.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_to_size(&mut self, size: Vec2) {
|
pub fn expand_to_size(&mut self, size: Vec2) {
|
||||||
self.child_bounds.extend_with(self.top_left() + size);
|
self.min_rect.extend_with(self.left_top() + size);
|
||||||
}
|
|
||||||
|
|
||||||
/// Bounding box of all contained children
|
|
||||||
pub fn child_bounds(&self) -> Rect {
|
|
||||||
self.child_bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn force_set_child_bounds(&mut self, child_bounds: Rect) {
|
|
||||||
self.child_bounds = child_bounds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -264,18 +306,14 @@ impl Ui {
|
||||||
/// An infinite rectangle should be interpreted as "as much as you want".
|
/// An infinite rectangle should be interpreted as "as much as you want".
|
||||||
/// In most layouts the next widget will be put in the top left corner of this `Rect`.
|
/// In most layouts the next widget will be put in the top left corner of this `Rect`.
|
||||||
pub fn available(&self) -> Rect {
|
pub fn available(&self) -> Rect {
|
||||||
self.layout.available(self.cursor, self.rect())
|
self.layout.available(self.cursor, self.max_rect())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is like `available()`, but will never be infinite.
|
/// This is like `available()`, but will never be infinite.
|
||||||
/// Use this for components that want to grow without bounds (but shouldn't).
|
/// Use this for components that want to grow without bounds (but shouldn't).
|
||||||
/// In most layouts the next widget will be put in the top left corner of this `Rect`.
|
/// In most layouts the next widget will be put in the top left corner of this `Rect`.
|
||||||
pub fn available_finite(&self) -> Rect {
|
pub fn available_finite(&self) -> Rect {
|
||||||
self.layout.available(self.cursor, self.rect_finite())
|
self.layout.available(self.cursor, self.max_rect_finite())
|
||||||
}
|
|
||||||
|
|
||||||
pub fn layout(&self) -> &Layout {
|
|
||||||
&self.layout
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -415,7 +453,8 @@ impl Ui {
|
||||||
let child_rect =
|
let child_rect =
|
||||||
self.layout
|
self.layout
|
||||||
.allocate_space(&mut self.cursor, &self.style, available_size, child_size);
|
.allocate_space(&mut self.cursor, &self.style, available_size, child_size);
|
||||||
self.child_bounds = self.child_bounds.union(child_rect);
|
self.min_rect = self.min_rect.union(child_rect);
|
||||||
|
self.max_rect = self.max_rect.union(child_rect);
|
||||||
self.child_count += 1;
|
self.child_count += 1;
|
||||||
child_rect
|
child_rect
|
||||||
}
|
}
|
||||||
|
@ -586,14 +625,14 @@ impl Ui {
|
||||||
/// Actual size may be much smaller if `available_size()` is not enough.
|
/// Actual size may be much smaller if `available_size()` is not enough.
|
||||||
/// Set `size` to `Vec::infinity()` to get as much space as possible.
|
/// Set `size` to `Vec::infinity()` to get as much space as possible.
|
||||||
/// Just because you ask for a lot of space does not mean you have to use it!
|
/// Just because you ask for a lot of space does not mean you have to use it!
|
||||||
/// After `add_contents` is called the contents of `bounding_size`
|
/// After `add_contents` is called the contents of `min_size`
|
||||||
/// will decide how much space will be used in the parent ui.
|
/// will decide how much space will be used in the parent ui.
|
||||||
pub fn add_custom_contents(&mut self, size: Vec2, add_contents: impl FnOnce(&mut Ui)) -> Rect {
|
pub fn add_custom_contents(&mut self, size: Vec2, add_contents: impl FnOnce(&mut Ui)) -> Rect {
|
||||||
let size = size.at_most(self.available().size());
|
let size = size.at_most(self.available().size());
|
||||||
let child_rect = self.layout.rect_from_cursor_size(self.cursor, size);
|
let child_rect = self.layout.rect_from_cursor_size(self.cursor, size);
|
||||||
let mut child_ui = self.child_ui(child_rect, self.layout);
|
let mut child_ui = self.child_ui(child_rect, self.layout);
|
||||||
add_contents(&mut child_ui);
|
add_contents(&mut child_ui);
|
||||||
self.allocate_space(child_ui.bounding_size())
|
self.allocate_space(child_ui.min_size())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a child ui. You can use this to temporarily change the Style of a sub-region, for instance.
|
/// Create a child ui. You can use this to temporarily change the Style of a sub-region, for instance.
|
||||||
|
@ -601,7 +640,7 @@ impl Ui {
|
||||||
let child_rect = self.available();
|
let child_rect = self.available();
|
||||||
let mut child_ui = self.child_ui(child_rect, self.layout);
|
let mut child_ui = self.child_ui(child_rect, self.layout);
|
||||||
let r = add_contents(&mut child_ui);
|
let r = add_contents(&mut child_ui);
|
||||||
let size = child_ui.bounding_size();
|
let size = child_ui.min_size();
|
||||||
(r, self.allocate_space(size))
|
(r, self.allocate_space(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,13 +655,13 @@ impl Ui {
|
||||||
"You can only indent vertical layouts"
|
"You can only indent vertical layouts"
|
||||||
);
|
);
|
||||||
let indent = vec2(self.style().spacing.indent, 0.0);
|
let indent = vec2(self.style().spacing.indent, 0.0);
|
||||||
let child_rect = Rect::from_min_max(self.cursor + indent, self.bottom_right()); // TODO: wrong for reversed layouts
|
let child_rect = Rect::from_min_max(self.cursor + indent, self.right_bottom()); // TODO: wrong for reversed layouts
|
||||||
let mut child_ui = Ui {
|
let mut child_ui = Ui {
|
||||||
id: self.id.with(id_source),
|
id: self.id.with(id_source),
|
||||||
..self.child_ui(child_rect, self.layout)
|
..self.child_ui(child_rect, self.layout)
|
||||||
};
|
};
|
||||||
let ret = add_contents(&mut child_ui);
|
let ret = add_contents(&mut child_ui);
|
||||||
let size = child_ui.bounding_size();
|
let size = child_ui.min_size();
|
||||||
|
|
||||||
// draw a grey line on the left to mark the indented section
|
// draw a grey line on the left to mark the indented section
|
||||||
let line_start = child_rect.min - indent * 0.5;
|
let line_start = child_rect.min - indent * 0.5;
|
||||||
|
@ -698,7 +737,7 @@ impl Ui {
|
||||||
let child_rect = self.layout.rect_from_cursor_size(self.cursor, initial_size);
|
let child_rect = self.layout.rect_from_cursor_size(self.cursor, initial_size);
|
||||||
let mut child_ui = self.child_ui(child_rect, layout);
|
let mut child_ui = self.child_ui(child_rect, layout);
|
||||||
let ret = add_contents(&mut child_ui);
|
let ret = add_contents(&mut child_ui);
|
||||||
let size = child_ui.bounding_size();
|
let size = child_ui.min_size();
|
||||||
let rect = self.allocate_space(size);
|
let rect = self.allocate_space(size);
|
||||||
(ret, rect)
|
(ret, rect)
|
||||||
}
|
}
|
||||||
|
@ -710,7 +749,7 @@ impl Ui {
|
||||||
) -> (R, Rect) {
|
) -> (R, Rect) {
|
||||||
let mut child_ui = self.child_ui(self.available(), layout);
|
let mut child_ui = self.child_ui(self.available(), layout);
|
||||||
let ret = add_contents(&mut child_ui);
|
let ret = add_contents(&mut child_ui);
|
||||||
let size = child_ui.bounding_size();
|
let size = child_ui.min_size();
|
||||||
let rect = self.allocate_space(size);
|
let rect = self.allocate_space(size);
|
||||||
(ret, rect)
|
(ret, rect)
|
||||||
}
|
}
|
||||||
|
@ -736,7 +775,7 @@ impl Ui {
|
||||||
.map(|col_idx| {
|
.map(|col_idx| {
|
||||||
let pos = self.cursor + vec2((col_idx as f32) * (column_width + spacing), 0.0);
|
let pos = self.cursor + vec2((col_idx as f32) * (column_width + spacing), 0.0);
|
||||||
let child_rect =
|
let child_rect =
|
||||||
Rect::from_min_max(pos, pos2(pos.x + column_width, self.bottom_right().y));
|
Rect::from_min_max(pos, pos2(pos.x + column_width, self.right_bottom().y));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: self.make_child_id(&("column", col_idx)),
|
id: self.make_child_id(&("column", col_idx)),
|
||||||
|
@ -749,12 +788,12 @@ impl Ui {
|
||||||
|
|
||||||
let mut sum_width = total_spacing;
|
let mut sum_width = total_spacing;
|
||||||
for column in &columns {
|
for column in &columns {
|
||||||
sum_width += column.child_bounds.width();
|
sum_width += column.min_rect.width();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut max_height = 0.0;
|
let mut max_height = 0.0;
|
||||||
for ui in columns {
|
for ui in columns {
|
||||||
let size = ui.bounding_size();
|
let size = ui.min_size();
|
||||||
max_height = size.y.max(max_height);
|
max_height = size.y.max(max_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue