Add ui.allocate_response(…): allocate space and check for interactions
This commit is contained in:
parent
66ae0ed7b9
commit
48dfcde65f
19 changed files with 109 additions and 92 deletions
|
@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
* You can now control the minimum and maixumum number of decimals to show in a `Slider` or `DragValue`.
|
* You can now control the minimum and maixumum number of decimals to show in a `Slider` or `DragValue`.
|
||||||
* Add `egui::math::Rot2`: rotation helper.
|
* Add `egui::math::Rot2`: rotation helper.
|
||||||
* `Response` now contains the `Id` of the widget it pertains to.
|
* `Response` now contains the `Id` of the widget it pertains to.
|
||||||
|
* `ui.allocate_response` that allocated space and checks for interactions.
|
||||||
|
|
||||||
### Changed 🔧
|
### Changed 🔧
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ fn button_frame(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.allocate_space(outer_rect.size());
|
ui.advance_cursor_after_rect(outer_rect);
|
||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ impl Prepared {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.allocate_space(outer_rect.size());
|
ui.advance_cursor_after_rect(outer_rect);
|
||||||
|
|
||||||
outer_rect
|
outer_rect
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,18 +265,19 @@ impl Resize {
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
if self.with_stroke || self.resizable {
|
let size = if self.with_stroke || self.resizable {
|
||||||
// We show how large we are,
|
// We show how large we are,
|
||||||
// so we must follow the contents:
|
// so we must follow the contents:
|
||||||
|
|
||||||
state.desired_size = state.desired_size.max(state.last_content_size);
|
state.desired_size = state.desired_size.max(state.last_content_size);
|
||||||
|
|
||||||
// We are as large as we look
|
// We are as large as we look
|
||||||
ui.allocate_space(state.desired_size);
|
state.desired_size
|
||||||
} else {
|
} else {
|
||||||
// Probably a window.
|
// Probably a window.
|
||||||
ui.allocate_space(state.last_content_size);
|
state.last_content_size
|
||||||
}
|
};
|
||||||
|
ui.advance_cursor_after_rect(Rect::from_min_size(content_ui.min_rect().min, size));
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
|
|
|
@ -291,7 +291,7 @@ impl Prepared {
|
||||||
outer_rect.size().x,
|
outer_rect.size().x,
|
||||||
outer_rect.size().y.min(content_size.y), // shrink if content is so small that we don't need scroll bars
|
outer_rect.size().y.min(content_size.y), // shrink if content is so small that we don't need scroll bars
|
||||||
);
|
);
|
||||||
ui.allocate_space(size);
|
ui.advance_cursor_after_rect(Rect::from_min_size(outer_rect.min, size));
|
||||||
|
|
||||||
if show_scroll_this_frame != state.show_scroll {
|
if show_scroll_this_frame != state.show_scroll {
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
|
|
|
@ -225,6 +225,8 @@ impl<'open> Window<'open> {
|
||||||
|
|
||||||
let mut area = area.begin(ctx);
|
let mut area = area.begin(ctx);
|
||||||
|
|
||||||
|
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
||||||
|
|
||||||
// First interact (move etc) to avoid frame delay:
|
// First interact (move etc) to avoid frame delay:
|
||||||
let last_frame_outer_rect = area.state().rect();
|
let last_frame_outer_rect = area.state().rect();
|
||||||
let interaction = if possible.movable || possible.resizable {
|
let interaction = if possible.movable || possible.resizable {
|
||||||
|
@ -238,8 +240,7 @@ impl<'open> Window<'open> {
|
||||||
.and_then(|window_interaction| {
|
.and_then(|window_interaction| {
|
||||||
// Calculate roughly how much larger the window size is compared to the inner rect
|
// Calculate roughly how much larger the window size is compared to the inner rect
|
||||||
let title_bar_height = if with_title_bar {
|
let title_bar_height = if with_title_bar {
|
||||||
title_label.font_height(ctx.fonts(), &ctx.style())
|
title_label.font_height(ctx.fonts(), &ctx.style()) + title_content_spacing
|
||||||
+ 1.0 * ctx.style().spacing.item_spacing.y // this could be better
|
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
@ -292,8 +293,7 @@ impl<'open> Window<'open> {
|
||||||
.add_contents(&mut frame.content_ui, collapsing_id, |ui| {
|
.add_contents(&mut frame.content_ui, collapsing_id, |ui| {
|
||||||
resize.show(ui, |ui| {
|
resize.show(ui, |ui| {
|
||||||
if title_bar.is_some() {
|
if title_bar.is_some() {
|
||||||
// Add some spacing between title and content:
|
ui.advance_cursor(title_content_spacing);
|
||||||
ui.allocate_space(ui.style().spacing.item_spacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(scroll) = scroll {
|
if let Some(scroll) = scroll {
|
||||||
|
|
|
@ -109,8 +109,9 @@ impl FrameHistory {
|
||||||
|
|
||||||
// TODO: we should not use `slider_width` as default graph width.
|
// TODO: we should not use `slider_width` as default graph width.
|
||||||
let height = ui.style().spacing.slider_width;
|
let height = ui.style().spacing.slider_width;
|
||||||
let (id, rect) = ui.allocate_space(vec2(ui.available_size_before_wrap_finite().x, height));
|
let size = vec2(ui.available_size_before_wrap_finite().x, height);
|
||||||
let response = ui.interact(rect, id, Sense::hover());
|
let response = ui.allocate_response(size, Sense::hover());
|
||||||
|
let rect = response.rect;
|
||||||
let style = ui.style().noninteractive();
|
let style = ui.style().noninteractive();
|
||||||
|
|
||||||
let mut cmds = vec![PaintCmd::Rect {
|
let mut cmds = vec![PaintCmd::Rect {
|
||||||
|
|
|
@ -267,11 +267,10 @@ impl ColorTest {
|
||||||
|
|
||||||
fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response {
|
fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response {
|
||||||
use crate::paint::*;
|
use crate::paint::*;
|
||||||
let (id, rect) = ui.allocate_space(GRADIENT_SIZE);
|
let response = ui.allocate_response(GRADIENT_SIZE, Sense::hover());
|
||||||
let response = ui.interact(rect, id, Sense::hover());
|
|
||||||
if bg_fill != Default::default() {
|
if bg_fill != Default::default() {
|
||||||
let mut triangles = Triangles::default();
|
let mut triangles = Triangles::default();
|
||||||
triangles.add_colored_rect(rect, bg_fill);
|
triangles.add_colored_rect(response.rect, bg_fill);
|
||||||
ui.painter().add(PaintCmd::triangles(triangles));
|
ui.painter().add(PaintCmd::triangles(triangles));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -280,9 +279,9 @@ fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response
|
||||||
let mut triangles = Triangles::default();
|
let mut triangles = Triangles::default();
|
||||||
for (i, &color) in gradient.0.iter().enumerate() {
|
for (i, &color) in gradient.0.iter().enumerate() {
|
||||||
let t = i as f32 / (n as f32 - 1.0);
|
let t = i as f32 / (n as f32 - 1.0);
|
||||||
let x = lerp(rect.x_range(), t);
|
let x = lerp(response.rect.x_range(), t);
|
||||||
triangles.colored_vertex(pos2(x, rect.top()), color);
|
triangles.colored_vertex(pos2(x, response.rect.top()), color);
|
||||||
triangles.colored_vertex(pos2(x, rect.bottom()), color);
|
triangles.colored_vertex(pos2(x, response.rect.bottom()), color);
|
||||||
if i < n - 1 {
|
if i < n - 1 {
|
||||||
let i = i as u32;
|
let i = i as u32;
|
||||||
triangles.add_triangle(2 * i, 2 * i + 1, 2 * i + 2);
|
triangles.add_triangle(2 * i, 2 * i + 1, 2 * i + 2);
|
||||||
|
|
|
@ -87,10 +87,10 @@ impl DemoWindow {
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("You can pretty easily paint your own small icons:");
|
ui.label("You can pretty easily paint your own small icons:");
|
||||||
let (_id, rect) = ui.allocate_space(Vec2::splat(16.0));
|
let response = ui.allocate_response(Vec2::splat(16.0), Sense::hover());
|
||||||
let painter = ui.painter();
|
let painter = ui.painter();
|
||||||
let c = rect.center();
|
let c = response.rect.center();
|
||||||
let r = rect.width() / 2.0 - 1.0;
|
let r = response.rect.width() / 2.0 - 1.0;
|
||||||
let color = Srgba::gray(128);
|
let color = Srgba::gray(128);
|
||||||
let stroke = Stroke::new(1.0, color);
|
let stroke = Stroke::new(1.0, color);
|
||||||
painter.circle_stroke(c, r, stroke);
|
painter.circle_stroke(c, r, stroke);
|
||||||
|
@ -206,9 +206,9 @@ impl BoxPainting {
|
||||||
|
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
for _ in 0..self.num_boxes {
|
for _ in 0..self.num_boxes {
|
||||||
let (_id, rect) = ui.allocate_space(self.size);
|
let response = ui.allocate_response(self.size, Sense::hover());
|
||||||
ui.painter().rect(
|
ui.painter().rect(
|
||||||
rect,
|
response.rect,
|
||||||
self.corner_radius,
|
self.corner_radius,
|
||||||
Srgba::gray(64),
|
Srgba::gray(64),
|
||||||
Stroke::new(self.stroke_width, WHITE),
|
Stroke::new(self.stroke_width, WHITE),
|
||||||
|
|
|
@ -50,8 +50,7 @@ pub fn drop_target<R>(
|
||||||
let mut content_ui = ui.child_ui(inner_rect, *ui.layout());
|
let mut content_ui = ui.child_ui(inner_rect, *ui.layout());
|
||||||
let ret = body(&mut content_ui);
|
let ret = body(&mut content_ui);
|
||||||
let outer_rect = Rect::from_min_max(outer_rect_bounds.min, content_ui.min_rect().max + margin);
|
let outer_rect = Rect::from_min_max(outer_rect_bounds.min, content_ui.min_rect().max + margin);
|
||||||
let (id, outer_rect) = ui.allocate_space(outer_rect.size());
|
let response = ui.allocate_response(outer_rect.size(), Sense::hover());
|
||||||
let response = ui.interact(outer_rect, id, Sense::hover());
|
|
||||||
|
|
||||||
let style = if is_being_dragged && can_accept_what_is_being_dragged && response.hovered {
|
let style = if is_being_dragged && can_accept_what_is_being_dragged && response.hovered {
|
||||||
ui.style().visuals.widgets.active
|
ui.style().visuals.widgets.active
|
||||||
|
@ -69,7 +68,7 @@ pub fn drop_target<R>(
|
||||||
corner_radius: style.corner_radius,
|
corner_radius: style.corner_radius,
|
||||||
fill: style.bg_fill,
|
fill: style.bg_fill,
|
||||||
stroke: style.bg_stroke,
|
stroke: style.bg_stroke,
|
||||||
rect: outer_rect,
|
rect: response.rect,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,11 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
let desired_size = ui.style().spacing.interact_size;
|
let desired_size = ui.style().spacing.interact_size;
|
||||||
|
|
||||||
// 2. Allocating space:
|
// 2. Allocating space:
|
||||||
// This is where we get a region (`Rect`) of the screen assigned.
|
// This is where we get a region of the screen assigned.
|
||||||
// We also get an automatically generated `Id` which can be used for interactions and animations.
|
// We also tell the Ui to sense clicks in the allocated region.
|
||||||
// (To get an `Id` that is persistent over long time, use `ui.make_persistent_id`).
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
|
||||||
|
|
||||||
// 3. Interact: Time to check for clicks!.
|
// 3. Interact: Time to check for clicks!.
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
|
||||||
if response.clicked {
|
if response.clicked {
|
||||||
*on = !*on;
|
*on = !*on;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +36,7 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
// First let's ask for a simple animation from Egui.
|
// First let's ask for a simple animation from Egui.
|
||||||
// Egui keeps track of changes in the boolean associated with the id and
|
// Egui keeps track of changes in the boolean associated with the id and
|
||||||
// returns an animated value in the 0-1 range for how much "on" we are.
|
// returns an animated value in the 0-1 range for how much "on" we are.
|
||||||
let how_on = ui.ctx().animate_bool(id, *on);
|
let how_on = ui.ctx().animate_bool(response.id, *on);
|
||||||
// We will follow the current style by asking
|
// We will follow the current style by asking
|
||||||
// "how should something that is being interacted with be painted?".
|
// "how should something that is being interacted with be painted?".
|
||||||
// This will, for instance, give us different colors when the widget is hovered or clicked.
|
// This will, for instance, give us different colors when the widget is hovered or clicked.
|
||||||
|
@ -47,6 +45,7 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||||
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||||
// All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
|
// All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
|
||||||
|
let rect = response.rect;
|
||||||
let radius = 0.5 * rect.height();
|
let radius = 0.5 * rect.height();
|
||||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||||
// Paint the circle, animating it from left to right with `how_on`:
|
// Paint the circle, animating it from left to right with `how_on`:
|
||||||
|
@ -64,16 +63,15 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn toggle_compact(ui: &mut Ui, on: &mut bool) -> Response {
|
fn toggle_compact(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
let desired_size = ui.style().spacing.interact_size;
|
let desired_size = ui.style().spacing.interact_size;
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
|
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
|
||||||
*on ^= response.clicked; // toggle if clicked
|
*on ^= response.clicked; // toggle if clicked
|
||||||
|
|
||||||
let how_on = ui.ctx().animate_bool(id, *on);
|
let how_on = ui.ctx().animate_bool(response.id, *on);
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let off_bg_fill = Rgba::new(0.0, 0.0, 0.0, 0.0);
|
let off_bg_fill = Rgba::new(0.0, 0.0, 0.0, 0.0);
|
||||||
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||||
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||||
|
let rect = response.rect;
|
||||||
let radius = 0.5 * rect.height();
|
let radius = 0.5 * rect.height();
|
||||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||||
let circle_x = lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
let circle_x = lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||||
|
@ -87,7 +85,7 @@ fn toggle_compact(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
pub fn demo(ui: &mut Ui, on: &mut bool) {
|
pub fn demo(ui: &mut Ui, on: &mut bool) {
|
||||||
ui.horizontal_wrapped_for_text(TextStyle::Button, |ui| {
|
ui.horizontal_wrapped_for_text(TextStyle::Button, |ui| {
|
||||||
ui.label("It's easy to create your own widgets!");
|
ui.label("It's easy to create your own widgets!");
|
||||||
ui.label("This toggle switch is just one function of 20 lines of code:");
|
ui.label("This toggle switch is just one function and 15 lines of code:");
|
||||||
toggle(ui, on).on_hover_text("Click to toggle");
|
toggle(ui, on).on_hover_text("Click to toggle");
|
||||||
ui.add(__egui_github_link_file!());
|
ui.add(__egui_github_link_file!());
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,8 +18,8 @@ impl Texture {
|
||||||
if size.x > ui.available_width() {
|
if size.x > ui.available_width() {
|
||||||
size *= ui.available_width() / size.x;
|
size *= ui.available_width() / size.x;
|
||||||
}
|
}
|
||||||
let (id, rect) = ui.allocate_space(size);
|
let response = ui.allocate_response(size, Sense::hover());
|
||||||
let response = ui.interact(rect, id, Sense::hover());
|
let rect = response.rect;
|
||||||
let mut triangles = Triangles::default();
|
let mut triangles = Triangles::default();
|
||||||
triangles.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), WHITE);
|
triangles.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), WHITE);
|
||||||
ui.painter().add(PaintCmd::triangles(triangles));
|
ui.painter().add(PaintCmd::triangles(triangles));
|
||||||
|
|
|
@ -416,6 +416,30 @@ impl Ui {
|
||||||
self.layout.advance_cursor(&mut self.region, amount);
|
self.layout.advance_cursor(&mut self.region, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocate space for a widget and check for interaction in the space.
|
||||||
|
/// Returns a `Response` which contains a rectangle, id, and interaction info.
|
||||||
|
///
|
||||||
|
/// ## How sizes are negotiated
|
||||||
|
/// Each widget should have a *minimum desired size* and a *desired size*.
|
||||||
|
/// When asking for space, ask AT LEAST for you minimum, and don't ask for more than you need.
|
||||||
|
/// If you want to fill the space, ask about `available().size()` and use that.
|
||||||
|
///
|
||||||
|
/// You may get MORE space than you asked for, for instance
|
||||||
|
/// for justified layouts, like in menus.
|
||||||
|
///
|
||||||
|
/// You will never get a rectangle that is smaller than the amount of space you asked for.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # let mut ui = egui::Ui::__test();
|
||||||
|
/// let response = ui.allocate_response(egui::vec2(100.0, 200.0), egui::Sense::click());
|
||||||
|
/// if response.clicked { /* … */ }
|
||||||
|
/// ui.painter().rect_stroke(response.rect, 0.0, (1.0, egui::color::WHITE));
|
||||||
|
/// ```
|
||||||
|
pub fn allocate_response(&mut self, desired_size: Vec2, sense: Sense) -> Response {
|
||||||
|
let (id, rect) = self.allocate_space(desired_size);
|
||||||
|
self.interact(rect, id, sense)
|
||||||
|
}
|
||||||
|
|
||||||
/// Reserve this much space and move the cursor.
|
/// Reserve this much space and move the cursor.
|
||||||
/// Returns where to put the widget.
|
/// Returns where to put the widget.
|
||||||
///
|
///
|
||||||
|
@ -427,7 +451,7 @@ impl Ui {
|
||||||
/// You may get MORE space than you asked for, for instance
|
/// You may get MORE space than you asked for, for instance
|
||||||
/// for justified layouts, like in menus.
|
/// 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.
|
/// You will never get a rectangle that is smaller than the amount of space you asked for.
|
||||||
///
|
///
|
||||||
/// Returns an automatic `Id` (which you can use for interaction) and the `Rect` of where to put your widget.
|
/// Returns an automatic `Id` (which you can use for interaction) and the `Rect` of where to put your widget.
|
||||||
///
|
///
|
||||||
|
|
|
@ -62,10 +62,9 @@ impl Widget for ImageButton {
|
||||||
|
|
||||||
let button_padding = ui.style().spacing.button_padding;
|
let button_padding = ui.style().spacing.button_padding;
|
||||||
let desired_size = image.desired_size() + 2.0 * button_padding;
|
let desired_size = image.desired_size() + 2.0 * button_padding;
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, sense);
|
||||||
let response = ui.interact(rect, id, sense);
|
|
||||||
|
|
||||||
if ui.clip_rect().intersects(rect) {
|
if ui.clip_rect().intersects(response.rect) {
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
|
|
|
@ -43,11 +43,10 @@ pub fn show_color(ui: &mut Ui, color: impl Into<Srgba>, desired_size: Vec2) -> R
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response {
|
fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response {
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::hover());
|
||||||
let response = ui.interact(rect, id, Sense::hover());
|
background_checkers(ui.painter(), response.rect);
|
||||||
background_checkers(ui.painter(), rect);
|
|
||||||
ui.painter().add(PaintCmd::Rect {
|
ui.painter().add(PaintCmd::Rect {
|
||||||
rect,
|
rect: response.rect,
|
||||||
corner_radius: 2.0,
|
corner_radius: 2.0,
|
||||||
fill: srgba,
|
fill: srgba,
|
||||||
stroke: Stroke::new(3.0, srgba.to_opaque()),
|
stroke: Stroke::new(3.0, srgba.to_opaque()),
|
||||||
|
@ -57,12 +56,11 @@ fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response {
|
||||||
|
|
||||||
fn color_button(ui: &mut Ui, color: Srgba) -> Response {
|
fn color_button(ui: &mut Ui, color: Srgba) -> Response {
|
||||||
let desired_size = ui.style().spacing.interact_size;
|
let desired_size = ui.style().spacing.interact_size;
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
background_checkers(ui.painter(), rect);
|
background_checkers(ui.painter(), response.rect);
|
||||||
ui.painter().add(PaintCmd::Rect {
|
ui.painter().add(PaintCmd::Rect {
|
||||||
rect,
|
rect: response.rect,
|
||||||
corner_radius: visuals.corner_radius.at_most(2.0),
|
corner_radius: visuals.corner_radius.at_most(2.0),
|
||||||
fill: color,
|
fill: color,
|
||||||
stroke: visuals.fg_stroke,
|
stroke: visuals.fg_stroke,
|
||||||
|
@ -77,9 +75,9 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Srgba
|
||||||
ui.style().spacing.slider_width,
|
ui.style().spacing.slider_width,
|
||||||
ui.style().spacing.interact_size.y * 2.0,
|
ui.style().spacing.interact_size.y * 2.0,
|
||||||
);
|
);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click_and_drag());
|
||||||
|
let rect = response.rect;
|
||||||
|
|
||||||
let response = ui.interact(rect, id, Sense::click_and_drag());
|
|
||||||
if response.active {
|
if response.active {
|
||||||
if let Some(mpos) = ui.input().mouse.pos {
|
if let Some(mpos) = ui.input().mouse.pos {
|
||||||
*value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);
|
*value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);
|
||||||
|
@ -135,9 +133,9 @@ fn color_slider_2d(
|
||||||
color_at: impl Fn(f32, f32) -> Srgba,
|
color_at: impl Fn(f32, f32) -> Srgba,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let desired_size = Vec2::splat(ui.style().spacing.slider_width);
|
let desired_size = Vec2::splat(ui.style().spacing.slider_width);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click_and_drag());
|
||||||
|
let rect = response.rect;
|
||||||
|
|
||||||
let response = ui.interact(rect, id, Sense::click_and_drag());
|
|
||||||
if response.active {
|
if response.active {
|
||||||
if let Some(mpos) = ui.input().mouse.pos {
|
if let Some(mpos) = ui.input().mouse.pos {
|
||||||
*x_value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);
|
*x_value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);
|
||||||
|
|
|
@ -72,8 +72,8 @@ impl Image {
|
||||||
|
|
||||||
impl Widget for Image {
|
impl Widget for Image {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
let (id, rect) = ui.allocate_space(self.desired_size);
|
let response = ui.allocate_response(self.desired_size, Sense::hover());
|
||||||
self.paint_at(ui, rect);
|
self.paint_at(ui, response.rect);
|
||||||
ui.interact(rect, id, Sense::hover())
|
response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,9 +186,10 @@ impl Widget for Label {
|
||||||
total_response
|
total_response
|
||||||
} else {
|
} else {
|
||||||
let galley = self.layout(ui);
|
let galley = self.layout(ui);
|
||||||
let (id, rect) = ui.allocate_space(galley.size);
|
let response = ui.allocate_response(galley.size, Sense::click());
|
||||||
let response = ui.interact(rect, id, Sense::hover());
|
let rect = ui
|
||||||
let rect = ui.layout().align_size_within_rect(galley.size, rect);
|
.layout()
|
||||||
|
.align_size_within_rect(galley.size, response.rect);
|
||||||
self.paint_galley(ui, rect.min, galley);
|
self.paint_galley(ui, rect.min, galley);
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
@ -261,9 +262,8 @@ impl Widget for Hyperlink {
|
||||||
let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style);
|
let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style);
|
||||||
let font = &ui.fonts()[text_style];
|
let font = &ui.fonts()[text_style];
|
||||||
let galley = font.layout_multiline(text, ui.available_width());
|
let galley = font.layout_multiline(text, ui.available_width());
|
||||||
let (id, rect) = ui.allocate_space(galley.size);
|
let response = ui.allocate_response(galley.size, Sense::click());
|
||||||
|
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
|
||||||
if response.hovered {
|
if response.hovered {
|
||||||
ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
|
ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
|
||||||
}
|
}
|
||||||
|
@ -404,11 +404,9 @@ impl Widget for Button {
|
||||||
desired_size.y = desired_size.y.at_least(ui.style().spacing.interact_size.y);
|
desired_size.y = desired_size.y.at_least(ui.style().spacing.interact_size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, sense);
|
||||||
|
|
||||||
let response = ui.interact(rect, id, sense);
|
if ui.clip_rect().intersects(response.rect) {
|
||||||
|
|
||||||
if ui.clip_rect().intersects(rect) {
|
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let text_cursor = ui
|
let text_cursor = ui
|
||||||
.layout()
|
.layout()
|
||||||
|
@ -489,20 +487,20 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
let mut desired_size = total_extra + galley.size;
|
let mut desired_size = total_extra + galley.size;
|
||||||
desired_size = desired_size.at_least(spacing.interact_size);
|
desired_size = desired_size.at_least(spacing.interact_size);
|
||||||
desired_size.y = desired_size.y.max(icon_width);
|
desired_size.y = desired_size.y.max(icon_width);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
let rect = ui.layout().align_size_within_rect(desired_size, rect);
|
let rect = ui
|
||||||
|
.layout()
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
.align_size_within_rect(desired_size, response.rect);
|
||||||
if response.clicked {
|
if response.clicked {
|
||||||
*checked = !*checked;
|
*checked = !*checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let text_cursor = pos2(
|
let text_cursor = pos2(
|
||||||
response.rect.min.x + button_padding.x + icon_width + icon_spacing,
|
rect.min.x + button_padding.x + icon_width + icon_spacing,
|
||||||
response.rect.center().y - 0.5 * galley.size.y,
|
rect.center().y - 0.5 * galley.size.y,
|
||||||
);
|
);
|
||||||
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(response.rect);
|
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(rect);
|
||||||
ui.painter().add(PaintCmd::Rect {
|
ui.painter().add(PaintCmd::Rect {
|
||||||
rect: big_icon_rect,
|
rect: big_icon_rect,
|
||||||
corner_radius: visuals.corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
|
@ -583,18 +581,19 @@ impl Widget for RadioButton {
|
||||||
let mut desired_size = total_extra + galley.size;
|
let mut desired_size = total_extra + galley.size;
|
||||||
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
||||||
desired_size.y = desired_size.y.max(icon_width);
|
desired_size.y = desired_size.y.max(icon_width);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
let rect = ui.layout().align_size_within_rect(desired_size, rect);
|
let rect = ui
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
.layout()
|
||||||
|
.align_size_within_rect(desired_size, response.rect);
|
||||||
|
|
||||||
let text_cursor = pos2(
|
let text_cursor = pos2(
|
||||||
response.rect.min.x + button_padding.x + icon_width + icon_spacing,
|
rect.min.x + button_padding.x + icon_width + icon_spacing,
|
||||||
response.rect.center().y - 0.5 * galley.size.y,
|
rect.center().y - 0.5 * galley.size.y,
|
||||||
);
|
);
|
||||||
|
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
|
|
||||||
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(response.rect);
|
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(rect);
|
||||||
|
|
||||||
let painter = ui.painter();
|
let painter = ui.painter();
|
||||||
|
|
||||||
|
@ -659,9 +658,7 @@ impl Widget for SelectableLabel {
|
||||||
|
|
||||||
let mut desired_size = total_extra + galley.size;
|
let mut desired_size = total_extra + galley.size;
|
||||||
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
let response = ui.allocate_response(desired_size, Sense::click());
|
||||||
|
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
|
||||||
|
|
||||||
let text_cursor = pos2(
|
let text_cursor = pos2(
|
||||||
response.rect.min.x + button_padding.x,
|
response.rect.min.x + button_padding.x,
|
||||||
|
@ -723,7 +720,8 @@ impl Widget for Separator {
|
||||||
vec2(available_space.x, spacing)
|
vec2(available_space.x, spacing)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (id, rect) = ui.allocate_space(size);
|
let response = ui.allocate_response(size, Sense::hover());
|
||||||
|
let rect = response.rect;
|
||||||
let points = if ui.layout().main_dir().is_horizontal() {
|
let points = if ui.layout().main_dir().is_horizontal() {
|
||||||
[
|
[
|
||||||
pos2(rect.center().x, rect.top()),
|
pos2(rect.center().x, rect.top()),
|
||||||
|
@ -737,6 +735,6 @@ impl Widget for Separator {
|
||||||
};
|
};
|
||||||
let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke;
|
let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke;
|
||||||
ui.painter().line_segment(points, stroke);
|
ui.painter().line_segment(points, stroke);
|
||||||
ui.interact(rect, id, Sense::hover())
|
response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,10 +241,9 @@ fn x_range(rect: &Rect) -> RangeInclusive<f32> {
|
||||||
|
|
||||||
impl<'a> Slider<'a> {
|
impl<'a> Slider<'a> {
|
||||||
/// Just the slider, no text
|
/// Just the slider, no text
|
||||||
fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> Response {
|
fn allocate_slider_space(&self, ui: &mut Ui, height: f32) -> Response {
|
||||||
let desired_size = vec2(ui.style().spacing.slider_width, height);
|
let desired_size = vec2(ui.style().spacing.slider_width, height);
|
||||||
let (id, rect) = ui.allocate_space(desired_size);
|
ui.allocate_response(desired_size, Sense::click_and_drag())
|
||||||
ui.interact(rect, id, Sense::click_and_drag())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Just the slider, no text
|
/// Just the slider, no text
|
||||||
|
@ -388,7 +387,7 @@ impl<'a> Widget for Slider<'a> {
|
||||||
|
|
||||||
if self.text.is_some() {
|
if self.text.is_some() {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let slider_response = self.allocate_slide_space(ui, height);
|
let slider_response = self.allocate_slider_space(ui, height);
|
||||||
self.slider_ui(ui, &slider_response);
|
self.slider_ui(ui, &slider_response);
|
||||||
let x_range = x_range(&slider_response.rect);
|
let x_range = x_range(&slider_response.rect);
|
||||||
self.value_ui(ui, x_range);
|
self.value_ui(ui, x_range);
|
||||||
|
@ -397,7 +396,7 @@ impl<'a> Widget for Slider<'a> {
|
||||||
})
|
})
|
||||||
.0
|
.0
|
||||||
} else {
|
} else {
|
||||||
let response = self.allocate_slide_space(ui, height);
|
let response = self.allocate_slider_space(ui, height);
|
||||||
self.slider_ui(ui, &response);
|
self.slider_ui(ui, &response);
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue