Replace (ret, response) tuples with new struct InnerResponse

This commit is contained in:
Emil Ernerfeldt 2021-02-07 14:09:44 +01:00
parent df4c0257c0
commit e82fb81f07
16 changed files with 109 additions and 68 deletions

View file

@ -65,7 +65,7 @@ impl State {
ui: &mut Ui,
id: Id,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> Option<(R, Response)> {
) -> Option<InnerResponse<R>> {
let openness = self.openness(ui.ctx(), id);
if openness <= 0.0 {
None
@ -96,10 +96,10 @@ impl State {
ret
}))
} else {
let (ret, response) = ui.wrap(add_contents);
let full_size = response.rect.size();
let ret_response = ui.wrap(add_contents);
let full_size = ret_response.response.rect.size();
self.open_height = Some(full_size.y);
Some((ret, response))
Some(ret_response)
}
}
}
@ -258,15 +258,15 @@ impl CollapsingHeader {
ui.expand_to_include_x(header_response.rect.right());
add_contents(ui)
})
.0
.inner
});
ui.memory().collapsing_headers.insert(id, state);
if let Some((ret, response)) = ret_response {
if let Some(ret_response) = ret_response {
CollapsingResponse {
header_response,
body_response: Some(response),
body_returned: Some(ret),
body_response: Some(ret_response.response),
body_returned: Some(ret_response.inner),
}
} else {
CollapsingResponse {
@ -276,7 +276,7 @@ impl CollapsingHeader {
}
}
})
.0
.inner
}
}

View file

@ -29,7 +29,7 @@ pub fn combo_box_with_label(
response |= ui.add(label);
response
})
.0
.inner
}
/// A drop-down selection menu.

View file

@ -35,7 +35,11 @@ impl SidePanel {
}
impl SidePanel {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn show<R>(
self,
ctx: &CtxRef,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
let Self { id, max_width } = self;
let mut panel_rect = ctx.available_rect();
@ -61,7 +65,7 @@ impl SidePanel {
ctx.frame_state()
.allocate_left_panel(used_space.expand2(frame.margin));
(r, response)
InnerResponse::new(r, response)
}
}
@ -97,7 +101,11 @@ impl TopPanel {
}
impl TopPanel {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn show<R>(
self,
ctx: &CtxRef,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
let Self { id, max_height } = self;
let max_height = max_height.unwrap_or_else(|| ctx.style().spacing.interact_size.y);
@ -124,7 +132,7 @@ impl TopPanel {
ctx.frame_state()
.allocate_top_panel(used_space.expand2(frame.margin));
(r, response)
InnerResponse::new(r, response)
}
}
@ -157,7 +165,11 @@ impl CentralPanel {
}
impl CentralPanel {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn show<R>(
self,
ctx: &CtxRef,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
let Self { frame } = self;
let panel_rect = ctx.available_rect();
@ -184,6 +196,6 @@ impl CentralPanel {
ctx.frame_state()
.allocate_central_panel(used_space.expand2(frame.margin));
(r, response)
InnerResponse::new(r, response)
}
}

View file

@ -333,7 +333,7 @@ impl<'open> Window<'open> {
}
})
})
.map(|ri| ri.1);
.map(|ir| ir.response);
let outer_rect = frame.end(&mut area_content_ui);
@ -670,7 +670,7 @@ fn show_title_bar(
collapsing: &mut collapsing_header::State,
collapsible: bool,
) -> TitleBar {
let (title_bar, response) = ui.horizontal(|ui| {
let inner_response = ui.horizontal(|ui| {
let height = title_label
.font_height(ui.fonts(), ui.style())
.max(ui.spacing().interact_size.y);
@ -713,10 +713,10 @@ fn show_title_bar(
}
});
TitleBar {
rect: response.rect,
..title_bar
}
let title_bar = inner_response.inner;
let rect = inner_response.response.rect;
TitleBar { rect, ..title_bar }
}
impl TitleBar {

View file

@ -328,6 +328,6 @@ impl Grid {
ui.save_grid();
r
})
.0
.inner
}
}

View file

