From a19f89d3a6af2804f2ac4e30f6d639b56a9bebfd Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 28 Jul 2020 18:07:46 +0300 Subject: feat(native): add Tooltip widget --- graphics/src/widget/tooltip.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 graphics/src/widget/tooltip.rs (limited to 'graphics/src/widget') diff --git a/graphics/src/widget/tooltip.rs b/graphics/src/widget/tooltip.rs new file mode 100644 index 00000000..b5b0c558 --- /dev/null +++ b/graphics/src/widget/tooltip.rs @@ -0,0 +1,37 @@ +//! Decorate content and apply alignment. +use crate::defaults::Defaults; +use crate::{Backend, Renderer}; +use iced_native::{Element, Layout, Point, Rectangle}; + +/// An element decorating some content. +/// +/// This is an alias of an `iced_native` tooltip with a default +/// `Renderer`. +pub type Tooltip<'a, Message, Backend> = + iced_native::Tooltip<'a, Message, Renderer>; + +impl iced_native::tooltip::Renderer for Renderer +where + B: Backend, +{ + type Style = (); + + fn draw( + &mut self, + defaults: &Defaults, + cursor_position: Point, + content: &Element<'_, Message, Self>, + content_layout: Layout<'_>, + viewport: &Rectangle, + ) -> Self::Output { + let (content, mouse_interaction) = content.draw( + self, + &defaults, + content_layout, + cursor_position, + viewport, + ); + + (content, mouse_interaction) + } +} -- cgit From 81c75c15249b608dd8a6d47e25f96feb10ca68da Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 23 Feb 2021 03:09:16 +0100 Subject: Change `Tooltip` to support `Text` only for now --- graphics/src/widget/tooltip.rs | 76 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) (limited to 'graphics/src/widget') diff --git a/graphics/src/widget/tooltip.rs b/graphics/src/widget/tooltip.rs index b5b0c558..0b4d1d2f 100644 --- a/graphics/src/widget/tooltip.rs +++ b/graphics/src/widget/tooltip.rs @@ -1,7 +1,10 @@ //! Decorate content and apply alignment. +use crate::backend::{self, Backend}; use crate::defaults::Defaults; -use crate::{Backend, Renderer}; -use iced_native::{Element, Layout, Point, Rectangle}; +use crate::{Primitive, Renderer, Vector}; + +use iced_native::layout::{self, Layout}; +use iced_native::{Element, Point, Rectangle, Size, Text}; /// An element decorating some content. /// @@ -10,9 +13,11 @@ use iced_native::{Element, Layout, Point, Rectangle}; pub type Tooltip<'a, Message, Backend> = iced_native::Tooltip<'a, Message, Renderer>; +pub use iced_native::tooltip::Position; + impl iced_native::tooltip::Renderer for Renderer where - B: Backend, + B: Backend + backend::Text, { type Style = (); @@ -20,10 +25,14 @@ where &mut self, defaults: &Defaults, cursor_position: Point, - content: &Element<'_, Message, Self>, content_layout: Layout<'_>, viewport: &Rectangle, + content: &Element<'_, Message, Self>, + tooltip: &Text, + position: Position, ) -> Self::Output { + let bounds = content_layout.bounds(); + let (content, mouse_interaction) = content.draw( self, &defaults, @@ -32,6 +41,63 @@ where viewport, ); - (content, mouse_interaction) + if bounds.contains(cursor_position) { + use iced_native::Widget; + + let tooltip_layout = Widget::<(), Self>::layout( + tooltip, + self, + &layout::Limits::new(Size::ZERO, viewport.size()), + ); + + let tooltip_bounds = tooltip_layout.bounds(); + + let x_center = + bounds.x + (bounds.width - tooltip_bounds.width) / 2.0; + + let y_center = + bounds.y + (bounds.height - tooltip_bounds.height) / 2.0; + + let offset = match position { + Position::Top => { + Vector::new(x_center, bounds.y - tooltip_bounds.height) + } + Position::Bottom => { + Vector::new(x_center, bounds.y + bounds.height) + } + Position::Left => { + Vector::new(bounds.x - tooltip_bounds.width, y_center) + } + Position::Right => { + Vector::new(bounds.x + bounds.width, y_center) + } + Position::FollowCursor => Vector::new( + cursor_position.x, + cursor_position.y - tooltip_bounds.height, + ), + }; + + let (tooltip, _) = Widget::<(), Self>::draw( + tooltip, + self, + defaults, + Layout::with_offset(offset, &tooltip_layout), + cursor_position, + viewport, + ); + + ( + Primitive::Clip { + bounds: *viewport, + offset: Vector::new(0, 0), + content: Box::new(Primitive::Group { + primitives: vec![content, tooltip], + }), + }, + mouse_interaction, + ) + } else { + (content, mouse_interaction) + } } } -- cgit From 2f766b73413fe60cd881e139fa0e84a0f0134d91 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 23 Feb 2021 03:16:37 +0100 Subject: Introduce `Tooltip::gap` to control spacing --- graphics/src/widget/tooltip.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'graphics/src/widget') diff --git a/graphics/src/widget/tooltip.rs b/graphics/src/widget/tooltip.rs index 0b4d1d2f..26b18507 100644 --- a/graphics/src/widget/tooltip.rs +++ b/graphics/src/widget/tooltip.rs @@ -30,6 +30,7 @@ where content: &Element<'_, Message, Self>, tooltip: &Text, position: Position, + gap: u16, ) -> Self::Output { let bounds = content_layout.bounds(); @@ -58,18 +59,21 @@ where let y_center = bounds.y + (bounds.height - tooltip_bounds.height) / 2.0; + let gap = f32::from(gap); + let offset = match position { - Position::Top => { - Vector::new(x_center, bounds.y - tooltip_bounds.height) - } + Position::Top => Vector::new( + x_center, + bounds.y - tooltip_bounds.height - gap, + ), Position::Bottom => { - Vector::new(x_center, bounds.y + bounds.height) + Vector::new(x_center, bounds.y + bounds.height + gap) } Position::Left => { - Vector::new(bounds.x - tooltip_bounds.width, y_center) + Vector::new(bounds.x - tooltip_bounds.width - gap, y_center) } Position::Right => { - Vector::new(bounds.x + bounds.width, y_center) + Vector::new(bounds.x + bounds.width + gap, y_center) } Position::FollowCursor => Vector::new( cursor_position.x, -- cgit From 4e923290ccb38dc9cee05592554f98f1f0f12966 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 23 Feb 2021 04:00:35 +0100 Subject: Add `style` and `padding` to `Tooltip` --- graphics/src/widget/tooltip.rs | 86 ++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 24 deletions(-) (limited to 'graphics/src/widget') diff --git a/graphics/src/widget/tooltip.rs b/graphics/src/widget/tooltip.rs index 26b18507..51b465a5 100644 --- a/graphics/src/widget/tooltip.rs +++ b/graphics/src/widget/tooltip.rs @@ -1,8 +1,9 @@ //! Decorate content and apply alignment. use crate::backend::{self, Backend}; -use crate::defaults::Defaults; +use crate::defaults::{self, Defaults}; use crate::{Primitive, Renderer, Vector}; +use iced_native::container; use iced_native::layout::{self, Layout}; use iced_native::{Element, Point, Rectangle, Size, Text}; @@ -19,7 +20,7 @@ impl iced_native::tooltip::Renderer for Renderer where B: Backend + backend::Text, { - type Style = (); + const DEFAULT_PADDING: u16 = 5; fn draw( &mut self, @@ -30,10 +31,10 @@ where content: &Element<'_, Message, Self>, tooltip: &Text, position: Position, + style_sheet: &::Style, gap: u16, + padding: u16, ) -> Self::Output { - let bounds = content_layout.bounds(); - let (content, mouse_interaction) = content.draw( self, &defaults, @@ -42,13 +43,26 @@ where viewport, ); + let bounds = content_layout.bounds(); + if bounds.contains(cursor_position) { use iced_native::Widget; + let gap = f32::from(gap); + let padding = f32::from(padding); + let style = style_sheet.style(); + + let defaults = Defaults { + text: defaults::Text { + color: style.text_color.unwrap_or(defaults.text.color), + }, + }; + let tooltip_layout = Widget::<(), Self>::layout( tooltip, self, - &layout::Limits::new(Size::ZERO, viewport.size()), + &layout::Limits::new(Size::ZERO, viewport.size()) + .pad(f32::from(padding)), ); let tooltip_bounds = tooltip_layout.bounds(); @@ -59,22 +73,23 @@ where let y_center = bounds.y + (bounds.height - tooltip_bounds.height) / 2.0; - let gap = f32::from(gap); - let offset = match position { Position::Top => Vector::new( x_center, - bounds.y - tooltip_bounds.height - gap, + bounds.y - tooltip_bounds.height - gap - padding, + ), + Position::Bottom => Vector::new( + x_center, + bounds.y + bounds.height + gap + padding, + ), + Position::Left => Vector::new( + bounds.x - tooltip_bounds.width - gap - padding, + y_center, + ), + Position::Right => Vector::new( + bounds.x + bounds.width + gap + padding, + y_center, ), - Position::Bottom => { - Vector::new(x_center, bounds.y + bounds.height + gap) - } - Position::Left => { - Vector::new(bounds.x - tooltip_bounds.width - gap, y_center) - } - Position::Right => { - Vector::new(bounds.x + bounds.width + gap, y_center) - } Position::FollowCursor => Vector::new( cursor_position.x, cursor_position.y - tooltip_bounds.height, @@ -84,19 +99,42 @@ where let (tooltip, _) = Widget::<(), Self>::draw( tooltip, self, - defaults, + &defaults, Layout::with_offset(offset, &tooltip_layout), cursor_position, viewport, ); + let tooltip_bounds = Rectangle { + x: offset.x - padding, + y: offset.y - padding, + width: tooltip_bounds.width + padding * 2.0, + height: tooltip_bounds.height + padding * 2.0, + }; + ( - Primitive::Clip { - bounds: *viewport, - offset: Vector::new(0, 0), - content: Box::new(Primitive::Group { - primitives: vec![content, tooltip], - }), + Primitive::Group { + primitives: vec![ + content, + Primitive::Clip { + bounds: *viewport, + offset: Vector::new(0, 0), + content: Box::new( + if let Some(background) = + crate::container::background( + tooltip_bounds, + &style, + ) + { + Primitive::Group { + primitives: vec![background, tooltip], + } + } else { + tooltip + }, + ), + }, + ], }, mouse_interaction, ) -- cgit