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:
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()),
|
||||
|
||||
Reference in New Issue
Block a user