@ -50,7 +50,7 @@ impl Widget for &epaint::Texture {
ui.painter().add(Shape::mesh(mesh));
});
})
.1
.response
}
}
@ -67,7 +67,7 @@ impl Widget for &mut epaint::text::FontDefinitions {
}
crate::reset_button(ui, self);
})
.1
.response
}
}
@ -111,7 +111,7 @@ impl Widget for &epaint::stats::PaintStats {
// ui.label("Total:");
// ui.label(self.total().format(""));
})
.1
.response
}
}
@ -139,6 +139,6 @@ impl Widget for &mut epaint::TessellationOptions {
ui.checkbox(debug_paint_clip_rects, "Paint clip rectangles (debug)");
ui.checkbox(debug_paint_text_rects, "Paint text bounds (debug)");
})
.1
.response
}
}

View file

@ -124,7 +124,7 @@ pub use {
layout::*,
memory::Memory,
painter::Painter,
response::Response,
response::{InnerResponse, Response},
sense::Sense,
style::{Style, Visuals},
ui::Ui,

View file

@ -40,7 +40,7 @@ impl BarState {
/// The menu bar goes well in `TopPanel`,
/// but can also be placed in a `Window`.
/// In the latter case you may want to wrap it in `Frame`.
pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
ui.horizontal(|ui| {
let mut style = (**ui.style()).clone();
style.spacing.button_padding = vec2(2.0, 0.0);

View file

@ -321,3 +321,28 @@ impl std::ops::BitOrAssign for Response {
*self = self.union(rhs);
}
}
// ----------------------------------------------------------------------------
/// Returned when we wrap some ui-code and want to return both
/// the results of the inner function and the ui as a whole, e.g.:
///
/// ```
/// # let ui = &mut egui::Ui::__test();
/// let inner_resp = ui.horizontal(|ui| {
/// ui.label("Blah blah");
/// 42
/// });
/// inner_resp.response.on_hover_text("You hovered the horizontal layout");
/// assert_eq!(inner_resp.inner, 42);
/// ```
pub struct InnerResponse<R> {
pub inner: R,
pub response: Response,
}
impl<R> InnerResponse<R> {
pub fn new(inner: R, response: Response) -> Self {
Self { inner, response }
}
}

View file

@ -709,7 +709,7 @@ fn ui_slider_vec2(
ui.add(Slider::f32(&mut value.y, range.clone()).text("h"));
ui.label(text);
})
.1
.response
}
fn ui_color(ui: &mut Ui, srgba: &mut Color32, text: &str) {

View file

@ -7,6 +7,8 @@ use crate::{
widgets::*, *,
};
// ----------------------------------------------------------------------------
/// This is what you use to place widgets.
///
/// Represents a region of the screen with a type of layout (horizontal or vertical).
@ -669,7 +671,7 @@ impl Ui {
&mut self,
desired_size: Vec2,
add_contents: impl FnOnce(&mut Self) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
let item_spacing = self.spacing().item_spacing;
let outer_child_rect = self.placer.next_space(desired_size, item_spacing);
let inner_child_rect = self
@ -687,7 +689,7 @@ impl Ui {
);
let response = self.interact(final_child_rect, child_ui.id, Sense::hover());
(ret, response)
InnerResponse::new(ret, response)
}
/// Allocated the given rectangle and then adds content to that rectangle.
@ -698,7 +700,7 @@ impl Ui {
&mut self,
max_rect: Rect,
add_contents: impl FnOnce(&mut Self) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
let mut child_ui = self.child_ui(max_rect, *self.layout());
let ret = add_contents(&mut child_ui);
let final_child_rect = child_ui.min_rect();
@ -710,7 +712,7 @@ impl Ui {
);
let response = self.interact(final_child_rect, child_ui.id, Sense::hover());
(ret, response)
InnerResponse::new(ret, response)
}
/// Convenience function to get a region to paint on
@ -763,17 +765,17 @@ impl Ui {
/// Add a widget to this `Ui` with a given max size.
pub fn add_sized(&mut self, max_size: Vec2, widget: impl Widget) -> Response {
self.allocate_ui(max_size, |ui| {
ui.centered_and_justified(|ui| ui.add(widget)).0
ui.centered_and_justified(|ui| ui.add(widget)).inner
})
.0
.inner
}
/// Add a widget to this `Ui` at a specific location (manual layout).
pub fn put(&mut self, max_rect: Rect, widget: impl Widget) -> Response {
self.allocate_ui_at_rect(max_rect, |ui| {
ui.centered_and_justified(|ui| ui.add(widget)).0
ui.centered_and_justified(|ui| ui.add(widget)).inner
})
.0
.inner
}
/// Shortcut for `add(Label::new(text))`
@ -1043,13 +1045,13 @@ impl Ui {
}
/// Create a child ui. You can use this to temporarily change the Style of a sub-region, for instance.
pub fn wrap<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn wrap<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
let child_rect = self.available_rect_before_wrap();
let mut child_ui = self.child_ui(child_rect, *self.layout());
let ret = add_contents(&mut child_ui);
let size = child_ui.min_size();
let response = self.allocate_response(size, Sense::hover());
(ret, response)
InnerResponse::new(ret, response)
}
/// Redirect shapes to another paint layer.
@ -1057,7 +1059,7 @@ impl Ui {
&mut self,
layer_id: LayerId,
add_contents: impl FnOnce(&mut Self) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.wrap(|ui| {
ui.painter.set_layer_id(layer_id);
add_contents(ui)
@ -1070,7 +1072,7 @@ impl Ui {
desired_size: Vec2,
add_contents: impl FnOnce(&mut Ui),
) -> Rect {
self.allocate_ui(desired_size, add_contents).1.rect
self.allocate_ui(desired_size, add_contents).response.rect
}
/// A `CollapsingHeader` that starts out collapsed.
@ -1087,7 +1089,7 @@ impl Ui {
&mut self,
id_source: impl Hash,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
assert!(
self.layout().is_vertical(),
"You can only indent vertical layouts, found {:?}",
@ -1123,7 +1125,7 @@ impl Ui {
}
let response = self.allocate_response(indent + size, Sense::hover());
(ret, response)
InnerResponse::new(ret, response)
}
#[deprecated]
@ -1173,7 +1175,7 @@ impl Ui {
/// The returned `Response` will only have checked for mouse hover
/// but can be used for tooltips (`on_hover_text`).
/// It also contains the `Rect` used by the horizontal layout.
pub fn horizontal<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
pub fn horizontal<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
self.horizontal_with_main_wrap(false, add_contents)
}
@ -1186,7 +1188,7 @@ impl Ui {
&mut self,
text_style: TextStyle,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.wrap(|ui| {
let font = &ui.fonts()[text_style];
let row_height = font.row_height();
@ -1195,7 +1197,7 @@ impl Ui {
spacing.interact_size.y = row_height;
spacing.item_spacing.x = space_width;
spacing.item_spacing.y = 0.0;
ui.horizontal(add_contents).0
ui.horizontal(add_contents).inner
})
}
@ -1215,7 +1217,7 @@ impl Ui {
pub fn horizontal_wrapped<R>(
&mut self,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.horizontal_with_main_wrap(true, add_contents)
}
@ -1230,7 +1232,7 @@ impl Ui {
&mut self,
text_style: TextStyle,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.wrap(|ui| {
let font = &ui.fonts()[text_style];
let row_height = font.row_height();
@ -1239,7 +1241,7 @@ impl Ui {
spacing.interact_size.y = row_height;
spacing.item_spacing.x = space_width;
spacing.item_spacing.y = 0.0;
ui.horizontal_wrapped(add_contents).0
ui.horizontal_wrapped(add_contents).inner
})
}
@ -1247,7 +1249,7 @@ impl Ui {
&mut self,
main_wrap: bool,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
let initial_size = vec2(
self.available_size_before_wrap_finite().x,
self.spacing().interact_size.y, // Assume there will be something interactive on the horizontal layout
@ -1260,12 +1262,14 @@ impl Ui {
}
.with_main_wrap(main_wrap);
self.allocate_ui(initial_size, |ui| ui.with_layout(layout, add_contents).0)
self.allocate_ui(initial_size, |ui| {
ui.with_layout(layout, add_contents).inner
})
}
/// 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) {
pub fn vertical<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
self.with_layout(Layout::top_down(Align::Min), add_contents)
}
@ -1274,7 +1278,7 @@ impl Ui {
pub fn vertical_centered<R>(
&mut self,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.with_layout(Layout::top_down(Align::Center), add_contents)
}
@ -1283,7 +1287,7 @@ impl Ui {
pub fn vertical_centered_justified<R>(
&mut self,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.with_layout(
Layout::top_down(Align::Center).with_cross_justify(true),
add_contents,
@ -1294,20 +1298,20 @@ impl Ui {
&mut self,
layout: Layout,
add_contents: impl FnOnce(&mut Self) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
let mut child_ui = self.child_ui(self.available_rect_before_wrap(), layout);
let ret = add_contents(&mut child_ui);
let inner = add_contents(&mut child_ui);
let rect = child_ui.min_rect();
let item_spacing = self.spacing().item_spacing;
self.placer.advance_after_rects(rect, rect, item_spacing);
(ret, self.interact(rect, child_ui.id, Sense::hover()))
InnerResponse::new(inner, self.interact(rect, child_ui.id, Sense::hover()))
}
/// This will make the next added widget centered and justified in the available space.
pub fn centered_and_justified<R>(
&mut self,
add_contents: impl FnOnce(&mut Self) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
self.with_layout(
Layout::centered_and_justified(Direction::TopDown),
add_contents,

View file

@ -149,7 +149,7 @@ impl Widget for Button {
ui.set_enabled(false);
self.enabled_ui(ui)
})
.0
.inner
}
}
}

View file

@ -413,7 +413,7 @@ impl<'a> Widget for Slider<'a> {
self.label_ui(ui);
slider_response
})
.0
.inner
} else {
let response = self.allocate_slider_space(ui, height);
self.slider_ui(ui, &response);

View file

@ -4,7 +4,7 @@ pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
let is_being_dragged = ui.memory().is_being_dragged(id);
if !is_being_dragged {
let response = ui.wrap(body).1;
let response = ui.wrap(body).response;
// Check for drags:
let response = ui.interact(response.rect, id, Sense::drag());
@ -16,7 +16,7 @@ pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
// Paint the body to a new layer:
let layer_id = LayerId::new(Order::Tooltip, id);
let response = ui.with_layer_id(layer_id, body).1;
let response = ui.with_layer_id(layer_id, body).response;
// Now we move the visuals of the body to where the mouse is.
// Normally you need to decide a location for a widget first,
@ -36,7 +36,7 @@ pub fn drop_target<R>(
ui: &mut Ui,
can_accept_what_is_being_dragged: bool,
body: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
) -> InnerResponse<R> {
let is_being_dragged = ui.memory().is_anything_being_dragged();
let margin = Vec2::splat(4.0);
@ -73,7 +73,7 @@ pub fn drop_target<R>(
},
);
(ret, response)
InnerResponse::new(ret, response)
}
pub struct DragAndDropDemo {
@ -135,7 +135,7 @@ impl super::View for DragAndDropDemo {
}
}
})
.1;
.response;
let is_being_dragged = ui.memory().is_anything_being_dragged();
if is_being_dragged && can_accept_what_is_being_dragged && response.hovered() {

View file

@ -86,7 +86,7 @@ pub fn demo(ui: &mut egui::Ui, on: &mut bool) {
toggle(ui, on).on_hover_text("Click to toggle");
ui.add(crate::__egui_github_link_file!());
})
.1
.response
.on_hover_text(
"It's easy to create your own widgets!\n\
This toggle switch is just one function and 20 lines of code.",

View file

@ -112,7 +112,7 @@ impl Widgets {
ui.label(format!("{:.3}τ", self.angle / std::f32::consts::TAU))
.on_hover_text("Each τ represents one turn (τ = 2π)");
})
.1
.response
.on_hover_text("The angle is stored in radians, but presented in degrees");
ui.separator();