Pass more inner return values (#557)
* add Window.show_with_return * Fixed all missed opportunities to pass an inner return value
This commit is contained in:
parent
06fc9afb1d
commit
224af23fd1
7 changed files with 176 additions and 86 deletions
|
@ -6,6 +6,13 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md) and [
|
||||||
|
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
* Replaced all missed opportunities to return an inner return value. (this is a breaking change!)
|
||||||
|
* `Area::show`
|
||||||
|
* `ComboBox::show_ui`
|
||||||
|
* `ComboBox::combo_box_with_label`
|
||||||
|
* `Window::show`
|
||||||
|
* `popup::*`
|
||||||
|
* `menu::menu`
|
||||||
|
|
||||||
### Added ⭐
|
### Added ⭐
|
||||||
* Plot:
|
* Plot:
|
||||||
|
|
|
@ -219,11 +219,16 @@ impl Area {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) -> Response {
|
pub fn show<R>(
|
||||||
|
self,
|
||||||
|
ctx: &CtxRef,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> InnerResponse<R> {
|
||||||
let prepared = self.begin(ctx);
|
let prepared = self.begin(ctx);
|
||||||
let mut content_ui = prepared.content_ui(ctx);
|
let mut content_ui = prepared.content_ui(ctx);
|
||||||
add_contents(&mut content_ui);
|
let inner = add_contents(&mut content_ui);
|
||||||
prepared.end(ctx, content_ui)
|
let response = prepared.end(ctx, content_ui);
|
||||||
|
InnerResponse { inner, response }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_open_close_animation(&self, ctx: &CtxRef, frame: &Frame, is_open: bool) {
|
pub fn show_open_close_animation(&self, ctx: &CtxRef, frame: &Frame, is_open: bool) {
|
||||||
|
|
|
@ -63,7 +63,13 @@ impl ComboBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show the combo box, with the given ui code for the menu contents.
|
/// Show the combo box, with the given ui code for the menu contents.
|
||||||
pub fn show_ui(self, ui: &mut Ui, menu_contents: impl FnOnce(&mut Ui)) -> Response {
|
///
|
||||||
|
/// Returns `InnerResponse { inner: None }` if the combo box is closed.
|
||||||
|
pub fn show_ui<R>(
|
||||||
|
self,
|
||||||
|
ui: &mut Ui,
|
||||||
|
menu_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> InnerResponse<Option<R>> {
|
||||||
let Self {
|
let Self {
|
||||||
id_source,
|
id_source,
|
||||||
label,
|
label,
|
||||||
|
@ -77,14 +83,16 @@ impl ComboBox {
|
||||||
if let Some(width) = width {
|
if let Some(width) = width {
|
||||||
ui.spacing_mut().slider_width = width; // yes, this is ugly. Will remove later.
|
ui.spacing_mut().slider_width = width; // yes, this is ugly. Will remove later.
|
||||||
}
|
}
|
||||||
let mut response = combo_box(ui, button_id, selected_text, menu_contents);
|
let mut ir = combo_box(ui, button_id, selected_text, menu_contents);
|
||||||
if let Some(label) = label {
|
if let Some(label) = label {
|
||||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, label.text()));
|
ir.response
|
||||||
response |= ui.add(label);
|
.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, label.text()));
|
||||||
|
ir.response |= ui.add(label);
|
||||||
} else {
|
} else {
|
||||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, ""));
|
ir.response
|
||||||
|
.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, ""));
|
||||||
}
|
}
|
||||||
response
|
ir
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
}
|
}
|
||||||
|
@ -117,14 +125,16 @@ impl ComboBox {
|
||||||
|
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
|
|
||||||
let mut response = slf.show_ui(ui, |ui| {
|
let mut response = slf
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if ui.selectable_label(i == *selected, get(i)).clicked() {
|
if ui.selectable_label(i == *selected, get(i)).clicked() {
|
||||||
*selected = i;
|
*selected = i;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.response;
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
response.mark_changed();
|
response.mark_changed();
|
||||||
|
@ -137,6 +147,8 @@ impl ComboBox {
|
||||||
///
|
///
|
||||||
/// Deprecated! Use [`ComboBox`] instead!
|
/// Deprecated! Use [`ComboBox`] instead!
|
||||||
///
|
///
|
||||||
|
/// Returns `InnerResponse { inner: None }` if the combo box is closed.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[derive(Debug, PartialEq)]
|
/// # #[derive(Debug, PartialEq)]
|
||||||
/// # enum Enum { First, Second, Third }
|
/// # enum Enum { First, Second, Third }
|
||||||
|
@ -149,31 +161,32 @@ impl ComboBox {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
#[deprecated = "Use egui::ComboBox::from_label instead"]
|
#[deprecated = "Use egui::ComboBox::from_label instead"]
|
||||||
pub fn combo_box_with_label(
|
pub fn combo_box_with_label<R>(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
label: impl Into<Label>,
|
label: impl Into<Label>,
|
||||||
selected: impl ToString,
|
selected: impl ToString,
|
||||||
menu_contents: impl FnOnce(&mut Ui),
|
menu_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> Response {
|
) -> InnerResponse<Option<R>> {
|
||||||
let label = label.into();
|
let label = label.into();
|
||||||
let button_id = ui.make_persistent_id(label.text());
|
let button_id = ui.make_persistent_id(label.text());
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let mut response = combo_box(ui, button_id, selected, menu_contents);
|
let mut ir = combo_box(ui, button_id, selected, menu_contents);
|
||||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, label.text()));
|
ir.response
|
||||||
response |= ui.add(label);
|
.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, label.text()));
|
||||||
response
|
ir.response |= ui.add(label);
|
||||||
|
ir
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn combo_box(
|
fn combo_box<R>(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
button_id: Id,
|
button_id: Id,
|
||||||
selected: impl ToString,
|
selected: impl ToString,
|
||||||
menu_contents: impl FnOnce(&mut Ui),
|
menu_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> Response {
|
) -> InnerResponse<Option<R>> {
|
||||||
let popup_id = button_id.with("popup");
|
let popup_id = button_id.with("popup");
|
||||||
|
|
||||||
let is_popup_open = ui.memory().is_popup_open(popup_id);
|
let is_popup_open = ui.memory().is_popup_open(popup_id);
|
||||||
|
@ -211,11 +224,14 @@ fn combo_box(
|
||||||
if button_response.clicked() {
|
if button_response.clicked() {
|
||||||
ui.memory().toggle_popup(popup_id);
|
ui.memory().toggle_popup(popup_id);
|
||||||
}
|
}
|
||||||
crate::popup::popup_below_widget(ui, popup_id, &button_response, |ui| {
|
let inner = crate::popup::popup_below_widget(ui, popup_id, &button_response, |ui| {
|
||||||
ScrollArea::from_max_height(ui.spacing().combo_height).show(ui, menu_contents)
|
ScrollArea::from_max_height(ui.spacing().combo_height).show(ui, menu_contents)
|
||||||
});
|
});
|
||||||
|
|
||||||
button_response
|
InnerResponse {
|
||||||
|
inner,
|
||||||
|
response: button_response,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button_frame(
|
fn button_frame(
|
||||||
|
|
|
@ -41,6 +41,8 @@ impl MonoState {
|
||||||
///
|
///
|
||||||
/// See also [`show_tooltip_text`].
|
/// See also [`show_tooltip_text`].
|
||||||
///
|
///
|
||||||
|
/// Returns `None` if the tooltip could not be placed.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # let mut ui = egui::Ui::__test();
|
/// # let mut ui = egui::Ui::__test();
|
||||||
/// if ui.ui_contains_pointer() {
|
/// if ui.ui_contains_pointer() {
|
||||||
|
@ -49,7 +51,7 @@ impl MonoState {
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn show_tooltip(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&mut Ui)) {
|
pub fn show_tooltip<R>(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&mut Ui) -> R) -> Option<R> {
|
||||||
show_tooltip_at_pointer(ctx, id, add_contents)
|
show_tooltip_at_pointer(ctx, id, add_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +61,8 @@ pub fn show_tooltip(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&mut Ui)) {
|
||||||
///
|
///
|
||||||
/// See also [`show_tooltip_text`].
|
/// See also [`show_tooltip_text`].
|
||||||
///
|
///
|
||||||
|
/// Returns `None` if the tooltip could not be placed.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # let mut ui = egui::Ui::__test();
|
/// # let mut ui = egui::Ui::__test();
|
||||||
/// if ui.ui_contains_pointer() {
|
/// if ui.ui_contains_pointer() {
|
||||||
|
@ -67,7 +71,11 @@ pub fn show_tooltip(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&mut Ui)) {
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn show_tooltip_at_pointer(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&mut Ui)) {
|
pub fn show_tooltip_at_pointer<R>(
|
||||||
|
ctx: &CtxRef,
|
||||||
|
id: Id,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> Option<R> {
|
||||||
let suggested_pos = ctx
|
let suggested_pos = ctx
|
||||||
.input()
|
.input()
|
||||||
.pointer
|
.pointer
|
||||||
|
@ -76,7 +84,12 @@ pub fn show_tooltip_at_pointer(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(&
|
||||||
show_tooltip_at(ctx, id, suggested_pos, add_contents)
|
show_tooltip_at(ctx, id, suggested_pos, add_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_tooltip_under(ctx: &CtxRef, id: Id, rect: &Rect, add_contents: impl FnOnce(&mut Ui)) {
|
pub fn show_tooltip_under<R>(
|
||||||
|
ctx: &CtxRef,
|
||||||
|
id: Id,
|
||||||
|
rect: &Rect,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> Option<R> {
|
||||||
show_tooltip_at(
|
show_tooltip_at(
|
||||||
ctx,
|
ctx,
|
||||||
id,
|
id,
|
||||||
|
@ -85,12 +98,15 @@ pub fn show_tooltip_under(ctx: &CtxRef, id: Id, rect: &Rect, add_contents: impl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_tooltip_at(
|
/// Show a tooltip at the given position.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the tooltip could not be placed.
|
||||||
|
pub fn show_tooltip_at<R>(
|
||||||
ctx: &CtxRef,
|
ctx: &CtxRef,
|
||||||
mut id: Id,
|
mut id: Id,
|
||||||
suggested_position: Option<Pos2>,
|
suggested_position: Option<Pos2>,
|
||||||
add_contents: impl FnOnce(&mut Ui),
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) {
|
) -> Option<R> {
|
||||||
let mut tooltip_rect = Rect::NOTHING;
|
let mut tooltip_rect = Rect::NOTHING;
|
||||||
|
|
||||||
let position = if let Some((stored_id, stored_tooltip_rect)) = ctx.frame_state().tooltip_rect {
|
let position = if let Some((stored_id, stored_tooltip_rect)) = ctx.frame_state().tooltip_rect {
|
||||||
|
@ -103,7 +119,7 @@ pub fn show_tooltip_at(
|
||||||
} else if ctx.memory().everything_is_visible() {
|
} else if ctx.memory().everything_is_visible() {
|
||||||
Pos2::default()
|
Pos2::default()
|
||||||
} else {
|
} else {
|
||||||
return; // No good place for a tooltip :(
|
return None; // No good place for a tooltip :(
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_size = ctx
|
let expected_size = ctx
|
||||||
|
@ -115,13 +131,14 @@ pub fn show_tooltip_at(
|
||||||
let position = position.min(ctx.input().screen_rect().right_bottom() - expected_size);
|
let position = position.min(ctx.input().screen_rect().right_bottom() - expected_size);
|
||||||
let position = position.max(ctx.input().screen_rect().left_top());
|
let position = position.max(ctx.input().screen_rect().left_top());
|
||||||
|
|
||||||
let response = show_tooltip_area(ctx, id, position, add_contents);
|
let InnerResponse { inner, response } = show_tooltip_area(ctx, id, position, add_contents);
|
||||||
ctx.memory()
|
ctx.memory()
|
||||||
.data_temp
|
.data_temp
|
||||||
.get_mut_or_default::<crate::containers::popup::MonoState>()
|
.get_mut_or_default::<crate::containers::popup::MonoState>()
|
||||||
.set_tooltip_size(id, response.rect.size());
|
.set_tooltip_size(id, response.rect.size());
|
||||||
|
|
||||||
ctx.frame_state().tooltip_rect = Some((id, tooltip_rect.union(response.rect)));
|
ctx.frame_state().tooltip_rect = Some((id, tooltip_rect.union(response.rect)));
|
||||||
|
Some(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show some text at the current pointer position (if any).
|
/// Show some text at the current pointer position (if any).
|
||||||
|
@ -130,35 +147,39 @@ pub fn show_tooltip_at(
|
||||||
///
|
///
|
||||||
/// See also [`show_tooltip`].
|
/// See also [`show_tooltip`].
|
||||||
///
|
///
|
||||||
|
/// Returns `None` if the tooltip could not be placed.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # let mut ui = egui::Ui::__test();
|
/// # let mut ui = egui::Ui::__test();
|
||||||
/// if ui.ui_contains_pointer() {
|
/// if ui.ui_contains_pointer() {
|
||||||
/// egui::show_tooltip_text(ui.ctx(), egui::Id::new("my_tooltip"), "Helpful text");
|
/// egui::show_tooltip_text(ui.ctx(), egui::Id::new("my_tooltip"), "Helpful text");
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn show_tooltip_text(ctx: &CtxRef, id: Id, text: impl ToString) {
|
pub fn show_tooltip_text(ctx: &CtxRef, id: Id, text: impl ToString) -> Option<()> {
|
||||||
show_tooltip(ctx, id, |ui| {
|
show_tooltip(ctx, id, |ui| {
|
||||||
ui.add(crate::widgets::Label::new(text));
|
ui.add(crate::widgets::Label::new(text));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show a pop-over window.
|
/// Show a pop-over window.
|
||||||
fn show_tooltip_area(
|
fn show_tooltip_area<R>(
|
||||||
ctx: &CtxRef,
|
ctx: &CtxRef,
|
||||||
id: Id,
|
id: Id,
|
||||||
window_pos: Pos2,
|
window_pos: Pos2,
|
||||||
add_contents: impl FnOnce(&mut Ui),
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> Response {
|
) -> InnerResponse<R> {
|
||||||
use containers::*;
|
use containers::*;
|
||||||
Area::new(id)
|
Area::new(id)
|
||||||
.order(Order::Tooltip)
|
.order(Order::Tooltip)
|
||||||
.fixed_pos(window_pos)
|
.fixed_pos(window_pos)
|
||||||
.interactable(false)
|
.interactable(false)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
Frame::popup(&ctx.style()).show(ui, |ui| {
|
Frame::popup(&ctx.style())
|
||||||
|
.show(ui, |ui| {
|
||||||
ui.set_max_width(ui.spacing().tooltip_width);
|
ui.set_max_width(ui.spacing().tooltip_width);
|
||||||
add_contents(ui);
|
add_contents(ui)
|
||||||
});
|
})
|
||||||
|
.inner
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +189,8 @@ fn show_tooltip_area(
|
||||||
///
|
///
|
||||||
/// You must open the popup with [`Memory::open_popup`] or [`Memory::toggle_popup`].
|
/// You must open the popup with [`Memory::open_popup`] or [`Memory::toggle_popup`].
|
||||||
///
|
///
|
||||||
|
/// Returns `None` if the popup is not open.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # let ui = &mut egui::Ui::__test();
|
/// # let ui = &mut egui::Ui::__test();
|
||||||
/// let response = ui.button("Open popup");
|
/// let response = ui.button("Open popup");
|
||||||
|
@ -181,32 +204,39 @@ fn show_tooltip_area(
|
||||||
/// ui.label("…");
|
/// ui.label("…");
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn popup_below_widget(
|
pub fn popup_below_widget<R>(
|
||||||
ui: &Ui,
|
ui: &Ui,
|
||||||
popup_id: Id,
|
popup_id: Id,
|
||||||
widget_response: &Response,
|
widget_response: &Response,
|
||||||
add_contents: impl FnOnce(&mut Ui),
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) {
|
) -> Option<R> {
|
||||||
if ui.memory().is_popup_open(popup_id) {
|
if ui.memory().is_popup_open(popup_id) {
|
||||||
let parent_clip_rect = ui.clip_rect();
|
let parent_clip_rect = ui.clip_rect();
|
||||||
|
|
||||||
Area::new(popup_id)
|
let inner = Area::new(popup_id)
|
||||||
.order(Order::Foreground)
|
.order(Order::Foreground)
|
||||||
.fixed_pos(widget_response.rect.left_bottom())
|
.fixed_pos(widget_response.rect.left_bottom())
|
||||||
.show(ui.ctx(), |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
ui.set_clip_rect(parent_clip_rect); // for when the combo-box is in a scroll area.
|
ui.set_clip_rect(parent_clip_rect); // for when the combo-box is in a scroll area.
|
||||||
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.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
|
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
|
||||||
ui.set_width(widget_response.rect.width() - 2.0 * frame_margin.x);
|
ui.set_width(widget_response.rect.width() - 2.0 * frame_margin.x);
|
||||||
add_contents(ui)
|
add_contents(ui)
|
||||||
});
|
})
|
||||||
});
|
.inner
|
||||||
});
|
})
|
||||||
|
.inner
|
||||||
|
})
|
||||||
|
.inner;
|
||||||
|
|
||||||
if ui.input().key_pressed(Key::Escape) || widget_response.clicked_elsewhere() {
|
if ui.input().key_pressed(Key::Escape) || widget_response.clicked_elsewhere() {
|
||||||
ui.memory().close_popup();
|
ui.memory().close_popup();
|
||||||
}
|
}
|
||||||
|
Some(inner)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,16 +231,21 @@ impl<'open> Window<'open> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'open> Window<'open> {
|
impl<'open> Window<'open> {
|
||||||
/// Returns `None` if the windows is not open (if [`Window::open`] was called with `&mut false`.
|
/// Returns `None` if the window is not open (if [`Window::open`] was called with `&mut false`).
|
||||||
pub fn show(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) -> Option<Response> {
|
/// Returns `Some(InnerResponse { inner: None })` if the window is collapsed.
|
||||||
|
pub fn show<R>(
|
||||||
|
self,
|
||||||
|
ctx: &CtxRef,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> Option<InnerResponse<Option<R>>> {
|
||||||
self.show_impl(ctx, Box::new(add_contents))
|
self.show_impl(ctx, Box::new(add_contents))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_impl<'c>(
|
fn show_impl<'c, R>(
|
||||||
self,
|
self,
|
||||||
ctx: &CtxRef,
|
ctx: &CtxRef,
|
||||||
add_contents: Box<dyn FnOnce(&mut Ui) + 'c>,
|
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||||
) -> Option<Response> {
|
) -> Option<InnerResponse<Option<R>>> {
|
||||||
let Window {
|
let Window {
|
||||||
title_label,
|
title_label,
|
||||||
open,
|
open,
|
||||||
|
@ -315,7 +320,7 @@ impl<'open> Window<'open> {
|
||||||
|
|
||||||
let mut area_content_ui = area.content_ui(ctx);
|
let mut area_content_ui = area.content_ui(ctx);
|
||||||
|
|
||||||
{
|
let content_inner = {
|
||||||
// BEGIN FRAME --------------------------------
|
// BEGIN FRAME --------------------------------
|
||||||
let frame_stroke = frame.stroke;
|
let frame_stroke = frame.stroke;
|
||||||
let mut frame = frame.begin(&mut area_content_ui);
|
let mut frame = frame.begin(&mut area_content_ui);
|
||||||
|
@ -342,7 +347,7 @@ impl<'open> Window<'open> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let content_response = collapsing
|
let (content_inner, content_response) = collapsing
|
||||||
.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() {
|
||||||
|
@ -350,13 +355,14 @@ impl<'open> Window<'open> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(scroll) = scroll {
|
if let Some(scroll) = scroll {
|
||||||
scroll.show(ui, add_contents);
|
scroll.show(ui, add_contents)
|
||||||
} else {
|
} else {
|
||||||
add_contents(ui);
|
add_contents(ui)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|ir| ir.response);
|
.map(|ir| (Some(ir.inner), Some(ir.response)))
|
||||||
|
.unwrap_or((None, None));
|
||||||
|
|
||||||
let outer_rect = frame.end(&mut area_content_ui).rect;
|
let outer_rect = frame.end(&mut area_content_ui).rect;
|
||||||
paint_resize_corner(&mut area_content_ui, &possible, outer_rect, frame_stroke);
|
paint_resize_corner(&mut area_content_ui, &possible, outer_rect, frame_stroke);
|
||||||
|
@ -396,10 +402,15 @@ impl<'open> Window<'open> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
content_inner
|
||||||
|
};
|
||||||
let full_response = area.end(ctx, area_content_ui);
|
let full_response = area.end(ctx, area_content_ui);
|
||||||
|
|
||||||
Some(full_response)
|
let inner_response = InnerResponse {
|
||||||
|
inner: content_inner,
|
||||||
|
response: full_response,
|
||||||
|
};
|
||||||
|
Some(inner_response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,12 +60,22 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a top level menu in a menu bar. This would be e.g. "File", "Edit" etc.
|
/// Construct a top level menu in a menu bar. This would be e.g. "File", "Edit" etc.
|
||||||
pub fn menu(ui: &mut Ui, title: impl ToString, add_contents: impl FnOnce(&mut Ui)) {
|
///
|
||||||
|
/// Returns `None` if the menu is not open.
|
||||||
|
pub fn menu<R>(
|
||||||
|
ui: &mut Ui,
|
||||||
|
title: impl ToString,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> Option<R> {
|
||||||
menu_impl(ui, title, Box::new(add_contents))
|
menu_impl(ui, title, Box::new(add_contents))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn menu_impl<'c>(ui: &mut Ui, title: impl ToString, add_contents: Box<dyn FnOnce(&mut Ui) + 'c>) {
|
fn menu_impl<'c, R>(
|
||||||
|
ui: &mut Ui,
|
||||||
|
title: impl ToString,
|
||||||
|
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||||
|
) -> Option<R> {
|
||||||
let title = title.to_string();
|
let title = title.to_string();
|
||||||
let bar_id = ui.id();
|
let bar_id = ui.id();
|
||||||
let menu_id = bar_id.with(&title);
|
let menu_id = bar_id.with(&title);
|
||||||
|
@ -91,14 +101,17 @@ fn menu_impl<'c>(ui: &mut Ui, title: impl ToString, add_contents: Box<dyn FnOnce
|
||||||
bar_state.open_menu = Some(menu_id);
|
bar_state.open_menu = Some(menu_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if bar_state.open_menu == Some(menu_id) || ui.ctx().memory().everything_is_visible() {
|
let inner = if bar_state.open_menu == Some(menu_id) || ui.ctx().memory().everything_is_visible()
|
||||||
|
{
|
||||||
let area = Area::new(menu_id)
|
let area = Area::new(menu_id)
|
||||||
.order(Order::Foreground)
|
.order(Order::Foreground)
|
||||||
.fixed_pos(button_response.rect.left_bottom());
|
.fixed_pos(button_response.rect.left_bottom());
|
||||||
let frame = Frame::menu(ui.style());
|
let frame = Frame::menu(ui.style());
|
||||||
|
|
||||||
area.show(ui.ctx(), |ui| {
|
let inner = area
|
||||||
frame.show(ui, |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
|
frame
|
||||||
|
.show(ui, |ui| {
|
||||||
let mut style = (**ui.style()).clone();
|
let mut style = (**ui.style()).clone();
|
||||||
style.spacing.button_padding = vec2(2.0, 0.0);
|
style.spacing.button_padding = vec2(2.0, 0.0);
|
||||||
// style.visuals.widgets.active.bg_fill = Color32::TRANSPARENT;
|
// style.visuals.widgets.active.bg_fill = Color32::TRANSPARENT;
|
||||||
|
@ -108,15 +121,22 @@ fn menu_impl<'c>(ui: &mut Ui, title: impl ToString, add_contents: Box<dyn FnOnce
|
||||||
style.visuals.widgets.inactive.bg_fill = Color32::TRANSPARENT;
|
style.visuals.widgets.inactive.bg_fill = Color32::TRANSPARENT;
|
||||||
style.visuals.widgets.inactive.bg_stroke = Stroke::none();
|
style.visuals.widgets.inactive.bg_stroke = Stroke::none();
|
||||||
ui.set_style(style);
|
ui.set_style(style);
|
||||||
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents);
|
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents)
|
||||||
});
|
.inner
|
||||||
});
|
})
|
||||||
|
.inner
|
||||||
|
})
|
||||||
|
.inner;
|
||||||
|
|
||||||
// TODO: this prevents sub-menus in menus. We should fix that.
|
// TODO: this prevents sub-menus in menus. We should fix that.
|
||||||
if ui.input().key_pressed(Key::Escape) || button_response.clicked_elsewhere() {
|
if ui.input().key_pressed(Key::Escape) || button_response.clicked_elsewhere() {
|
||||||
bar_state.open_menu = None;
|
bar_state.open_menu = None;
|
||||||
}
|
}
|
||||||
}
|
Some(inner)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
bar_state.save(ui.ctx(), bar_id);
|
bar_state.save(ui.ctx(), bar_id);
|
||||||
|
inner
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,7 +355,8 @@ pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Res
|
||||||
button_response.mark_changed();
|
button_response.mark_changed();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
.response;
|
||||||
|
|
||||||
if !button_response.clicked()
|
if !button_response.clicked()
|
||||||
&& (ui.input().key_pressed(Key::Escape) || area_response.clicked_elsewhere())
|
&& (ui.input().key_pressed(Key::Escape) || area_response.clicked_elsewhere())
|
||||||
|
|
Loading…
Reference in a new issue