Merge pull request #2960 from kiedtl/tooltip-delays
Make Tooltip show after a delay
This commit is contained in:
commit
2280c8a6b2
2 changed files with 78 additions and 18 deletions
|
|
@ -1,6 +1,8 @@
|
|||
use iced::Element;
|
||||
use iced::alignment;
|
||||
use iced::time::seconds;
|
||||
use iced::widget::tooltip::Position;
|
||||
use iced::widget::{button, center, container, tooltip};
|
||||
use iced::widget::{button, center, checkbox, column, container, tooltip};
|
||||
|
||||
pub fn main() -> iced::Result {
|
||||
iced::run(Tooltip::update, Tooltip::view)
|
||||
|
|
@ -9,11 +11,13 @@ pub fn main() -> iced::Result {
|
|||
#[derive(Default)]
|
||||
struct Tooltip {
|
||||
position: Position,
|
||||
is_immediate: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Message {
|
||||
ChangePosition,
|
||||
ToggleImmediate(bool),
|
||||
}
|
||||
|
||||
impl Tooltip {
|
||||
|
|
@ -30,6 +34,9 @@ impl Tooltip {
|
|||
|
||||
self.position = position;
|
||||
}
|
||||
Message::ToggleImmediate(is_immediate) => {
|
||||
self.is_immediate = is_immediate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,9 +48,19 @@ impl Tooltip {
|
|||
self.position,
|
||||
)
|
||||
.gap(10)
|
||||
.delay(seconds(if self.is_immediate { 0 } else { 2 }))
|
||||
.style(container::rounded_box);
|
||||
|
||||
center(tooltip).into()
|
||||
let checkbox = checkbox(self.is_immediate)
|
||||
.label("Show immediately")
|
||||
.on_toggle(Message::ToggleImmediate);
|
||||
|
||||
center(
|
||||
column![tooltip, checkbox]
|
||||
.align_x(alignment::Horizontal::Center)
|
||||
.spacing(10),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
//! Tooltips display a hint of information over some element when hovered.
|
||||
//!
|
||||
//! By default, the tooltip is only displayed when hovered for 2 seconds.
|
||||
//! This delay can be adjusted with [`Tooltip::delay`].
|
||||
//!
|
||||
//! # Example
|
||||
//! ```no_run
|
||||
//! # mod iced { pub mod widget { pub use iced_widget::*; } }
|
||||
|
|
@ -27,6 +30,7 @@ use crate::core::mouse;
|
|||
use crate::core::overlay;
|
||||
use crate::core::renderer;
|
||||
use crate::core::text;
|
||||
use crate::core::time::{Duration, Instant};
|
||||
use crate::core::widget::{self, Widget};
|
||||
use crate::core::window;
|
||||
use crate::core::{
|
||||
|
|
@ -72,6 +76,7 @@ pub struct Tooltip<
|
|||
gap: f32,
|
||||
padding: f32,
|
||||
snap_within_viewport: bool,
|
||||
delay: Duration,
|
||||
class: Theme::Class<'a>,
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +88,9 @@ where
|
|||
/// The default padding of a [`Tooltip`] drawn by this renderer.
|
||||
const DEFAULT_PADDING: f32 = 5.0;
|
||||
|
||||
/// The default delay before a [`Tooltip`] is shown.
|
||||
const DEFAULT_DELAY: Duration = Duration::from_secs(2);
|
||||
|
||||
/// Creates a new [`Tooltip`].
|
||||
///
|
||||
/// [`Tooltip`]: struct.Tooltip.html
|
||||
|
|
@ -98,6 +106,7 @@ where
|
|||
gap: 0.0,
|
||||
padding: Self::DEFAULT_PADDING,
|
||||
snap_within_viewport: true,
|
||||
delay: Self::DEFAULT_DELAY,
|
||||
class: Theme::default(),
|
||||
}
|
||||
}
|
||||
|
|
@ -114,6 +123,14 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the delay before the [`Tooltip`] is shown.
|
||||
///
|
||||
/// Set to [`Duration::ZERO`] to be shown immediately.
|
||||
pub fn delay(mut self, delay: Duration) -> Self {
|
||||
self.delay = delay;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets whether the [`Tooltip`] is snapped within the viewport.
|
||||
pub fn snap_within_viewport(mut self, snap: bool) -> Self {
|
||||
self.snap_within_viewport = snap;
|
||||
|
|
@ -206,23 +223,46 @@ where
|
|||
| Event::Window(window::Event::RedrawRequested(_)) = event
|
||||
{
|
||||
let state = tree.state.downcast_mut::<State>();
|
||||
let previous_state = *state;
|
||||
let was_idle = *state == State::Idle;
|
||||
let now = Instant::now();
|
||||
let cursor_position = cursor.position_over(layout.bounds());
|
||||
|
||||
*state = cursor
|
||||
.position_over(layout.bounds())
|
||||
.map(|cursor_position| State::Hovered { cursor_position })
|
||||
.unwrap_or_default();
|
||||
match (*state, cursor_position) {
|
||||
(State::Idle, Some(cursor_position)) => {
|
||||
if self.delay == Duration::ZERO {
|
||||
*state = State::Open { cursor_position };
|
||||
shell.invalidate_layout();
|
||||
} else {
|
||||
*state = State::Hovered { at: now };
|
||||
}
|
||||
|
||||
let is_idle = *state == State::Idle;
|
||||
|
||||
if was_idle != is_idle {
|
||||
shell.invalidate_layout();
|
||||
shell.request_redraw();
|
||||
} else if self.position == Position::FollowCursor
|
||||
&& *state != previous_state
|
||||
{
|
||||
shell.request_redraw();
|
||||
shell.request_redraw_at(now + self.delay);
|
||||
}
|
||||
(State::Hovered { .. }, None) => {
|
||||
*state = State::Idle;
|
||||
}
|
||||
(State::Hovered { at, .. }, _) if at.elapsed() < self.delay => {
|
||||
shell.request_redraw_at(now + self.delay - at.elapsed());
|
||||
}
|
||||
(State::Hovered { .. }, Some(cursor_position)) => {
|
||||
*state = State::Open { cursor_position };
|
||||
shell.invalidate_layout();
|
||||
}
|
||||
(
|
||||
State::Open {
|
||||
cursor_position: last_position,
|
||||
},
|
||||
Some(cursor_position),
|
||||
) if self.position == Position::FollowCursor
|
||||
&& last_position != cursor_position =>
|
||||
{
|
||||
*state = State::Open { cursor_position };
|
||||
shell.request_redraw();
|
||||
}
|
||||
(State::Open { .. }, None) => {
|
||||
*state = State::Idle;
|
||||
shell.invalidate_layout();
|
||||
}
|
||||
(State::Open { .. }, Some(_)) | (State::Idle, None) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +336,7 @@ where
|
|||
translation,
|
||||
);
|
||||
|
||||
let tooltip = if let State::Hovered { cursor_position } = *state {
|
||||
let tooltip = if let State::Open { cursor_position } = *state {
|
||||
Some(overlay::Element::new(Box::new(Overlay {
|
||||
position: layout.position() + translation,
|
||||
tooltip: &mut self.tooltip,
|
||||
|
|
@ -361,6 +401,9 @@ enum State {
|
|||
#[default]
|
||||
Idle,
|
||||
Hovered {
|
||||
at: Instant,
|
||||
},
|
||||
Open {
|
||||
cursor_position: Point,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue