-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add Tooltip widget with simple example
- Loading branch information
Showing
11 changed files
with
346 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,7 @@ members = [ | |
"examples/svg", | ||
"examples/todos", | ||
"examples/tour", | ||
"examples/tooltip", | ||
] | ||
|
||
[dependencies] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "tooltip" | ||
version = "0.1.0" | ||
authors = ["Yusuf Bera Ertan <y.bera003.06@protonmail.com>"] | ||
edition = "2018" | ||
publish = false | ||
|
||
[dependencies] | ||
iced = { path = "../..", features = ["debug"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
## Tooltip | ||
|
||
A tooltip. | ||
|
||
It displays and positions a widget on another based on cursor position. | ||
|
||
The __[`main`]__ file contains all the code of the example. | ||
|
||
You can run it with `cargo run`: | ||
``` | ||
cargo run --package tooltip | ||
``` | ||
|
||
[`main`]: src/main.rs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use iced::{Container, Element, Length, Sandbox, Settings, Text, Tooltip}; | ||
|
||
pub fn main() { | ||
Example::run(Settings::default()) | ||
} | ||
|
||
#[derive(Default)] | ||
struct Example {} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
enum Message {} | ||
|
||
impl Sandbox for Example { | ||
type Message = Message; | ||
|
||
fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
fn title(&self) -> String { | ||
String::from("Tooltip - Iced") | ||
} | ||
|
||
fn update(&mut self, _message: Message) {} | ||
|
||
fn view(&mut self) -> Element<Message> { | ||
let tooltip = Tooltip::new(Text::new("hello").size(60)) | ||
.hover_content(Text::new("hello but smaller").size(30)); | ||
|
||
Container::new(tooltip) | ||
.width(Length::Fill) | ||
.height(Length::Fill) | ||
.center_x() | ||
.center_y() | ||
.into() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//! Decorate content and apply alignment. | ||
use crate::defaults::Defaults; | ||
use crate::{Backend, Renderer}; | ||
use iced_native::{Element, Layout, Point}; | ||
|
||
/// 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<Backend>>; | ||
|
||
impl<B> iced_native::tooltip::Renderer for Renderer<B> | ||
where | ||
B: Backend, | ||
{ | ||
type Style = (); | ||
|
||
fn draw<Message>( | ||
&mut self, | ||
defaults: &Defaults, | ||
cursor_position: Point, | ||
content: &Element<'_, Message, Self>, | ||
content_layout: Layout<'_>, | ||
) -> Self::Output { | ||
let (content, mouse_interaction) = | ||
content.draw(self, &defaults, content_layout, cursor_position); | ||
|
||
(content, mouse_interaction) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
//! Display a widget over another. | ||
use std::hash::Hash; | ||
|
||
use crate::{ | ||
layout, overlay, Clipboard, Element, Event, Hasher, Layout, Length, Point, | ||
Size, Vector, Widget, | ||
}; | ||
|
||
/// An element to display a widget over another. | ||
#[allow(missing_debug_implementations)] | ||
pub struct Tooltip<'a, Message, Renderer: self::Renderer> { | ||
state: State, | ||
content: Element<'a, Message, Renderer>, | ||
hover_content: Option<Element<'a, Message, Renderer>>, | ||
} | ||
|
||
impl<'a, Message, Renderer> Tooltip<'a, Message, Renderer> | ||
where | ||
Renderer: self::Renderer, | ||
{ | ||
/// Creates an empty [`Tooltip`]. | ||
/// | ||
/// [`Tooltip`]: struct.Tooltip.html | ||
pub fn new<T>(content: T) -> Self | ||
where | ||
T: Into<Element<'a, Message, Renderer>>, | ||
{ | ||
Tooltip { | ||
state: Default::default(), | ||
content: content.into(), | ||
hover_content: None, | ||
} | ||
} | ||
|
||
/// Sets the hover_content of the [`Tooltip`]. | ||
/// | ||
/// [`Tooltip`]: struct.Tooltip.html | ||
pub fn hover_content<T>(mut self, hover_content: T) -> Self | ||
where | ||
T: Into<Element<'a, Message, Renderer>>, | ||
{ | ||
self.hover_content = Some(hover_content.into()); | ||
self | ||
} | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
struct State { | ||
cursor_position: Point, | ||
is_hovered: bool, | ||
} | ||
|
||
impl<'a, Message, Renderer> Widget<Message, Renderer> | ||
for Tooltip<'a, Message, Renderer> | ||
where | ||
Renderer: self::Renderer, | ||
{ | ||
fn width(&self) -> Length { | ||
self.content.width() | ||
} | ||
|
||
fn height(&self) -> Length { | ||
self.content.height() | ||
} | ||
|
||
fn layout( | ||
&self, | ||
renderer: &Renderer, | ||
limits: &layout::Limits, | ||
) -> layout::Node { | ||
self.content.layout(renderer, limits) | ||
} | ||
|
||
fn on_event( | ||
&mut self, | ||
event: Event, | ||
layout: Layout<'_>, | ||
cursor_position: Point, | ||
messages: &mut Vec<Message>, | ||
renderer: &Renderer, | ||
clipboard: Option<&dyn Clipboard>, | ||
) { | ||
match event { | ||
Event::Mouse(iced_core::mouse::Event::CursorMoved { x, y }) => { | ||
self.state.cursor_position.x = x; | ||
self.state.cursor_position.y = y; | ||
if layout.bounds().contains(self.state.cursor_position) { | ||
self.state.is_hovered = true; | ||
} else { | ||
self.state.is_hovered = false; | ||
} | ||
} | ||
_ => (), | ||
} | ||
self.content.widget.on_event( | ||
event, | ||
layout, | ||
cursor_position, | ||
messages, | ||
renderer, | ||
clipboard, | ||
) | ||
} | ||
|
||
fn draw( | ||
&self, | ||
renderer: &mut Renderer, | ||
defaults: &Renderer::Defaults, | ||
layout: Layout<'_>, | ||
cursor_position: Point, | ||
) -> Renderer::Output { | ||
renderer.draw(defaults, cursor_position, &self.content, layout) | ||
} | ||
|
||
fn hash_layout(&self, state: &mut Hasher) { | ||
struct Marker; | ||
std::any::TypeId::of::<Marker>().hash(state); | ||
|
||
self.content.hash_layout(state); | ||
} | ||
|
||
fn overlay( | ||
&mut self, | ||
layout: Layout<'_>, | ||
) -> Option<overlay::Element<'_, Message, Renderer>> { | ||
if layout.bounds().contains(self.state.cursor_position) { | ||
Some(overlay::Element::new( | ||
self.state.cursor_position, | ||
Box::new(Overlay::new(self.hover_content.as_ref()?)), | ||
)) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
struct Overlay<'a, Message, Renderer: self::Renderer> { | ||
content: &'a Element<'a, Message, Renderer>, | ||
} | ||
|
||
impl<'a, Message, Renderer: self::Renderer> Overlay<'a, Message, Renderer> | ||
where | ||
Message: 'a, | ||
Renderer: 'a, | ||
{ | ||
pub fn new(content: &'a Element<'a, Message, Renderer>) -> Self { | ||
Self { content } | ||
} | ||
} | ||
|
||
impl<'a, Message, Renderer> crate::Overlay<Message, Renderer> | ||
for Overlay<'a, Message, Renderer> | ||
where | ||
Renderer: self::Renderer, | ||
{ | ||
fn layout( | ||
&self, | ||
renderer: &Renderer, | ||
bounds: Size, | ||
position: Point, | ||
) -> layout::Node { | ||
let space_below = bounds.height - position.y; | ||
let space_above = position.y; | ||
|
||
let limits = layout::Limits::new( | ||
Size::ZERO, | ||
Size::new( | ||
bounds.width - position.x, | ||
if space_below > space_above { | ||
space_below | ||
} else { | ||
space_above | ||
}, | ||
), | ||
) | ||
.width(self.content.width()); | ||
|
||
let mut node = self.content.layout(renderer, &limits); | ||
|
||
node.move_to(position - Vector::new(0.0, node.size().height)); | ||
|
||
node | ||
} | ||
|
||
fn hash_layout(&self, state: &mut Hasher, position: Point) { | ||
struct Marker; | ||
std::any::TypeId::of::<Marker>().hash(state); | ||
|
||
(position.x as u32).hash(state); | ||
(position.y as u32).hash(state); | ||
self.content.hash_layout(state); | ||
} | ||
|
||
fn draw( | ||
&self, | ||
renderer: &mut Renderer, | ||
defaults: &Renderer::Defaults, | ||
layout: Layout<'_>, | ||
cursor_position: Point, | ||
) -> Renderer::Output { | ||
renderer.draw(defaults, cursor_position, &self.content, layout) | ||
} | ||
} | ||
|
||
/// The renderer of a [`Tooltip`]. | ||
/// | ||
/// Your [renderer] will need to implement this trait before being | ||
/// able to use a [`Tooltip`] in your user interface. | ||
/// | ||
/// [`Tooltip`]: struct.Tooltip.html | ||
/// [renderer]: ../../renderer/index.html | ||
pub trait Renderer: crate::Renderer { | ||
/// The style supported by this renderer. | ||
type Style: Default; | ||
|
||
/// Draws a [`Tooltip`]. | ||
/// | ||
/// [`Tooltip`]: struct.Tooltip.html | ||
fn draw<Message>( | ||
&mut self, | ||
defaults: &Self::Defaults, | ||
cursor_position: Point, | ||
content: &Element<'_, Message, Self>, | ||
content_layout: Layout<'_>, | ||
) -> Self::Output; | ||
} | ||
|
||
impl<'a, Message, Renderer> From<Tooltip<'a, Message, Renderer>> | ||
for Element<'a, Message, Renderer> | ||
where | ||
Renderer: 'a + self::Renderer, | ||
Message: 'a, | ||
{ | ||
fn from( | ||
column: Tooltip<'a, Message, Renderer>, | ||
) -> Element<'a, Message, Renderer> { | ||
Element::new(column) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.