From 8d89944b58de99b4c3ec7f4a227fd1ff67b1a444 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 19 May 2020 23:57:48 +0200 Subject: [PATCH] containers will (mostly) return value of add_contents function --- emigui/src/containers/collapsing_header.rs | 30 ++++++++-------- emigui/src/containers/frame.rs | 6 ++-- emigui/src/containers/menu.rs | 2 +- emigui/src/containers/resize.rs | 12 ++++--- emigui/src/containers/window.rs | 21 ++++++----- emigui/src/context.rs | 6 ++-- emigui/src/examples/app.rs | 14 +++++--- emigui/src/ui.rs | 41 ++++++++++++---------- 8 files changed, 76 insertions(+), 56 deletions(-) diff --git a/emigui/src/containers/collapsing_header.rs b/emigui/src/containers/collapsing_header.rs index eb1a3947..7fee1955 100644 --- a/emigui/src/containers/collapsing_header.rs +++ b/emigui/src/containers/collapsing_header.rs @@ -92,11 +92,11 @@ impl State { } /// Show contents if we are open, with a nice animation between closed and open - pub fn add_contents( + pub fn add_contents( &mut self, ui: &mut Ui, - add_contents: impl FnOnce(&mut Ui), - ) -> Option { + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> Option<(R, InteractInfo)> { let openness = self.openness(ui); let animate = 0.0 < openness && openness < 1.0; if animate { @@ -120,7 +120,7 @@ impl State { child_ui.set_clip_rect(clip_rect); let top_left = child_ui.top_left(); - add_contents(child_ui); + let r = add_contents(child_ui); self.open_height = Some(child_ui.bounding_size().y); @@ -128,12 +128,13 @@ impl State { let mut child_bounds = child_ui.child_bounds(); child_bounds.max.y = child_bounds.max.y.min(top_left.y + max_height); child_ui.force_set_child_bounds(child_bounds); + r })) } else if self.open { - let interact = ui.add_custom(add_contents); - let full_size = interact.rect.size(); + let r_interact = ui.add_custom(add_contents); + let full_size = r_interact.1.rect.size(); self.open_height = Some(full_size.y); - Some(interact) + Some(r_interact) } else { None } @@ -155,14 +156,14 @@ impl CollapsingHeader { } } - pub fn default_open(mut self) -> Self { - self.default_open = true; + pub fn default_open(mut self, open: bool) -> Self { + self.default_open = open; self } } impl CollapsingHeader { - pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) -> GuiResponse { + pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Option { assert!( ui.layout().dir() == Direction::Vertical, "Horizontal collapsing is unimplemented" @@ -232,11 +233,12 @@ impl CollapsingHeader { ui.expand_to_include_child(interact.rect); // TODO: remove, just a test - state.add_contents(ui, |ui| { - ui.indent(id, add_contents); - }); + let r_interact = state.add_contents(ui, |ui| ui.indent(id, add_contents).0); + let ret = r_interact.map(|ri| ri.0); ui.memory().collapsing_headers.insert(id, state); - ui.response(interact) + ui.response(interact); + + ret } } diff --git a/emigui/src/containers/frame.rs b/emigui/src/containers/frame.rs index 8f338a5a..136b6714 100644 --- a/emigui/src/containers/frame.rs +++ b/emigui/src/containers/frame.rs @@ -60,7 +60,7 @@ impl Frame { } impl Frame { - pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) { + pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R { let Frame { margin, corner_radius, @@ -73,7 +73,7 @@ impl Frame { let where_to_put_background = ui.paint_list_len(); let mut child_ui = ui.child_ui(inner_rect); - add_contents(&mut child_ui); + let ret = add_contents(&mut child_ui); let outer_rect = Rect::from_min_max(outer_rect.min, child_ui.child_bounds().max + margin); @@ -89,5 +89,7 @@ impl Frame { ui.expand_to_include_child(outer_rect); // TODO: move cursor in parent ui + + ret } } diff --git a/emigui/src/containers/menu.rs b/emigui/src/containers/menu.rs index 8641f022..c036ea09 100644 --- a/emigui/src/containers/menu.rs +++ b/emigui/src/containers/menu.rs @@ -20,7 +20,7 @@ impl Default for BarState { } } -pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { +pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, InteractInfo) { ui.inner_layout(Layout::horizontal(Align::Center), |ui| { Frame::menu_bar(ui.style()).show(ui, |ui| { let mut style = ui.style().clone(); diff --git a/emigui/src/containers/resize.rs b/emigui/src/containers/resize.rs index c7b5ee75..2ef54bef 100644 --- a/emigui/src/containers/resize.rs +++ b/emigui/src/containers/resize.rs @@ -169,7 +169,7 @@ impl Resize { } impl Resize { - pub fn show(mut self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) { + pub fn show(mut self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R { let id = self.id.unwrap_or_else(|| ui.make_child_id("resize")); self.min_size = self.min_size.min(ui.available().size()); self.max_size = self.max_size.min(ui.available().size()); @@ -231,7 +231,9 @@ impl Resize { // ------------------------------ let inner_rect = Rect::from_min_size(position, state.size); - let desired_size = { + + let (ret, desired_size); + { let mut content_clip_rect = ui .clip_rect() .intersect(inner_rect.expand(ui.style().clip_rect_margin)); @@ -248,8 +250,8 @@ impl Resize { let mut contents_ui = ui.child_ui(inner_rect); contents_ui.set_clip_rect(content_clip_rect); - add_contents(&mut contents_ui); - contents_ui.bounding_size() + ret = add_contents(&mut contents_ui); + desired_size = contents_ui.bounding_size(); }; let desired_size = desired_size.ceil(); // Avoid rounding errors in math @@ -296,6 +298,8 @@ impl Resize { } ui.memory().resize.insert(id, state); + + ret } } diff --git a/emigui/src/containers/window.rs b/emigui/src/containers/window.rs index f3f25f35..191269ac 100644 --- a/emigui/src/containers/window.rs +++ b/emigui/src/containers/window.rs @@ -172,16 +172,18 @@ impl<'open> Window<'open> { ); // TODO: fix collapsing window animation - let content = collapsing.add_contents(ui, |ui| { - resize.show(ui, |ui| { - ui.add(Separator::new().line_width(1.0)); // TODO: nicer way to split window title from contents - if let Some(scroll) = scroll { - scroll.show(ui, add_contents) - } else { - add_contents(ui) - } + let content = collapsing + .add_contents(ui, |ui| { + resize.show(ui, |ui| { + ui.add(Separator::new().line_width(1.0)); // TODO: nicer way to split window title from contents + if let Some(scroll) = scroll { + scroll.show(ui, add_contents) + } else { + add_contents(ui) + } + }) }) - }); + .map(|ri| ri.1); ui.memory() .collapsing_headers @@ -471,6 +473,7 @@ fn show_title_bar( ui.expand_to_include_child(close_rect); } }) + .1 } fn close_button(ui: &mut Ui, rect: Rect) -> InteractInfo { diff --git a/emigui/src/context.rs b/emigui/src/context.rs index 0c53f290..21f94af0 100644 --- a/emigui/src/context.rs +++ b/emigui/src/context.rs @@ -476,14 +476,14 @@ impl Context { use crate::containers::*; CollapsingHeader::new("Style") - // .default_open() + .default_open(false) .show(ui, |ui| { self.paint_options.lock().ui(ui); self.style_ui(ui); }); CollapsingHeader::new("Fonts") - // .default_open() + .default_open(false) .show(ui, |ui| { let old_font_definitions = self.fonts().definitions(); let mut new_font_definitions = old_font_definitions.clone(); @@ -505,7 +505,7 @@ impl Context { ui.collapsing("Input", |ui| { CollapsingHeader::new("Raw Input").show(ui, |ui| ui.ctx().raw_input.clone().ui(ui)); CollapsingHeader::new("Input") - .default_open() + .default_open(true) .show(ui, |ui| ui.input().clone().ui(ui)); }); diff --git a/emigui/src/examples/app.rs b/emigui/src/examples/app.rs index 2f838bb2..999f7d6d 100644 --- a/emigui/src/examples/app.rs +++ b/emigui/src/examples/app.rs @@ -195,15 +195,19 @@ impl ExampleWindow { }); CollapsingHeader::new("Widgets") - .default_open() + .default_open(true) .show(ui, |ui| { self.widgets.ui(ui); }); CollapsingHeader::new("Layout") - .default_open() + .default_open(false) .show(ui, |ui| self.layout.ui(ui)); + CollapsingHeader::new("Tree") + .default_open(true) + .show(ui, |ui| self.tree.ui(ui)); + ui.collapsing("Columns", |ui| { ui.add(Slider::usize(&mut self.num_columns, 1..=10).text("Columns")); ui.columns(self.num_columns, |cols| { @@ -219,7 +223,7 @@ impl ExampleWindow { ui.collapsing("Test box rendering", |ui| self.box_painting.ui(ui)); CollapsingHeader::new("Scroll area") - // .default_open() + .default_open(false) .show(ui, |ui| { ScrollArea::default().show(ui, |ui| { ui.add_label(LOREM_IPSUM); @@ -227,11 +231,11 @@ impl ExampleWindow { }); CollapsingHeader::new("Painting") - // .default_open() + .default_open(false) .show(ui, |ui| self.painting.ui(ui)); CollapsingHeader::new("Resize") - // .default_open() + .default_open(false) .show(ui, |ui| { Resize::default() .default_height(200.0) diff --git a/emigui/src/ui.rs b/emigui/src/ui.rs index 3eeb05aa..ce6ee1ef 100644 --- a/emigui/src/ui.rs +++ b/emigui/src/ui.rs @@ -503,6 +503,10 @@ impl Ui { self.add(Label::new(text)) } + pub fn button(&mut self, text: impl Into) -> bool { + self.add(Button::new(text)).clicked + } + pub fn add_hyperlink(&mut self, url: impl Into) -> GuiResponse { self.add(Hyperlink::new(url)) } @@ -510,11 +514,11 @@ impl Ui { // ------------------------------------------------------------------------ // Addding Containers / Sub-uis: - pub fn collapsing( + pub fn collapsing( &mut self, text: impl Into, - add_contents: impl FnOnce(&mut Ui), - ) -> GuiResponse { + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> Option { CollapsingHeader::new(text).show(self, add_contents) } @@ -538,20 +542,20 @@ impl Ui { } /// Create a child ui - pub fn add_custom(&mut self, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { + pub fn add_custom(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, InteractInfo) { let child_rect = self.available(); let mut child_ui = self.child_ui(child_rect); - add_contents(&mut child_ui); + let r = add_contents(&mut child_ui); let size = child_ui.bounding_size(); - self.reserve_space(size, None) + (r, self.reserve_space(size, None)) } /// Create a child ui which is indented to the right - pub fn indent( + pub fn indent( &mut self, id_source: impl Hash, - add_contents: impl FnOnce(&mut Ui), - ) -> InteractInfo { + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> (R, InteractInfo) { assert!( self.layout().dir() == Direction::Vertical, "You can only indent vertical layouts" @@ -562,7 +566,7 @@ impl Ui { id: self.id.with(id_source), ..self.child_ui(child_rect) }; - add_contents(&mut child_ui); + let ret = add_contents(&mut child_ui); let size = child_ui.bounding_size(); // draw a grey line on the left to mark the indented section @@ -575,7 +579,7 @@ impl Ui { self.style.line_width, )); - self.reserve_space(indent + size, None) + (ret, self.reserve_space(indent + size, None)) } pub fn left_column(&mut self, width: f32) -> Ui { @@ -604,28 +608,29 @@ impl Ui { } /// Start a ui with horizontal layout - pub fn horizontal(&mut self, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { + pub fn horizontal(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, InteractInfo) { self.inner_layout(Layout::horizontal(Align::Min), add_contents) } /// Start a ui with vertical layout - pub fn vertical(&mut self, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { + pub fn vertical(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, InteractInfo) { self.inner_layout(Layout::vertical(Align::Min), add_contents) } - pub fn inner_layout( + pub fn inner_layout( &mut self, layout: Layout, - add_contents: impl FnOnce(&mut Self), - ) -> InteractInfo { + add_contents: impl FnOnce(&mut Self) -> R, + ) -> (R, InteractInfo) { let child_rect = Rect::from_min_max(self.cursor, self.bottom_right()); let mut child_ui = Self { ..self.child_ui(child_rect) }; child_ui.set_layout(layout); // HACK: need a separate call right now - add_contents(&mut child_ui); + let ret = add_contents(&mut child_ui); let size = child_ui.bounding_size(); - self.reserve_space(size, None) + let interact = self.reserve_space(size, None); + (ret, interact) } /// Temporarily split split an Ui into several columns.