Introduce a new Tooltip
element and a with_tooltip
helper
This commit is contained in:
parent
94fc28b29d
commit
982de971fa
5 changed files with 112 additions and 31 deletions
|
@ -1,38 +1,77 @@
|
|||
use super::{ContainerStyle, Element, ElementBox};
|
||||
use crate::{
|
||||
geometry::{rect::RectF, vector::Vector2F},
|
||||
json::{json, ToJson},
|
||||
ElementStateHandle, LayoutContext, PaintContext, RenderContext, SizeConstraint, View,
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
rc::Rc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use super::{Element, ElementBox, MouseEventHandler};
|
||||
use crate::{
|
||||
geometry::{rect::RectF, vector::Vector2F},
|
||||
json::json,
|
||||
ElementStateHandle, LayoutContext, PaintContext, RenderContext, SizeConstraint, Task, View,
|
||||
};
|
||||
|
||||
const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(500);
|
||||
|
||||
pub struct Tooltip {
|
||||
state: ElementStateHandle<TooltipState>,
|
||||
child: ElementBox,
|
||||
style: ContainerStyle,
|
||||
text: String,
|
||||
tooltip: Option<ElementBox>,
|
||||
state: ElementStateHandle<Rc<TooltipState>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TooltipState {}
|
||||
struct TooltipState {
|
||||
visible: Cell<bool>,
|
||||
position: Cell<Vector2F>,
|
||||
debounce: RefCell<Option<Task<()>>>,
|
||||
}
|
||||
|
||||
impl Tooltip {
|
||||
pub fn new<T: View>(
|
||||
id: usize,
|
||||
child: ElementBox,
|
||||
text: String,
|
||||
tooltip: ElementBox,
|
||||
cx: &mut RenderContext<T>,
|
||||
) -> Self {
|
||||
Self {
|
||||
state: cx.element_state::<Self, _>(id),
|
||||
child,
|
||||
text,
|
||||
style: Default::default(),
|
||||
}
|
||||
}
|
||||
let state_handle = cx.element_state::<TooltipState, Rc<TooltipState>>(id);
|
||||
let state = state_handle.read(cx).clone();
|
||||
let tooltip = if state.visible.get() {
|
||||
Some(tooltip)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let child = MouseEventHandler::new::<Self, _, _>(id, cx, |_, _| child)
|
||||
.on_hover(move |position, hover, cx| {
|
||||
let window_id = cx.window_id();
|
||||
if let Some(view_id) = cx.view_id() {
|
||||
if hover {
|
||||
if !state.visible.get() {
|
||||
state.position.set(position);
|
||||
|
||||
pub fn with_style(mut self, style: ContainerStyle) -> Self {
|
||||
self.style = style;
|
||||
self
|
||||
let mut debounce = state.debounce.borrow_mut();
|
||||
if debounce.is_none() {
|
||||
*debounce = Some(cx.spawn({
|
||||
let state = state.clone();
|
||||
|mut cx| async move {
|
||||
cx.background().timer(DEBOUNCE_TIMEOUT).await;
|
||||
state.visible.set(true);
|
||||
cx.update(|cx| cx.notify_view(window_id, view_id));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.visible.set(false);
|
||||
state.debounce.take();
|
||||
}
|
||||
}
|
||||
})
|
||||
.boxed();
|
||||
Self {
|
||||
child,
|
||||
tooltip,
|
||||
state: state_handle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +85,9 @@ impl Element for Tooltip {
|
|||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, cx);
|
||||
if let Some(tooltip) = self.tooltip.as_mut() {
|
||||
tooltip.layout(SizeConstraint::new(Vector2F::zero(), cx.window_size), cx);
|
||||
}
|
||||
(size, ())
|
||||
}
|
||||
|
||||
|
@ -57,6 +99,13 @@ impl Element for Tooltip {
|
|||
cx: &mut PaintContext,
|
||||
) {
|
||||
self.child.paint(bounds.origin(), visible_bounds, cx);
|
||||
if let Some(tooltip) = self.tooltip.as_mut() {
|
||||
let origin = self.state.read(cx).position.get();
|
||||
let size = tooltip.size();
|
||||
cx.scene.push_stacking_context(None);
|
||||
tooltip.paint(origin, RectF::new(origin, size), cx);
|
||||
cx.scene.pop_stacking_context();
|
||||
}
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
|
@ -80,8 +129,7 @@ impl Element for Tooltip {
|
|||
) -> serde_json::Value {
|
||||
json!({
|
||||
"child": self.child.debug(cx),
|
||||
"style": self.style.to_json(),
|
||||
"text": &self.text,
|
||||
"tooltip": self.tooltip.as_ref().map(|t| t.debug(cx)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue