Collapsing header returns header and body responses

This commit is contained in:
Emil Ernerfeldt 2020-10-14 15:26:31 +02:00
parent 7561ccc189
commit 1bd45c35eb
5 changed files with 57 additions and 19 deletions

View file

@ -139,6 +139,7 @@ TODO-list for the Egui project. If you looking for something to do, look here.
* [ ] Rename things to be more consistent with Dear ImGui ? * [ ] Rename things to be more consistent with Dear ImGui ?
* [ ] Put everything in `Context` behind the same Mutex? `struct Context(Arc<Mutex<ContextImpl>>);`, with e.g. `context.lock().memory.foo`? * [ ] Put everything in `Context` behind the same Mutex? `struct Context(Arc<Mutex<ContextImpl>>);`, with e.g. `context.lock().memory.foo`?
* [ ] Resolve the various uses of "heading", "header", "title" etc
## Global widget search ## Global widget search

View file

@ -163,6 +163,7 @@ impl CollapsingHeader {
struct Prepared { struct Prepared {
id: Id, id: Id,
header_response: Response,
state: State, state: State,
} }
@ -197,25 +198,28 @@ impl CollapsingHeader {
desired_size = desired_size.at_least(ui.style().spacing.interact_size); desired_size = desired_size.at_least(ui.style().spacing.interact_size);
let rect = ui.allocate_space(desired_size); let rect = ui.allocate_space(desired_size);
let response = ui.interact(rect, id, Sense::click()); let header_response = ui.interact(rect, id, Sense::click());
let text_pos = pos2(text_pos.x, response.rect.center().y - galley.size.y / 2.0); let text_pos = pos2(
text_pos.x,
header_response.rect.center().y - galley.size.y / 2.0,
);
let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open); let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open);
if response.clicked { if header_response.clicked {
state.toggle(ui); state.toggle(ui);
} }
let bg_index = ui.painter().add(PaintCmd::Noop); let bg_index = ui.painter().add(PaintCmd::Noop);
{ {
let (mut icon_rect, _) = ui.style().spacing.icon_rectangles(response.rect); let (mut icon_rect, _) = ui.style().spacing.icon_rectangles(header_response.rect);
icon_rect.set_center(pos2( icon_rect.set_center(pos2(
response.rect.left() + ui.style().spacing.indent / 2.0, header_response.rect.left() + ui.style().spacing.indent / 2.0,
response.rect.center().y, header_response.rect.center().y,
)); ));
let icon_response = Response { let icon_response = Response {
rect: icon_rect, rect: icon_rect,
..response.clone() ..header_response.clone()
}; };
let openness = state.openness(ui.ctx(), id); let openness = state.openness(ui.ctx(), id);
paint_icon(ui, openness, &icon_response); paint_icon(ui, openness, &icon_response);
@ -226,27 +230,59 @@ impl CollapsingHeader {
text_pos, text_pos,
galley, galley,
label.text_style_or_default(ui.style()), label.text_style_or_default(ui.style()),
ui.style().interact(&response).text_color(), ui.style().interact(&header_response).text_color(),
); );
painter.set( painter.set(
bg_index, bg_index,
PaintCmd::Rect { PaintCmd::Rect {
rect: response.rect, rect: header_response.rect,
corner_radius: ui.style().interact(&response).corner_radius, corner_radius: ui.style().interact(&header_response).corner_radius,
fill: ui.style().interact(&response).bg_fill, fill: ui.style().interact(&header_response).bg_fill,
stroke: Default::default(), stroke: Default::default(),
}, },
); );
Prepared { id, state } Prepared {
id,
header_response,
state,
}
} }
pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Option<R> { pub fn show<R>(
let Prepared { id, mut state } = self.begin(ui); self,
ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> CollapsingResponse<R> {
let Prepared {
id,
header_response,
mut state,
} = self.begin(ui);
let ret_response = state.add_contents(ui, id, |ui| ui.indent(id, add_contents).0); let ret_response = state.add_contents(ui, id, |ui| ui.indent(id, add_contents).0);
let ret = ret_response.map(|ri| ri.0);
ui.memory().collapsing_headers.insert(id, state); ui.memory().collapsing_headers.insert(id, state);
ret
if let Some((ret, response)) = ret_response {
CollapsingResponse {
header_response,
body_response: Some(response),
body_returned: Some(ret),
}
} else {
CollapsingResponse {
header_response,
body_response: None,
body_returned: None,
}
}
} }
} }
pub struct CollapsingResponse<R> {
pub header_response: Response,
/// None iff collapsed.
pub body_response: Option<Response>,
/// None iff collapsed.
pub body_returned: Option<R>,
}

View file

@ -12,6 +12,6 @@ pub(crate) mod scroll_area;
pub(crate) mod window; pub(crate) mod window;
pub use { pub use {
area::Area, collapsing_header::CollapsingHeader, combo_box::*, frame::Frame, popup::*, area::Area, collapsing_header::*, combo_box::*, frame::Frame, popup::*, resize::Resize,
resize::Resize, scroll_area::ScrollArea, window::Window, scroll_area::ScrollArea, window::Window,
}; };

View file

@ -451,6 +451,7 @@ impl Tree {
CollapsingHeader::new(name) CollapsingHeader::new(name)
.default_open(depth < 1) .default_open(depth < 1)
.show(ui, |ui| self.children_ui(ui, depth)) .show(ui, |ui| self.children_ui(ui, depth))
.body_returned
.unwrap_or(Action::Keep) .unwrap_or(Action::Keep)
} }

View file

@ -637,7 +637,7 @@ impl Ui {
&mut self, &mut self,
heading: impl Into<String>, heading: impl Into<String>,
add_contents: impl FnOnce(&mut Ui) -> R, add_contents: impl FnOnce(&mut Ui) -> R,
) -> Option<R> { ) -> CollapsingResponse<R> {
CollapsingHeader::new(heading).show(self, add_contents) CollapsingHeader::new(heading).show(self, add_contents)
} }