1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 05:10:03 -04:00

Add ui.allocate_at_least and ui.allocate_exact_size

This commit is contained in:
Emil Ernerfeldt
2021-01-06 11:03:29 +01:00
parent f68c30e0c7
commit b4871e2aef
15 changed files with 74 additions and 72 deletions

View File

@@ -7,6 +7,7 @@ use crate::{
impl Texture {
pub fn ui(&self, ui: &mut Ui) {
// Show font texture in demo Ui
ui.label(format!(
"Texture size: {} x {} (hover to zoom)",
self.width, self.height
@@ -18,8 +19,7 @@ impl Texture {
if size.x > ui.available_width() {
size *= ui.available_width() / size.x;
}
let response = ui.allocate_response(size, Sense::hover());
let rect = response.rect;
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let mut triangles = Triangles::default();
triangles.add_rect_with_uv(
rect,

View File

@@ -468,6 +468,27 @@ impl Ui {
self.interact(rect, id, sense)
}
/// Returns a `Rect` with exactly what you asked for.
///
/// The response rect will be larger if this is part of a justified layout or similar.
/// This means that iof this is a narrow widget in a wide justified layout, then
/// the widget will react to interactions outside the returned `Rect`.
pub fn allocate_exact_size(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
let response = self.allocate_response(desired_size, sense);
let rect = self
.layout()
.align_size_within_rect(desired_size, response.rect);
(rect, response)
}
/// Allocate at least as much space as needed, and interact with that rect.
///
/// The returned `Rect` will be the same size as `Response::rect`.
pub fn allocate_at_least(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
let response = self.allocate_response(desired_size, sense);
(response.rect, response)
}
/// Reserve this much space and move the cursor.
/// Returns where to put the widget.
///

View File

@@ -106,23 +106,19 @@ impl Widget for Button {
desired_size.y = desired_size.y.at_least(ui.style().spacing.interact_size.y);
}
let response = ui.allocate_response(desired_size, sense);
let (rect, response) = ui.allocate_at_least(desired_size, sense);
if ui.clip_rect().intersects(response.rect) {
if ui.clip_rect().intersects(rect) {
let visuals = ui.style().interact(&response);
let text_cursor = ui
.layout()
.align_size_within_rect(galley.size, response.rect.shrink2(button_padding))
.align_size_within_rect(galley.size, rect.shrink2(button_padding))
.min;
if frame {
let fill = fill.unwrap_or(visuals.bg_fill);
ui.painter().rect(
response.rect,
visuals.corner_radius,
fill,
visuals.bg_stroke,
);
ui.painter()
.rect(rect, visuals.corner_radius, fill, visuals.bg_stroke);
}
let text_color = text_color
@@ -189,10 +185,7 @@ impl<'a> Widget for Checkbox<'a> {
let mut desired_size = total_extra + galley.size;
desired_size = desired_size.at_least(spacing.interact_size);
desired_size.y = desired_size.y.max(icon_width);
let response = ui.allocate_response(desired_size, Sense::click());
let rect = ui
.layout()
.align_size_within_rect(desired_size, response.rect);
let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
if response.clicked {
*checked = !*checked;
}
@@ -283,10 +276,7 @@ impl Widget for RadioButton {
let mut desired_size = total_extra + galley.size;
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
desired_size.y = desired_size.y.max(icon_width);
let response = ui.allocate_response(desired_size, Sense::click());
let rect = ui
.layout()
.align_size_within_rect(desired_size, response.rect);
let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
let text_cursor = pos2(
rect.min.x + button_padding.x + icon_width + icon_spacing,
@@ -390,28 +380,27 @@ impl Widget for ImageButton {
let button_padding = ui.style().spacing.button_padding;
let desired_size = image.desired_size() + 2.0 * button_padding;
let response = ui.allocate_response(desired_size, sense);
let (rect, response) = ui.allocate_at_least(desired_size, sense);
if ui.clip_rect().intersects(response.rect) {
if ui.clip_rect().intersects(rect) {
let visuals = ui.style().interact(&response);
if selected {
let selection = ui.style().visuals.selection;
ui.painter()
.rect(response.rect, 0.0, selection.bg_fill, selection.stroke);
.rect(rect, 0.0, selection.bg_fill, selection.stroke);
} else if frame {
ui.painter().rect(
response.rect,
rect,
visuals.corner_radius,
visuals.bg_fill,
visuals.bg_stroke,
);
}
let image_rect = ui.layout().align_size_within_rect(
image.desired_size(),
response.rect.shrink2(button_padding),
);
let image_rect = ui
.layout()
.align_size_within_rect(image.desired_size(), rect.shrink2(button_padding));
image.paint_at(ui, image_rect);
}

View File

@@ -45,10 +45,10 @@ pub fn show_color(ui: &mut Ui, color: impl Into<Color32>, desired_size: Vec2) ->
}
fn show_srgba(ui: &mut Ui, srgba: Color32, desired_size: Vec2) -> Response {
let response = ui.allocate_response(desired_size, Sense::hover());
background_checkers(ui.painter(), response.rect);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::hover());
background_checkers(ui.painter(), rect);
ui.painter().add(PaintCmd::Rect {
rect: response.rect,
rect,
corner_radius: 2.0,
fill: srgba,
stroke: Stroke::new(3.0, srgba.to_opaque()),
@@ -58,11 +58,11 @@ fn show_srgba(ui: &mut Ui, srgba: Color32, desired_size: Vec2) -> Response {
fn color_button(ui: &mut Ui, color: Color32) -> Response {
let desired_size = ui.style().spacing.interact_size;
let response = ui.allocate_response(desired_size, Sense::click());
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
let visuals = ui.style().interact(&response);
background_checkers(ui.painter(), response.rect);
background_checkers(ui.painter(), rect);
ui.painter().add(PaintCmd::Rect {
rect: response.rect,
rect,
corner_radius: visuals.corner_radius.at_most(2.0),
fill: color,
stroke: visuals.fg_stroke,
@@ -77,8 +77,7 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Color
ui.style().spacing.slider_width,
ui.style().spacing.interact_size.y * 2.0,
);
let response = ui.allocate_response(desired_size, Sense::click_and_drag());
let rect = response.rect;
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click_and_drag());
if response.active {
if let Some(mpos) = ui.input().mouse.pos {
@@ -135,8 +134,7 @@ fn color_slider_2d(
color_at: impl Fn(f32, f32) -> Color32,
) -> Response {
let desired_size = Vec2::splat(ui.style().spacing.slider_width);
let response = ui.allocate_response(desired_size, Sense::click_and_drag());
let rect = response.rect;
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click_and_drag());
if response.active {
if let Some(mpos) = ui.input().mouse.pos {

View File

@@ -46,7 +46,7 @@ impl Widget for Hyperlink {
let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style);
let font = &ui.fonts()[text_style];
let galley = font.layout_multiline(text, ui.available_width());
let response = ui.allocate_response(galley.size, Sense::click());
let (rect, response) = ui.allocate_exact_size(galley.size, Sense::click());
if response.hovered {
ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
@@ -61,7 +61,7 @@ impl Widget for Hyperlink {
if response.hovered {
// Underline:
for line in &galley.rows {
let pos = response.rect.min;
let pos = rect.min;
let y = pos.y + line.y_max;
let y = ui.painter().round_to_pixel(y);
let min_x = pos.x + line.min_x();
@@ -73,8 +73,7 @@ impl Widget for Hyperlink {
}
}
ui.painter()
.galley(response.rect.min, galley, text_style, color);
ui.painter().galley(rect.min, galley, text_style, color);
response.on_hover_text(url)
}

View File

@@ -73,8 +73,8 @@ impl Image {
impl Widget for Image {
fn ui(self, ui: &mut Ui) -> Response {
let response = ui.allocate_response(self.desired_size, Sense::hover());
self.paint_at(ui, response.rect);
let (rect, response) = ui.allocate_at_least(self.desired_size, Sense::hover());
self.paint_at(ui, rect);
response
}
}

View File

@@ -157,10 +157,7 @@ impl Widget for Label {
total_response
} else {
let galley = self.layout(ui);
let response = ui.allocate_response(galley.size, Sense::click());
let rect = ui
.layout()
.align_size_within_rect(galley.size, response.rect);
let (rect, response) = ui.allocate_exact_size(galley.size, Sense::click());
self.paint_galley(ui, rect.min, galley);
response
}

View File

@@ -33,11 +33,11 @@ impl Widget for SelectableLabel {
let mut desired_size = total_extra + galley.size;
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
let response = ui.allocate_response(desired_size, Sense::click());
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
let text_cursor = pos2(
response.rect.min.x + button_padding.x,
response.rect.center().y - 0.5 * galley.size.y,
rect.min.x + button_padding.x,
rect.center().y - 0.5 * galley.size.y,
);
let visuals = ui.style().interact(&response);
@@ -48,8 +48,7 @@ impl Widget for SelectableLabel {
} else {
Default::default()
};
ui.painter()
.rect(response.rect, 0.0, bg_fill, visuals.bg_stroke);
ui.painter().rect(rect, 0.0, bg_fill, visuals.bg_stroke);
}
let text_color = ui

View File

@@ -30,8 +30,7 @@ impl Widget for Separator {
vec2(available_space.x, spacing)
};
let response = ui.allocate_response(size, Sense::hover());
let rect = response.rect;
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()),