From ad9c6b83cad1402a11e7e45df832868063b98014 Mon Sep 17 00:00:00 2001 From: Juan Campa Date: Fri, 21 Jan 2022 18:13:47 -0500 Subject: [PATCH 1/4] Add ability to override collapsing icons --- egui/src/containers/collapsing_header.rs | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index 6f05b26d0d6..adae8f33af9 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -141,6 +141,7 @@ pub struct CollapsingHeader { selectable: bool, selected: bool, show_background: bool, + icon: Option>, } impl CollapsingHeader { @@ -162,6 +163,7 @@ impl CollapsingHeader { selectable: false, selected: false, show_background: false, + icon: None, } } @@ -236,6 +238,25 @@ impl CollapsingHeader { self.show_background = show_background; self } + + /// Use the provided function to render a different `CollapsingHeader` icon. + /// Defaults to a triangle that animates as the `CollapsingHeader` opens and closes. + /// + /// For example: + /// ``` + /// fn circle_icon(ui: &mut Ui, openness: f32, response: &Response) { + /// let stroke = ui.style().interact(&response).fg_stroke; + /// ui.painter().circle_filled(response.rect.center(), 2.0 + openness, stroke.color); + /// } + /// + /// CollapsingHeader::new("Circles") + /// .icon(circle_icon) + /// .show(ui, |ui| { ui.label("Hi!"); }); + /// ``` + pub fn icon(mut self, icon_fn: impl FnOnce(&mut Ui, f32, &Response) + 'static) -> Self { + self.icon = Some(Box::new(icon_fn)); + self + } } struct Prepared { @@ -251,6 +272,7 @@ impl CollapsingHeader { "Horizontal collapsing is unimplemented" ); let Self { + icon, text, default_open, open, @@ -341,7 +363,11 @@ impl CollapsingHeader { ..header_response.clone() }; let openness = state.openness(ui.ctx(), id); - paint_icon(ui, openness, &icon_response); + if let Some(icon) = icon { + icon(ui, openness, &icon_response); + } else { + paint_icon(ui, openness, &icon_response); + } } text.paint_with_visuals(ui.painter(), text_pos, &visuals); From 41047974b7ffbc472094aaef522f59a40f3c296d Mon Sep 17 00:00:00 2001 From: Juan Campa Date: Fri, 21 Jan 2022 18:50:22 -0500 Subject: [PATCH 2/4] Fix tests --- egui/src/containers/collapsing_header.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index adae8f33af9..d5bec0ae08e 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -244,14 +244,17 @@ impl CollapsingHeader { /// /// For example: /// ``` - /// fn circle_icon(ui: &mut Ui, openness: f32, response: &Response) { + /// + /// # egui::__run_test_ui(|ui| { + /// fn circle_icon(ui: &mut egui::Ui, openness: f32, response: &egui::Response) { /// let stroke = ui.style().interact(&response).fg_stroke; /// ui.painter().circle_filled(response.rect.center(), 2.0 + openness, stroke.color); /// } /// - /// CollapsingHeader::new("Circles") + /// egui::CollapsingHeader::new("Circles") /// .icon(circle_icon) /// .show(ui, |ui| { ui.label("Hi!"); }); + /// # }); /// ``` pub fn icon(mut self, icon_fn: impl FnOnce(&mut Ui, f32, &Response) + 'static) -> Self { self.icon = Some(Box::new(icon_fn)); From 930af6fe1813aa08f6b5a4ac708a5aa6f5e741da Mon Sep 17 00:00:00 2001 From: Juan Campa Date: Sat, 22 Jan 2022 04:04:08 -0500 Subject: [PATCH 3/4] Improve clarity --- egui/src/containers/collapsing_header.rs | 13 ++++++++----- egui/src/containers/window.rs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index d5bec0ae08e..33d27301bcd 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -98,7 +98,7 @@ impl State { } /// Paint the arrow icon that indicated if the region is open or not -pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) { +pub(crate) fn paint_default_icon(ui: &mut Ui, openness: f32, response: &Response) { let visuals = ui.style().interact(response); let stroke = visuals.fg_stroke; @@ -117,6 +117,9 @@ pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) { ui.painter().add(Shape::closed_line(points, stroke)); } +/// A function that paints an icon indicating if the region is open or not +pub type IconPainter = Box; + /// A header which can be collapsed/expanded, revealing a contained [`Ui`] region. /// /// @@ -141,7 +144,7 @@ pub struct CollapsingHeader { selectable: bool, selected: bool, show_background: bool, - icon: Option>, + icon: Option, } impl CollapsingHeader { @@ -244,11 +247,11 @@ impl CollapsingHeader { /// /// For example: /// ``` - /// /// # egui::__run_test_ui(|ui| { /// fn circle_icon(ui: &mut egui::Ui, openness: f32, response: &egui::Response) { /// let stroke = ui.style().interact(&response).fg_stroke; - /// ui.painter().circle_filled(response.rect.center(), 2.0 + openness, stroke.color); + /// let radius = egui::lerp(2.0..=3.0, openness); + /// ui.painter().circle_filled(response.rect.center(), radius, stroke.color); /// } /// /// egui::CollapsingHeader::new("Circles") @@ -369,7 +372,7 @@ impl CollapsingHeader { if let Some(icon) = icon { icon(ui, openness, &icon_response); } else { - paint_icon(ui, openness, &icon_response); + paint_default_icon(ui, openness, &icon_response); } } diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index 537eb3522c1..1a7d2382c34 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -782,7 +782,7 @@ fn show_title_bar( collapsing.toggle(ui); } let openness = collapsing.openness(ui.ctx(), collapsing_id); - collapsing_header::paint_icon(ui, openness, &collapse_button_response); + collapsing_header::paint_default_icon(ui, openness, &collapse_button_response); } let title_galley = title.into_galley(ui, Some(false), f32::INFINITY, TextStyle::Heading); From 1b2060ca17772e7e29b321232a33c2d2250bcc2c Mon Sep 17 00:00:00 2001 From: Juan Campa Date: Sat, 22 Jan 2022 04:18:48 -0500 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b24912a1495..3351f20dae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w ### Added ⭐ * `Context::load_texture` to convert an image into a texture which can be displayed using e.g. `ui.image(texture, size)` ([#1110](https://github.com/emilk/egui/pull/1110)). * Added `Ui::add_visible` and `Ui::add_visible_ui`. +* Added `CollapsingHeader::icon` to override the default open/close icon using a custom function. ([1147](https://github.com/emilk/egui/pull/1147)) ### Changed 🔧 * ⚠️ `Context::input` and `Ui::input` now locks a mutex. This can lead to a dead-lock is used in an `if let` binding! @@ -26,6 +27,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w ### Contributors 🙏 * [danielkeller](https://github.com/danielkeller): [#1050](https://github.com/emilk/egui/pull/1050). +* [juancampa](https://github.com/juancampa): [#1147](https://github.com/emilk/egui/pull/1147). ## 0.16.1 - 2021-12-31 - Add back `CtxRef::begin_frame,end_frame`