containers will (mostly) return value of add_contents function

This commit is contained in:
Emil Ernerfeldt 2020-05-19 23:57:48 +02:00
parent 3b822ac294
commit 8d89944b58
8 changed files with 76 additions and 56 deletions

View File

@ -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<R>(
&mut self,
ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui),
) -> Option<InteractInfo> {
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<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Option<R> {
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
}
}

View File

@ -60,7 +60,7 @@ impl Frame {
}
impl Frame {
pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) {
pub fn show<R>(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
}
}

View File

@ -20,7 +20,7 @@ impl Default for BarState {
}
}
pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo {
pub fn bar<R>(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();

View File

@ -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<R>(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
}
}

View File

@ -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 {

View File

@ -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));
});

View File

@ -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)

View File

@ -503,6 +503,10 @@ impl Ui {
self.add(Label::new(text))
}
pub fn button(&mut self, text: impl Into<String>) -> bool {
self.add(Button::new(text)).clicked
}
pub fn add_hyperlink(&mut self, url: impl Into<String>) -> GuiResponse {
self.add(Hyperlink::new(url))
}
@ -510,11 +514,11 @@ impl Ui {
// ------------------------------------------------------------------------
// Addding Containers / Sub-uis:
pub fn collapsing(
pub fn collapsing<R>(
&mut self,
text: impl Into<String>,
add_contents: impl FnOnce(&mut Ui),
) -> GuiResponse {
add_contents: impl FnOnce(&mut Ui) -> R,
) -> Option<R> {
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<R>(&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<R>(
&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<R>(&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<R>(&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<R>(
&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.