From ce7010eee7b9043041e82a90de639aa2a3e4d460 Mon Sep 17 00:00:00 2001 From: Stijn Seghers Date: Wed, 22 Mar 2023 16:26:00 +0100 Subject: [PATCH 1/3] Add tooltip to ToggleButton --- CHANGELOG.md | 3 + .../src/component/node/action_bar.rs | 56 +++++++++++++++---- .../graph-editor/src/component/profiling.rs | 5 +- .../ensogl/component/toggle-button/src/lib.rs | 43 +++++++++----- 4 files changed, 82 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d774ea48b182..8fca12a16ab7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,6 +126,7 @@ shortened labels for entries with long module paths. When an option is selected from the dropdown, the necessary module imports are inserted, eliminating the need for fully qualified names. +- [Icon buttons now have tooltips.][6035] #### EnsoGL (rendering engine) @@ -176,12 +177,14 @@ performed in a given frame][5895]. In particular, you can now inspect names of all symbols rendered in a given frame. You can also pause the performance monitor and inspect results recorded in the past. +- [ToggleButtons can now have tooltips][6035]. [3857]: https://github.com/enso-org/enso/pull/3857 [3985]: https://github.com/enso-org/enso/pull/3985 [4047]: https://github.com/enso-org/enso/pull/4047 [4003]: https://github.com/enso-org/enso/pull/4003 [5895]: https://github.com/enso-org/enso/pull/5895 +[6035]: https://github.com/enso-org/enso/pull/6035 #### Enso Standard Library diff --git a/app/gui/view/graph-editor/src/component/node/action_bar.rs b/app/gui/view/graph-editor/src/component/node/action_bar.rs index 913fd5b475c9..834591d8b9d1 100644 --- a/app/gui/view/graph-editor/src/component/node/action_bar.rs +++ b/app/gui/view/graph-editor/src/component/node/action_bar.rs @@ -1,22 +1,26 @@ //! Definition of the `ActionBar` component for the `visualization::Container`. - - -pub mod icon; - use crate::prelude::*; +use ensogl::display::shape::*; use enso_config::ARGS; use enso_frp as frp; +use ensogl::application::tooltip; use ensogl::application::Application; use ensogl::display; -use ensogl::display::shape::*; use ensogl_component::toggle_button; use ensogl_component::toggle_button::ColorableShape; use ensogl_component::toggle_button::ToggleButton; use ensogl_hardcoded_theme as theme; +// ============== +// === Export === +// ============== + +pub mod icon; + + // ================== // === Constants === @@ -89,11 +93,12 @@ struct Icons { } impl Icons { - fn new() -> Self { + fn new(app: &Application) -> Self { let display_object = display::object::Instance::new(); - let freeze = ToggleButton::new(); - let visibility = ToggleButton::new(); - let skip = ToggleButton::new(); + let freeze = ToggleButton::new(app, tooltip::Style::set_label("Freeze".to_owned())); + let visibility = + ToggleButton::new(app, tooltip::Style::set_label("Show preview".to_owned())); + let skip = ToggleButton::new(app, tooltip::Style::set_label("Skip".to_owned())); display_object.add_child(&visibility); if ARGS.groups.feature_preview.options.skip_and_freeze.value { display_object.add_child(&freeze); @@ -136,7 +141,7 @@ impl Model { let scene = &app.display.default_scene; let display_object = display::object::Instance::new(); let hover_area = hover_area::View::new(); - let icons = Icons::new(); + let icons = Icons::new(app); let shapes = compound::events::MouseEvents::default(); let size = default(); let styles = StyleWatch::new(&scene.style_sheet); @@ -324,3 +329,34 @@ impl display::Object for ActionBar { self.model.display_object() } } + + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_tooltips() { + let app = Application::new("root"); + let action_bar = ActionBar::new(&app); + let visibility_icon = &action_bar.model.icons.visibility; + + // By default, the tooltip shouldn't be shown + assert_eq!(app.frp.tooltip.value().content(), None); + + // Move the mouse over the visibility button + visibility_icon.view().events.mouse_over.emit(()); + + // We expect the button to be hovered by the mouse + assert!(visibility_icon.frp.is_hovered.value()); + + // We expect the tooltip to be shown now + assert_eq!(app.frp.tooltip.value().content(), Some("Show preview")); + + // Move the mouse away again + visibility_icon.view().events.mouse_out.emit(()); + + // We expect the tooltip to be gone + assert_eq!(app.frp.tooltip.value().content(), None); + } +} diff --git a/app/gui/view/graph-editor/src/component/profiling.rs b/app/gui/view/graph-editor/src/component/profiling.rs index 16b613261042..96c02e6da0ac 100644 --- a/app/gui/view/graph-editor/src/component/profiling.rs +++ b/app/gui/view/graph-editor/src/component/profiling.rs @@ -6,6 +6,7 @@ use ensogl::display::shape::*; use crate::view; use enso_frp as frp; +use ensogl::application::tooltip; use ensogl::application::Application; use ensogl::data::color; use ensogl::display; @@ -148,7 +149,9 @@ impl Button { let frp = Frp::new(); let network = &frp.network; - let button = ToggleButton::::new(); + let tooltip_style = tooltip::Style::set_label("Profile".to_owned()) + .with_placement(tooltip::Placement::Left); + let button = ToggleButton::::new(app, tooltip_style); scene.layers.panel.add(&button); button.set_visibility(true); button.frp.set_size(Vector2(32.0, 32.0)); diff --git a/lib/rust/ensogl/component/toggle-button/src/lib.rs b/lib/rust/ensogl/component/toggle-button/src/lib.rs index 08bc56e37660..c2a72be2f9cc 100644 --- a/lib/rust/ensogl/component/toggle-button/src/lib.rs +++ b/lib/rust/ensogl/component/toggle-button/src/lib.rs @@ -21,6 +21,8 @@ use ensogl_core::prelude::*; use enso_frp as frp; +use ensogl_core::application::tooltip; +use ensogl_core::application::Application; use ensogl_core::data::color; use ensogl_core::display; use ensogl_core::display::shape::system::Shape; @@ -202,27 +204,28 @@ pub struct ToggleButton { model: Rc>, } -impl Default for ToggleButton { - fn default() -> Self { - let frp = Frp::new(); - let model = Rc::new(Model::::new()); - Self { frp, model }.init_frp() - } -} - impl ToggleButton { /// Constructor. - pub fn new() -> Self { - default() + pub fn new(app: &Application, tooltip_style: tooltip::Style) -> Self { + let frp = Frp::new(); + let model = Rc::new(Model::::new()); + Self { frp, model }.init_frp(app, tooltip_style) } - fn init_frp(self) -> Self { + fn init_frp(self, app: &Application, tooltip_style: tooltip::Style) -> Self { let network = &self.frp.network; let frp = &self.frp; let model = &self.model; let color = color::Animation::new(network); let icon = &model.icon.events; + // Explicitly define the tooltip placement if the default was used, to ensure that, when + // multiple tooltips are being used, we always override to the one we want. + let tooltip_style = { + let placement = tooltip_style.placement().unwrap_or_default(); + tooltip_style.with_placement(placement) + }; + frp::extend! { network // === Input Processing === @@ -241,6 +244,8 @@ impl ToggleButton { frp.source.mouse_over <+ icon.mouse_over; frp.source.mouse_out <+ icon.mouse_out; + frp.source.is_hovered <+ bool(&icon.mouse_out,&icon.mouse_over); + frp.source.is_pressed <+ bool(&icon.mouse_up_primary,&icon.mouse_down_primary); // === Color === @@ -248,9 +253,7 @@ impl ToggleButton { invisible <- frp.set_visibility.on_false().constant(0.0); color.target_alpha <+ invisible; - frp.source.visible <+ frp.set_visibility; - frp.source.is_hovered <+ bool(&icon.mouse_out,&icon.mouse_over); - frp.source.is_pressed <+ bool(&icon.mouse_up_primary,&icon.mouse_down_primary); + frp.source.visible <+ frp.set_visibility; button_state <- all_with4(&frp.visible,&frp.state,&frp.is_hovered,&frp.is_pressed, |a,b,c,d| ButtonState::new(*a,*b,*c,*d)); @@ -260,6 +263,18 @@ impl ToggleButton { color.target <+ color_target; eval color.value ((color) model.icon.set_color(color.into())); + + + // === Tooltip === + + tooltip <- frp.is_hovered.map(move |is_hovered| { + if *is_hovered { + tooltip_style.clone() + } else { + tooltip::Style::unset_label() + } + }); + app.frp.set_tooltip <+ tooltip; } frp.set_state.emit(false); From 91bb2a502edc2f95448ac900ec2f2d4342295e54 Mon Sep 17 00:00:00 2001 From: Stijn Seghers Date: Thu, 23 Mar 2023 09:08:06 +0100 Subject: [PATCH 2/3] Address review comments --- .../src/component/node/action_bar.rs | 20 +++++++++++++++---- .../ensogl/component/toggle-button/src/lib.rs | 10 ++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/gui/view/graph-editor/src/component/node/action_bar.rs b/app/gui/view/graph-editor/src/component/node/action_bar.rs index 834591d8b9d1..72e8cb8dce13 100644 --- a/app/gui/view/graph-editor/src/component/node/action_bar.rs +++ b/app/gui/view/graph-editor/src/component/node/action_bar.rs @@ -31,6 +31,9 @@ const BUTTON_OFFSET: f32 = 0.5; /// Grow the hover area in x direction by this amount. Used to close the gap between action /// icons and node. const HOVER_EXTENSION_X: f32 = 15.0; +const FREEZE_TOOLTIP_LABEL: &str = "Freeze"; +const SKIP_TOOLTIP_LABEL: &str = "Skip"; +const VISIBILITY_TOOLTIP_LABEL: &str = "Show preview"; // =============== @@ -95,10 +98,9 @@ struct Icons { impl Icons { fn new(app: &Application) -> Self { let display_object = display::object::Instance::new(); - let freeze = ToggleButton::new(app, tooltip::Style::set_label("Freeze".to_owned())); - let visibility = - ToggleButton::new(app, tooltip::Style::set_label("Show preview".to_owned())); - let skip = ToggleButton::new(app, tooltip::Style::set_label("Skip".to_owned())); + let freeze = labeled_button(app, FREEZE_TOOLTIP_LABEL); + let visibility = labeled_button(app, VISIBILITY_TOOLTIP_LABEL); + let skip = labeled_button(app, SKIP_TOOLTIP_LABEL); display_object.add_child(&visibility); if ARGS.groups.feature_preview.options.skip_and_freeze.value { display_object.add_child(&freeze); @@ -120,6 +122,11 @@ impl display::Object for Icons { } } +fn labeled_button(app: &Application, label: &str) -> ToggleButton { + let tooltip_style = tooltip::Style::set_label(label.to_owned()); + ToggleButton::new(app, tooltip_style) +} + // ======================== @@ -331,6 +338,11 @@ impl display::Object for ActionBar { } + +// ============ +// === Test === +// ============ + #[cfg(test)] mod test { use super::*; diff --git a/lib/rust/ensogl/component/toggle-button/src/lib.rs b/lib/rust/ensogl/component/toggle-button/src/lib.rs index c2a72be2f9cc..b11e487a9809 100644 --- a/lib/rust/ensogl/component/toggle-button/src/lib.rs +++ b/lib/rust/ensogl/component/toggle-button/src/lib.rs @@ -219,8 +219,10 @@ impl ToggleButton { let color = color::Animation::new(network); let icon = &model.icon.events; - // Explicitly define the tooltip placement if the default was used, to ensure that, when - // multiple tooltips are being used, we always override to the one we want. + // Explicitly define the tooltip placement if none was set. This ensures that this tooltip + // is always correctly placed even when other components use tooltips as well. Otherwise, + // the explicit placement setting of other tooltips would be used, since other tooltips use + // the same application-level FRP node for setting the style. let tooltip_style = { let placement = tooltip_style.placement().unwrap_or_default(); tooltip_style.with_placement(placement) @@ -244,8 +246,8 @@ impl ToggleButton { frp.source.mouse_over <+ icon.mouse_over; frp.source.mouse_out <+ icon.mouse_out; - frp.source.is_hovered <+ bool(&icon.mouse_out,&icon.mouse_over); - frp.source.is_pressed <+ bool(&icon.mouse_up_primary,&icon.mouse_down_primary); + frp.source.is_hovered <+ bool(&icon.mouse_out, &icon.mouse_over); + frp.source.is_pressed <+ bool(&icon.mouse_up_primary, &icon.mouse_down_primary); // === Color === From dd1fc03a93321c6660e430f885d2e967c43ed5e3 Mon Sep 17 00:00:00 2001 From: Stijn Seghers Date: Mon, 27 Mar 2023 10:06:24 +0200 Subject: [PATCH 3/3] Changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fca12a16ab7..7d79c1dab63e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,7 +126,8 @@ shortened labels for entries with long module paths. When an option is selected from the dropdown, the necessary module imports are inserted, eliminating the need for fully qualified names. -- [Icon buttons now have tooltips.][6035] +- [Added tooltips to icon buttons][6035] for improved usability. Users can now + quickly understand each button's function. #### EnsoGL (rendering engine)